kelly / node-i2c

Node.js native bindings for i2c-dev. Plays well with Raspberry Pi and Beaglebone.
Other
216 stars 91 forks source link

Segmentation Fault Reading MCP3424 A/D Converter #13

Open ghost opened 11 years ago

ghost commented 11 years ago

I am getting a 'segmentation fault' with the below code running on a BeagleBone Black (node version v0.8.22) communicating with a MCP3424 digital/analog converter:

    var i2c = require('i2c');       
    var address = 0x6a;
    var wire = new i2c(address, {device: '/dev/i2c-1', debug: false}); 
    var semaphore = true;
    setInterval(function() {
        observeCallback();
    }, 1);
    function observeCallback() {
        if (semaphore === true) {
            semaphore = false;
            wire.readBytes(0x80, 4, function(err, buffer) {
                observe(buffer);
                semaphore = true;
            });
        }
    }
    function observe(buffer) {
        var voltageIn = (buffer[0] << 8) + buffer[1];
        voltageIn = voltageIn / 2048;
    }

Obviously this is a pared down version of the code. It will generally fail within a single digit number of minutes but sometimes it will take longer.

This code is a key element of a pro-bono project that I am doing for a non-profit so any help would be appreciated!

critch commented 11 years ago

ThamesWill, In my similar problem, I found that you just have to fully avoid the readBytes method. You need to rewrite the function to only use ReadByte. Such as

function observeCallback() {
        if (semaphore === true) {
            semaphore = false;

            // tell the device to send us the data
            wire.writeByte(0x80, function(err){});

            // i + 1 bytes to read  
            i = 3;
            // replacement buffer
            buff = 0;

            read_byte = function(){
                wire.readByte(function(err,res){
                    buff = buff<<8 + res;
                 }
                 if(i--){
                    // more to read
                    read_byte();
                 }else{
                     // done reading, call to closing
                     observe(buff);
                 }
            }

            // prime the loop
            read_byte();
      }
}
ghost commented 11 years ago

Excellent feedback. I jumped on this and got some initial good news...then some bad news. The good news is that it does not crash! The bad news is that I only ever get the first of four bytes that the ADC generates! I dump each byte as I get them and as I change the voltage in I can see the output change...but only the highest order byte! I suspect that there is something I need to do to get this to work but I am not seeing what from looking at the device data sheet.

Do you have any ideas? Am I doing something boneheaded? Here is the code pretty much exactly as you suggested:

    wire.writeByte(0x90, function(err){});
    readByte();
    function readByte() {
        wire.readByte(function(err, res) {
            console.log(res);
            if(i++ < 3){
                readByte();
            }
        });
    }

On another front, I also tried solving my problem using the wire.stream command from the library. Good news and bad news here as well. The good news is that it also does not seem to crash. The bad news is that control never returns from the wire.stream command to my script! I get good readings but it makes it a little hard to move on from getting the readings to doing something with them! I guess I could setup a background process but I don't think this is how it should work!

Here is my code for the wire.stream variant:

    var i2c = require('i2c');       
    var address = 0x6a;
    var wire = new i2c(address, {device: '/dev/i2c-1', debug: false}); 

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

    console.log("-----Starting stream");
    wire.stream(0x90, 4, 1);
    console.log("-----Started stream ");

    function observeCallback(data) {
        observe(data.data);
    }

    function observe(buffer) {
        var voltageIn = (buffer[0] << 8) + buffer[1];
        voltageIn = voltageIn / 2048;
    }

Thanks again for the first recommendation...hopefully I am doing something boneheaded.

Will

ghost commented 10 years ago

It is a shame that this library is not supported. I don't have the right skills to do so myself though at a future point I might take a stab at a rewrite that would produce a library that parallels the Wire interface in Arduino land. Is there any chance that someone out there could help in the meantime?

x3itsolutions commented 10 years ago

Hey Thomas, i've written a module for mcp3424, i don't know if you still need it, but you can download it from here: https://github.com/x3itsolutions/mcp3424 I haven't tested so much, please try it and let me know, if you've problems with my module.

rzr commented 3 years ago

Is this issue still relevant on latest @abandonware's fork ?

https://libraries.io/npm/@abandonware%2Fi2c/usage

Relate-to: https://github.com/kelly/node-i2c/issues/97