Teaching: Measurement and Instrumentation
After graduating at UBC I got the opportunity to teach a course called Measurement and Instrumentation, a core 3rd year course in Mechanical Engineering. The course covered all the steps in getting data from a physical system into a computer: sensor selection, analog signal processing, and readout.
As a lab component I supplied students with a PCB (designed by my lab-mate) that spits out data from a 3-axis accelerometer. Their task was to write a driver in Visual C# that let them read in the data, then use the data to do something cool.
The microprocessor on the PCB (an MSP430, the workhorse of our research lab) was programmed to transmit data through a UART at 128000 baud. The package we chose was simply [255, XAcceleration, YAcceleration, ZAcceleration], where the three data bytes were confined to [0,254] in value.
Many students struggled writing their drivers, as there were a few complications.
The second common trip-up was building a functional state machine. The data coming in from the accelerometer is unlabelled; if you just look at one byte there's no way to know which axis it represents. We solve this problem by knowing a) the pattern of incoming data package, and b) which axis we read last. When the serial port is first connected we wait to see 255, then we know the next byte will be the X-axis data, and the subsequent one will be the Y-axis, etc.
The final problem was lag. Roughly 1400 useful bytes/second are being sent across the cable, and if you use a first-in-first-out queue and don't process the data fast enough, you'll end up with overflow. Some projects would work OK immediately after loading, then get progressively more and more sluggish as time wore on before eventually crashing altogether. The simple fix was making sure each 'use the data' step used all of the data in the queue, not just the first available byte.
As an example project, I used the accelerometer PCB to control a game. When the person holding the accelerometer PCB makes a certain gesture, for example a punch up and to the left, that gesture will produce a characteristic combination of X,Y, and Z accelerations. Our punch up and to the left gives a peak [X, Y, Z] accelerations of greater than [1.3,-1,2] g. My C# program continually looks for these gesture signatures, and when it finds one, it sends the appropriate keystroke to the gameplay window using the SendKeys function.