Evolution of a Blog

This blog has evolved as I have as a maker. It starts at the beginning of my journey where I began to re-tread my tires in the useful lore of micro electronics and the open-source software that can drive them. While building solutions around micro-electronics are still an occasional topic my more recent focus has been on the 3D Printing side of making.

Wednesday, October 30, 2013

Implementing an I2c Workaround

The i2c library that I am using (kelly/node-i2c) works great...but...after some period of observations it causes node.js to fail with a segmentation fault.   I am not sure this is a problem with the base library or with how I am using it with the Analog Digital Converter that I am using.   I suspect that it is the latter but I don't have the technical skills to diagnose the problem.  Given the former I decided to implement a workaround as described below.

wireServer = require('child_process').fork('wireServer.js', 
   [global.config.i2cDevice, global.config.i2cAddress, global.config.i2cCommand]);
wireServerPid = wireServer.pid; 
utilities.trace(false, "test - wireServer started as PID " + wireServerPid);
Since failures generally only occurred after a period of time I decided to create a background process that could be started for the period of observation and then killed until the next period is started.  


eventEmitter.on('startObserve', function(message){
    wireServer.send({"message":"init", 
        "i2cDevice":global.config.i2cDevice,
        "i2cAddress":global.config.i2cAddress,
        "i2cCommand":global.config.i2cCommand});
    // Each message will be a voltage reading that we then pass to the below routine
    wireServer.on('message', function (message) {
        observe(message.voltageIn);
    });
});
I am using an event to start the observation period by sending a message to the wireServer process started above.   The message tells the server where to look for the I2c device.  Once this is done I setup a handler for readings coming back from the server.



execSync('kill ' + wireServerPid);
utilities.trace(false, "test - Current wireServer running as PID " + wireServerPid + " killed")
Once the I2c interface is started node will no longer respond to messages sent to the background process!   This means I have no way of asking it to die gracefully.  That being missing I use a little less graceful approach and kill it at the O/S level.

eventEmitter.emit('startObserve', '');
Finally we launch the observation perio.

The background process that the above launches, and then communicates with, is shown below:


// Load the library we need to get voltage measurements using i2c
var i2c = require('i2c');       
var i2cDevice = "/dev/i2c-" + process.argv[2];
var i2cAddress = process.argv[3];
var i2cCommand = Number(process.argv[4]);
// Convert the i2c address from character to hex
i2cAddress = parseInt("0x" + i2cAddress);
var wire = new i2c(i2cAddress, {device: i2cDevice, debug: false}); 
var seq = 0;

wire.on('data', function(data) {
    observe(data.data);
});

// Look for an init message from test to start our observations
process.on('message', function (message) {    
    wire.stream(i2cCommand, 4, 3);
});

// Take a voltage reading and send it on to test
function observe(buffer) {
    var voltageIn = 0;
    voltageIn = (buffer[0] << 8) + buffer[1];
    // Did we get a negative value?  If so make it a zero.
    if (voltageIn > 2048) {
        voltageIn = 0;
    }
    else {
        voltageIn = voltageIn / 2048;
    }
    if (seq == 5000 || seq === 0) {
        console.log(datetimeStamp() + " - wireServer - active");
        seq = 1;
    }
    process.send({seq:seq++, voltageIn: voltageIn });    
}

No comments:

Post a Comment