Wednesday, October 30, 2013

Integrating a Joystick via I2c with a GPIO Detected Button - Software

The code used to integrate with the Joystick hardware described by the previous post is shown below.   Note that the entire working demo is avalable on GitHub.
  1. Bring in the "i2c" ibrary (Kelly / Node-I2C) used to interface with I2C devices such as our Analog Digital Converter (ADC).  I have configured the device to be on address 0x6A and I know that it is /dev/i2c-1 from using i2cdetect
  2. Bring in the "onoff" library (fivdi / onnoff) that we will use to detect the pressing of the select button on the Joystick.  Note that bonescript on the BeagleBone Black would accomplish this with an interupt but since I am doing my demo on an Raspberry Pi I pulled in the onoff library.
  3. Bring in the "events" library (node events) that I use to poll for I2c and Select Button states.
  4. React to an event requesting a read of the Y axis.  Use the I2c library to read 4 bytes in response to the command "0xB0" which is a request to read 12 bits of data from channel 2.
  5. React to an event requesting a read of the X axis.  Use the I2c library to read 4 bytes in response to the command "0xD0" which is a request to read 12 bits of data from channel 3.
  6. The observe routine translates the buffer returned from the I2c library into a usable voltage reading and stashes it in one of our two axis variables
  7. The "startObserve" event triggers a repeating event that will do our actuall polling for the Joystick state.  It launches an interval event every 25 ms that toggles between the X and Y axis getting an update for each every 50 ms.   The current state of the axis's are sent to the client every cycle.   The state of the joystick select button is also checked every iteration and if it is depressed a snapshot is sent to the client for the current X and Y axis positions.
  8. Once all the event handlers have been registered we kick things off by emitting startObserve!
(1) var i2c = require('i2c');
var address = 0x6A;
var wire = new i2c(address, {device: '/dev/i2c-1', debug: false});
(2) var Gpio = require('onoff').Gpio,
    button = new Gpio(4, 'in', 'both');
button.debounceTimeout = 1000;
(3) var events = require('events');
var eventEmitter = new events.EventEmitter();
(4) eventEmitter.on('measureY', function(message){
    wire.readBytes(0xB0, 4, function(err, res) {
        observe("Y", res);
    });
});
(5) eventEmitter.on('measureY', function(message){
    wire.readBytes(0xD0, 4, function(err, res) {
        observe("Y", res);
    });
});
(6) function observe(xy, buffer) {
    var voltageIn = (buffer[0] << 8) + buffer[1];
    if (voltageIn > 2048) {
        voltageIn = 0;
    }
    else {
        voltageIn = voltageIn / 2048 * 5 * 22.6;
    }
    if (xy == "X") {
        voltageInX = voltageIn
    }
    else {
        voltageInY = voltageIn
    }
}
(7)
eventEmitter.on('startObserve', function(message){
    var toggle = "X";
    intervalId = setInterval(function() {
        if (toggle == "X") {
            eventEmitter.emit('measureX', '');
            toggle = "Y";
        }
        else {
            eventEmitter.emit('measureY', '');
            toggle = "X";
        }
        plot();
        if (button.readSync() == 1) {
            console.log("Sent " + voltageInX + " - " + voltageInY);
            socket.emit('buttonPressed', { dp1: voltageInX, dp2: voltageInY });
            buttonPressed = false;
        }
    }, 25);
(8) eventEmitter.emit('startObserve', '');

No comments:

Post a Comment