So I have been using the loststone prototype for about a month, I have only been using my store bought mouse when I screw something up ūüôā

Aside from the occasional physical issue, mainly the buttons falling off, I have only been having one issue. Sensitivity. If I set the CPI high enough(ex 4500) for the courser to travel the full length of the monitor with a reasonable spin of the ball, It is next to impossible to move the courser over a specific character on the first try. Some times even the 4th or 5th try, VERY annoying. Setting the CPI low enough(ex 540) for really nice small movements and it takes multiple turns of the ball to move the full length of the screen.

I originally thought that some very complicated math would be required to solve this issue. So I figured I would start out small to get an idea of what I needed to do to accelerate the courser across the screen when moved fast enough and yet still allow small intricate movements. Much to my amazement the first equation I came up with did exactly what I needed it to do.

After some tweaking of the denominator and CPI values I came up with the CPI at 540 and the following equation.

f(x) = ( |x| / 40 + 1) * x

f(x) = x
f(x) = ( |x| / 60 + 1) * x
f(x) = ( |x| / 40 + 1) * x
f(x) = ( |x| / 20 + 1) * x

The red plot is the raw sensor input(both x and y coordinates). The rest are different values for the denominator, I am currently using the blue one.

One of the reasons this works so well is the way that rounding is done when casting a float to an int in C++. Well actually there is no rounding. For example if we solve for x = 6 we end up with 1.15 * 6 = 6.9 which when cast to and int is simply 6. When x = 7 we end up with 1.175 * 7 = 8.225 which then becomes 8. So the 6 smallest movements are not actually changed. And when the values do start changing it is a smooth progression to larger numbers.

Share Button

dc_power_supply

I have been meaning to get a DC power supply for my work bench. In the passed I have used computer power supplies in a pinch. I figured with a little tweaking it would make a pretty good general DC power supply. I attached a switch i had lying around to pins 15 and 16 (pin-outs) and then attached pins 1, 2, 4, 6, 10, 11, 17 and 18 to a dual row terminal strip. The terminal strip I had has 8 positions so I figured I would do 2 of each voltage, 3.3V, 5V, 12V and GND. I didn’t bother with the -12V

So far it is working well. Especially since it cost me $0.

The folks at Dangerous Prototypes have a really nice kit you can get at seedstudio.com. Even though I just through this together I will still probably get one. They put in some resetable fuses which is nice. You also wont need to chop up the cables. And at $14 you cant go wrong.

Share Button

The HID report descriptor of the USBMouse interface is functional but minimalistic. I spent some time looking into HID descriptors and came up with a new descriptor which adds support for the following.

  1. Horizontal scrolling.
  2. A fourth and fifth mouse buttons (Forward and back by default).
  3. 16bit X and Y values

I don’t think I even like horizontal scrolling, maybe I just have to get used to it. Not sure what i am going to use the extra buttons for but there there if I need them. The 16bit ¬†X and Y values eliminate the need for some nasty logic that broke up X and Y values larger/smaller than 127/-127 into multiple reports. I was planning on redoing that logic, I don’t think it was doing exactly what I wanted it to do. That would have been some nasty code though. By changing it to support 16bit values a single report can hold any number the¬†ADNS-9500 can output( 32767/-32768) I still don’t have the scroll multiplier report. I don’t think I need that if I want the numbers to be larger I can always just bump up the CPI when in scrolling mode.

 

The new HID report Descriptor is as follows.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
//
// Wheel Mouse - simplified version - 5 button, vertical and horizontal wheel
//
// Input report - 6 bytes
//
//     Byte | D7   D6   D5   D4      D3      D2      D1      D0
//    ------+---------------------------------------------------------------------
//      0   |  0    0    0    Forward  Back    Middle  Right   Left (Buttons)
//      1   |                       X High
//      2   |                       X Low
//      3   |                       Y High
//      4   |                       Y Low
//      5   |                   Vertical Wheel
//      6   |               Horizontal (Tilt) Wheel
//
// Feature report - 1 byte
//
//     Byte | D7   D6   D5   D4   |  D3      D2  |   D1      D0
//    ------+---------------------+--------------+----------------
//      0   |  0    0    0    0   |  Horizontal  |    Vertical
//                                    (Resolution multiplier)
//
// Reference
//    Wheel.docx in "Enhanced Wheel Support in Windows Vista" on MS WHDC
//    http://www.microsoft.com/whdc/device/input/wheel.mspx
//
static uint8_t reportDescriptor[] = {
    0x05, 0x01,        // USAGE_PAGE (Generic Desktop)
    0x09, 0x02,        // USAGE (Mouse)
    0xa1, 0x01,        // COLLECTION (Application)
    0x09, 0x02,        //   USAGE (Mouse)
    0xa1, 0x02,        //   COLLECTION (Logical)
    0x09, 0x01,        //     USAGE (Pointer)
    0xa1, 0x00,        //     COLLECTION (Physical)
                       // ------------------------------  Buttons
    0x05, 0x09,        //       USAGE_PAGE (Button)
    0x19, 0x01,        //       USAGE_MINIMUM (Button 1)
    0x29, 0x05,        //       USAGE_MAXIMUM (Button 5)
    0x15, 0x00,        //       LOGICAL_MINIMUM (0)
    0x25, 0x01,        //       LOGICAL_MAXIMUM (1)
    0x75, 0x01,        //       REPORT_SIZE (1)
    0x95, 0x05,        //       REPORT_COUNT (5)
    0x81, 0x02,        //       INPUT (Data,Var,Abs)
                       // ------------------------------  Padding
    0x75, 0x03,        //       REPORT_SIZE (3)
    0x95, 0x01,        //       REPORT_COUNT (1)
    0x81, 0x03,        //       INPUT (Cnst,Var,Abs)
                       // ------------------------------  X,Y position
    0x05, 0x01,        //       USAGE_PAGE (Generic Desktop)
    0x09, 0x30,        //       USAGE (X)
    0x09, 0x31,        //       USAGE (Y)
    0x16, 0x00, 0x81,  //       LOGICAL_MINIMUM (-32768)
    0x26, 0xff, 0x7f,  //       LOGICAL_MAXIMUM (32767)
    0x75, 0x10,        //       REPORT_SIZE (16)
    0x95, 0x02,        //       REPORT_COUNT (2)
    0x81, 0x06,        //       INPUT (Data,Var,Rel)
    0xa1, 0x02,        //       COLLECTION (Logical)
                       // ------------------------------  Vertical wheel res multiplier
    0x09, 0x48,        //         USAGE (Resolution Multiplier)
    0x15, 0x00,        //         LOGICAL_MINIMUM (0)
    0x25, 0x01,        //         LOGICAL_MAXIMUM (1)
    0x35, 0x01,        //         PHYSICAL_MINIMUM (1)
    0x45, 0x04,        //         PHYSICAL_MAXIMUM (4)
    0x75, 0x02,        //         REPORT_SIZE (2)
    0x95, 0x01,        //         REPORT_COUNT (1)
    0xa4,              //         PUSH
    0xb1, 0x02,        //         FEATURE (Data,Var,Abs)
                       // ------------------------------  Vertical wheel
    0x09, 0x38,        //         USAGE (Wheel)
    0x15, 0x81,        //         LOGICAL_MINIMUM (-127)
    0x25, 0x7f,        //         LOGICAL_MAXIMUM (127)
    0x35, 0x00,        //         PHYSICAL_MINIMUM (0)        - reset physical
    0x45, 0x00,        //         PHYSICAL_MAXIMUM (0)
    0x75, 0x08,        //         REPORT_SIZE (8)
    0x81, 0x06,        //         INPUT (Data,Var,Rel)
    0xc0,              //       END_COLLECTION
    0xa1, 0x02,        //       COLLECTION (Logical)
                       // ------------------------------  Horizontal wheel res multiplier
    0x09, 0x48,        //         USAGE (Resolution Multiplier)
    0xb4,              //         POP
    0xb1, 0x02,        //         FEATURE (Data,Var,Abs)
                       // ------------------------------  Padding for Feature report
    0x35, 0x00,        //         PHYSICAL_MINIMUM (0)        - reset physical
    0x45, 0x00,        //         PHYSICAL_MAXIMUM (0)
    0x75, 0x04,        //         REPORT_SIZE (4)
    0xb1, 0x03,        //         FEATURE (Cnst,Var,Abs)
                       // ------------------------------  Horizontal wheel
    0x05, 0x0c,        //         USAGE_PAGE (Consumer Devices)
    0x0a, 0x38, 0x02,  //         USAGE (AC Pan)
    0x15, 0x81,        //         LOGICAL_MINIMUM (-127)
    0x25, 0x7f,        //         LOGICAL_MAXIMUM (127)
    0x75, 0x08,        //         REPORT_SIZE (8)
    0x81, 0x06,        //         INPUT (Data,Var,Rel)
    0xc0,              //       END_COLLECTION
    0xc0,              //     END_COLLECTION
    0xc0,              //   END_COLLECTION
    0xc0               // END_COLLECTION
};

White paper from Microft with a bref description and some examples.
http://www.microsoft.com/whdc/device/input/wheel.mspx

Many usfuall doc’s and the “HID Description tool” its not a very user friendly tool but helps with coming up with the hex codes.
http://www.usb.org/developers/hidpage/

This is a wonderful tutorial on HID descriptors short but nice explanations and examples.
http://www.frank-zhao.com/cache/hid_tutorial_1.php

USB in a nutshell? That’s one big nutshell! Well actually its barley scratching the surface but this is usually my goto when i want to know something.
http://www.beyondlogic.org/usbnutshell/usb1.shtml

Share Button

DSC_0251_smallSo I have been using this as my primary pointing device for about a week now. I have changed the button position and stylish clay palm rest close to 30 times. There still not exactly where I want them but its close enough where I can now start figuring out how I’m going to mount the buttons.

The motion of the call is working better than I ever expected it would. Its as smother than any trackball I have ever used. The Z-axis is still a bit wonky for some apps. Currently when you press the left bottom “button” it changes the CPI from 5040(max) down to zero(min) and uses the X-axis value as the Z-axis value

Originally I had set up a “PinDetect” object for each button to debounce them. ¬†This worked fairly well but no matter what values I changed the¬†frequency¬†and¬†sampling¬†numbers to I could¬†always¬†get¬†either¬†clicks that did not register because i clicked to quickly or clicks that¬†registers¬†more than once because the bounce was to long. Even if i could get it working as i wanted to as a¬†programmer¬†I have never been a fan of polling. Its generally a waist of¬†resources¬†and in some cases lead to unexpected behavior¬†especially¬†when there are going to be 6 or so polling so tightly(~20ms). ¬†I just don’t like breaking the program flow like that. I realize the MCU is¬†complete¬†overkill for a trackball and I have more than enough ticks to spare.

Because of my aversion to polling like that on my last Mouser purchase I added a MC14490PG from ON Semiconductor.  The chip is ludicrously expensive at $4.77, hell the LPC11U24  MCU was only $3.92. However it was easy to wire up and in my opinion a more elegant solution, and so far I have not seen any unwanted behavior.  There where few other debounce solutions I read up on and may test out, but for now the MC14490PG it is.

Though I would still like to get my hands on an¬†oscilloscope. It kills me not being able know what is actually going on when one of the buttons is pressed. If I knew how long, on average these switches¬†bounced¬†for I might have been able to fine tune the “PinDetect” objects better

On another note I came¬†across¬†Dialight,¬†which¬†among¬†other things makes SMD LED‘s and light pipes, lots of them! (What can I say odd things¬†excite¬†me ūüėÄ ), Mouser/Digikey even have them in small¬†quantities. Not even sure if I am going to do anything more than standard 5mm/2.5mm round LED’s but its nice to know the option is there.

Share Button

pen_tips Functional prototype
I could not find any type of bearing or other material that would give the billiard ball a nice smooth motion. After describing what i was doing to a co-worker without success I told them I needed something like a ballpoint pen tip reverse tripod, thing. There was a short pause and then I said well I guess I will go try that, and it worked.

It works shockingly well actually. There are actually quite a few pen tip types. I picked 5 different sizes. I was surprised that the tips can simply be pulled off with a pair of pliers with very little force. To remove the ink I soaked them in acetone. I tried a half dozen different things I had around the house and the acetone worked by far the best. It took a few days changing out the acetone but in the end there is almost no ink left they they are still just as smooth as they where before. From left to right 0.5mm, 0.7mm, 1.0mm, 1.2mm and 1.6mm.

For now I am using the 1.2mm. I really did not notice any different in motion between any of them. I chose the 1.2mm tip because it is by far the shortest in length and the 1.2mm ball gives me enough play that the billiard ball does not hit rim holding the ball in place. My PVC reducer and drilled holes are not exactly precise when your getting down to sub milometer tolerances.

So there it is. A working prof of concept. The next step is to get it all working without using the mbed.

Share Button

Custom PCB from OSHPark

Well after a very long break I finally ordered a custom PCB from  OSHPark. I am very pleased with the result, i needed to manually cut the board because had my cutouts on the wrong layer.  I am most impressed with the fact that I soldered on a MOSFET with .5mm pad the first try! After putting all the components on the board and rewiring the breadboard it worked. Hell yes. My code was all wonky and its completely unusable but the hardware is functioning.

On to some code clean up.

 

 

Share Button

The LPC 1343 is a nice chip and the dev board works well. Unfortunately¬†this chip is¬†basically¬†ignored by LCP and the community is just not there. I just don’t have time to get a USB stack working with this chip. Because of this i decided to go with the mbed LPC11u24. mbed has an outstanding user community including an awsome cookbook¬†page¬†which¬†includes a USB stack¬†that has wonderful examples. Hell someone even wrote some interface code for the ADNS-9500, which to be¬†honest¬†i was somewhat¬†disappointed¬†at, I was looking¬†foreword¬†to doing that myself(still might).

Share Button

Falure:

To make the base for the ball of my prototype trackball I went to Homedpot and got 3″ to 1.5″ PVC¬†bushing and a 3mm Teflon rod from McMaster.com (Damn that’s an awesome site) and assembled them like you see in the picture. This was a complete failure. There is some serous resistance when moving the billiard ball. I tried flat and pointed Teflon nubs with the same result. I am not sure what I am going to use in its place but I am thinking a hard smooth metal of some sorts. Its funtional so i am leaving it the way it is for now.

 

 Problem:

It never occurred to me to check the pitch of the ADNS-9500, which is a problem since its 1.78mm  and almost most everything development or prototype related is 2.54 mm.

hmmm…

Share Button

Had an odd issue a few weeks back. A process was not behaving as it should. After doing some digging I found out that the the only way it could behave like it was, was if an environment variable was set incorrectly. The odd part was that /proc/$$/environ was showing that it was set correctly.

After doing some research and playing with gdb a bit (thankfully this was a test environment) I found out that /proc/$$/environ does not give you what you think it gives you!

on to the why.

When a process starts the create_elf_tables function gets called. This function creates and populates a mm_struct data structure. This structure, among other things, contains env_start and env_end, which are the memory address of the begging and end of the environment variable data in the stack.

To get the environment variable information the proc file system reads mm_struct to get he start and end values where the environment variables are located. This is done in the environ_read function.

So why is this not giving me what i want? Well when the process is created in memory there is no buffer in the stack to add more environment variables or to make existing environment variables longer.  So when the process creates a new environment variable or modifies an existing one the environment variables get moved to the heap and the environ symbol is changed to point to the new location. The mm_struct however, is not changed. Which is not necessarily a bad thing but since the proc file system looks at the mm_struct you get the environment at execution time and not the current environment.

this behavior is simple to see.

1
2
3
4
5
6
7
$ echo $FOO

$ cat /proc/$$/environ |tr '\0' '\n' |grep FOO
$ export FOO=BAR
$ echo $FOO
BAR
$ cat /proc/$$/environ |tr '\0' '\n' |grep FOO

For the hell of it I was playing around with ptrace and made an small program that attaches to a process parses the elf structure, finds the environ symbol and then prints out the
current environment variables. The code is crap and the thing barely works(well sometimes it barely works) I was just fooling around. Its allot easier (and safer) to start up GDB and do a “show environ“.

Share Button

It¬†doesn’t actually do anything but I can plug it into a computer and it registers as a USB device. The computer has no idea what to do with it but it at least knows it exists. I know I wired at least two parts worse then correct but better than wrong, since it seems to be working. I need to read up on this a bit more.

As far as the code, I used stock example code for a generic HID from NXP. I literally did not change a single character of code and loaded it with the LPCExpresso IDE in Windows. It actually says “LPC 13XX USB HID” in the lsusb output.

Its not much but i accomplished what i set out to do yesterday, which was simply to see if i could get a computer to see something coherent from this dev board.

Share Button