How to hack a theremin sensor

From Hackers & Designers
Revision as of 15:37, 22 November 2015 by JBG (talk | contribs)

How to hack a sensor

by James Bryan Graves

Due to lack of documentation for the theremin sensor output the following steps were employed to hack the protocol. Although details are specific to the theremin sensor, similar methods could be used to hack other protocols.

Step 1

The sensor was attached to Arduino UNO, and the sensorReader5 sketch supplied by Andrey Smirnov and available on Github was uploaded to the Arduino.

Step 2

Note the baud rate in the script was set to 57600. A script was created, in this case with Processing to read the a computer's serial port at the same baud rate. The next step was to print each incoming byte.

Step 3

Look for repetitions. Here it was noticed on byte was repeated, 63, every 8 bytes. Therefore the assumption can be made the packet size is 8 bytes. So, everytime a 63 is seen it can be assumed it is a new packet from the sensor.

Step 4

What does the sensor do? Here, a theremin sensor, it is telling us about distance (capacitance) between a conductive body and the sensor. So, by moving closer and further away from the sensor we could look for highly dynamic values in the packets. I this case it turned out to be byte 5 and 7, indexes 4 and 6 in 0 based arrays. Since there are two dynamic values, we can assume they should be combined, there are generally 2 ways to do this BIG and Little Endian. So try both. Here it turned out to be Little Endian.

Step 5

Do something "useful". Once we have the changing values, we could create an algorithm to utilize the values. In this Processing script we simply grow/shrink a text size.


   import processing.serial.*;
   
   Serial ser;
   
   int width = 320;
   int height = 240;
   
   void setup() {
     size(width, height);
     println(Serial.list());
     ser = new Serial(this, Serial.list()[3], 57600);
   }
   
   int count = 0;
   Boolean process = false;
   
   int[] packet = new int[8];
   
   void draw() {
     background(0);
     fill(255);
 
     while (ser.available() > 0) {
       int inByte = ser.read();
       println(inByte);
       if(inByte == 63) {
         if(process) {
           int lsb = packet[4];
           int msb = packet[6];
           int combined = (msb << 8 ) | (lsb & 0xff);
           int size = combined / 100;
           //println("SIZE: " + size);
           //println(packet);
           if(size > 0) {
             textSize(size);
           }
           textAlign(CENTER, CENTER);
           text("WORD", width/2, 60);
         }
         // Okay we can start looking at packets now - JBG
         process = true;
         count = 0;
       }
       packet[count] = inByte;
       ++count;
     }  
   }