Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using I2C functions #28

Open
jadonk opened this issue Apr 25, 2018 · 6 comments
Open

Using I2C functions #28

jadonk opened this issue Apr 25, 2018 · 6 comments

Comments

@jadonk
Copy link
Member

jadonk commented Apr 25, 2018

From @colinbes on July 1, 2014 19:11

Maybe I am misunderstanding correct usage of I2C functions provided by bonescript but from what I understand, the correct usage is along the lines of

b.i2cOpen(PORT, PWR_CHIP);
b.i2cReadBytes(PORT, STATUS, 1, function(data){...})

I assume the thinking is that the ReadBytes is always preceded by the i2cOpen function within the same function scope. If the i2cOpen function was, for example, in static part of code, and the ReadBytes was in a function then you could end up with wrong results.

Example.

i2cOpen('/dev/i2c-1', 0x20);

function func1() {
  i2cReadBytes .....
}

In this case if any other function anywhere called i2cOpen and then you called func1() you'd be reading bytes of the last i2cOpen function.

Is there a way to use these functions similar to the way it is used in i2c which is basis for bonescript i2c functions? Where method returned by i2cOpen is used as 'parent' (sorry, can't think of right word to use) to ReadBytes call?

Just looking for direction, thanks

Copied from original issue: jadonk#90

@jadonk
Copy link
Member Author

jadonk commented Apr 25, 2018

From @colinbes on July 1, 2014 19:48

I am needing to periodically scan a particular i2c device (monitoring for powerfail). Per my above question I have call to i2cOpen just before i2cReadBytes in timer function. On running the code for a short period of time I get possible EventEmitter memory leak detected message. Seems to be caused by the i2cOpen function call. If I move this out the timer interval function then I don't get the error - looks like I need to close i2c somehow? Moving i2cOpen outside of the interval function would not be a solution as I am reading i2c devices in other areas of code.

var timer = setInterval(function() {
        b.i2cOpen(PORT, PWR_CHIP);
        b.i2cReadBytes(PORT, STATUS, 1, function(data){
  ...}, 2000);

Full error message

(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.
Trace
    at process.EventEmitter.addListener (events.js:160:15)
    at process.on.process.addListener (node.js:769:26)
    at new i2c (/usr/local/lib/node_modules/bonescript/node_modules/i2c/lib/i2c.coffee:32:15)
    at Object.m.doOpen (/usr/local/lib/node_modules/bonescript/iic.js:18:20)
    at Object.newFunction [as i2cOpen] (/usr/local/lib/node_modules/bonescript/my.js:234:31)
    at null.<anonymous> (/mnt/nfs/code/testpower.js:21:5)
    at wrapper [as _onTimeout] (timers.js:252:14)
    at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)

Appreciate your help.
Colin

@jadonk
Copy link
Member Author

jadonk commented Apr 25, 2018

From @Findus1 on September 16, 2014 11:16

I'm having the same problem. Did you find a solution?
The problem is trivially easy to produce:

var b = require('bonescript');
var port = '/dev/i2c-1';

for(var i = 0; i< 11; i++){
    b.i2cOpen(port, 0x70, {});
}

This produces a warning after 11 loops.
That means I can a use only 10 addresses on my I2C bus!

@jadonk
Copy link
Member Author

jadonk commented Apr 25, 2018

From @Findus1 on September 16, 2014 11:30

An update to that last post: it's not okay to just handle the warning.
You get a warning after 11 i2cOpen operations, then an error after 1012 operations.
Here's the test case:

var b = require('bonescript');
var port = '/dev/i2c-1';

for(var i = 0; i< 10000; i++){
    b.i2cOpen(port, 0x70, {});
    console.log("handles:", i);
}

Note that putting delays between i2cOpen() functions does not fix it.
Is there not an i2cClose() function in Bonescript, like there is for other I2c libraries?

@jadonk
Copy link
Member Author

jadonk commented Apr 25, 2018

From @Findus1 on September 16, 2014 16:1

If anyone else is banging up against this issue, the solution I found is to directly use the i2c library that Bonescript uses for i2c:
https://github.com/kelly/node-i2c
That lets you create an object for each device

var wire = new i2c(LED_ADDRESS, {device : '/dev/i2c-2'});

and write bytes to an address on it

wire.writeBytes(LED_BRIGHTNESS_ADDRESS, [0xFF], function(err) {});

as a bonus, it also numbers the i2c devices properly, so where Bonescript calls i2c-2 "i2c-1", the Kelly I2C library calls it "i2c-2"

@jadonk
Copy link
Member Author

jadonk commented Apr 25, 2018

From @colinbes on September 16, 2014 16:39

I have yet to find a solution, presently in order to move forward I am using an exec call to read i2c but would much prefer to not have to do this. I did try to use the i2c library but didn't come right.

How did you install and require i2c - I recall having an issue with one of these steps.

I actually prefer i2c implementation as the i2c object, 'wire' in your code above is bound to a physical device - I think this is much safer.

@jadonk
Copy link
Member Author

jadonk commented Apr 25, 2018

From @Findus1 on September 16, 2014 19:4

To install i2c, I followed the Beaglebone installation instructions on NPM.
https://www.npmjs.org/package/i2c
The Python installation produces errors, but the module installed without problems.

Like you, I also prefer the way i2c binds each instance to a device object. It is better than the way Bonescript's "open" command needs to be called before each device access (which means that if you are addressing several devices, you very soon exceed 11 "opens" to cause a warning, and eventually it crashes after 1012)

It's worth noting that the NPM i2c library also causes a warning when you create more than 11 devices - but unlike Bonescript, you don't need to open a new instance each time you send to a different device, because you can reuse device objects.

If anyone knows how to get around the 11 device limit in the i2c library, I'd like to know how.
Edit:
I've found that the I2C library doesn't set up the cape manager properly. After power-up, you need to issue a Bonescript Open, otherwise you get a cape manager error. After Bonescript has Opened the I2c port, you can use it with the i2c library.
I just put a Bonescript Open before each new i2c object. e.g.:

var b = require('bonescript');
var i2c = require('i2c');

b.i2cOpen('/dev/i2c-1', DEVICE_ADDRESS, {});    //needed to open the cape manager port
var wire = new i2c(DEVICE_ADDRESS, {device : '/dev/i2c-2', debug: false});
//note that Bonescript's '/dev/i2c-1' == i2c's '/dev/i2c-2' 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant