rwaldron / johnny-five

JavaScript Robotics and IoT programming framework, developed at Bocoup.
http://johnny-five.io
Other
13.26k stars 1.76k forks source link

RangeError with MPU6050 on Edison #678

Closed GrossDesignCo closed 9 years ago

GrossDesignCo commented 9 years ago

Hi there, I'm working on an Intel Edison (arduino breakout board) & running into the following error

RangeError: Trying to access beyond buffer length
    at checkOffset (buffer.js:582:11)
    at Buffer.readUInt8 (buffer.js:588:5)
    at Galileo.<anonymous> (/home/root/node_modules/galileo-io/lib/galileo.js:592:24)
    at wrapper [as _onTimeout] (timers.js:258:14)
    at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)

when I run anything, including the basic Accelerometer script (https://github.com/rwaldron/johnny-five/blob/master/docs/accelerometer-mpu6050.md)

Here's my modified version to incorporate the edison/gallileo-io plugin

var five = require("johnny-five");
var Edison = require("galileo-io");
var board = new five.Board({
  io: new Edison()
});

board.on("ready", function() {
  var accelerometer = new five.Accelerometer({
    controller: "MPU6050"
  });

  accelerometer.on("data", function(data) {
    console.log("raw", data);
  });
});

It doesn't look like this occurs on other platforms, could it be a specific quirk of the Edison?

dtex commented 9 years ago

@GrossDesignCo I imagine the reason nobody has chimed in yet is because you might be the first trying out that specific combination. I tried to take a look anyway and noticed that the line numbers in your trace don't seem to match up with the latest version (0.8.2). What version of Galileo-IO are you running? I don't know of any specific changes that would have made a difference for you, but it certainly couldn't hurt to upgrade.

rwaldron commented 9 years ago

@GrossDesignCo I will set this up locally and see what I can learn—will post back as soon as I know more :)

I imagine the reason nobody has chimed in yet

Wife's birthday weekend!

GrossDesignCo commented 9 years ago

Ah, that's interesting. I just updated from 0.8.1 to 0.8.2 and I'm getting the following notice now.

  NOTICE
  --------------------------------
  This OS image is no longer supported.
  Please upgrade to IoTKit Image with libmraa0 support.
  https://github.com/intel-iot-devkit/mraa/#installing-on-your-board
  --------------------------------

/home/root/node_modules/galileo-io/lib/galileo.js:44
if (Pin.IO.getPlatformType() === 2) {
           ^
TypeError: Cannot call method 'getPlatformType' of undefined
    at Object.<anonymous> (/home/root/node_modules/galileo-io/lib/galileo.js:44:12)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object.<anonymous> (/home/root/testing/testing-accel.js:2:14)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
GrossDesignCo commented 9 years ago

Thanks @rwaldron & @dtex!

It looks like I'll be updating my Edison's OS today. I'll follow up with the results.

rwaldron commented 9 years ago

It looks like I'll be updating my Edison's OS today.

Ah, yeah—Intel stopped supporting the older OS images.


I just tried your example above and the good news is that with the latest os image and Johnny-Five + Galileo/Edison-IO work as expected :)

GrossDesignCo commented 9 years ago

So I installed the latest Yocto image from intel and I'm still getting the same results. (well, a couple line numbers are different). I suppose my next guess is that I'm missing a dependency somewhere.

NOTICE
  --------------------------------
  This OS image is no longer supported.
  Please upgrade to IoTKit Image with libmraa0 support.
  https://github.com/intel-iot-devkit/mraa/#installing-on-your-board
  --------------------------------

/home/root/node_modules/galileo-io/lib/galileo.js:44
if (Pin.IO.getPlatformType() === 2) {
           ^
TypeError: Cannot call method 'getPlatformType' of undefined
    at Object.<anonymous> (/home/root/node_modules/galileo-io/lib/galileo.js:44:12)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object.<anonymous> (/home/root/testing/testing-accel.js:3:14)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
rwaldron commented 9 years ago

Can you tell me the output of this:

uname -a;
GrossDesignCo commented 9 years ago

Yep:

Linux First 3.10.17-poky-edison+ #1 SMP PREEMPT Fri Jan 30 14:16:35 CET 2015 i686 GNU/Linux
rwaldron commented 9 years ago

The error you're seeing can only be reached if the native bindings aren't installed. These are supposed to be present by default, but you can make sure by doing this:

echo "src mraa-upm http://iotdk.intel.com/repos/1.1/intelgalactic" > /etc/opkg/mraa-upm.conf
opkg update
opkg install libmraa0

Did you install johnny-five and galileo-io via npm or are you using the git repo? Recommend: npm install johnny-five galileo-io

GrossDesignCo commented 9 years ago

I used npm for JF & Galileo-io, just re-installed to see if I had anything out of date from a week ago.

I also installed libmraa0 with that same script yesterday & it seemed to work fine (edit: the installation seemed to work fine that is). After running it just now I got the message Package libmraa0 (0.6.1) installed in root is up to date.

I'm a little perplexed now, after reinstalling johnny-five and galileo-io the accelerometer script throws the original error

RangeError: Trying to access beyond buffer length
    at checkOffset (buffer.js:582:11)
    at Buffer.readUInt8 (buffer.js:588:5)
    at Galileo.<anonymous> (/home/root/node_modules/galileo-io/lib/galileo.js:585:24)
    at wrapper [as _onTimeout] (timers.js:258:14)
    at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)
rwaldron commented 9 years ago

Yeah... that's weird. I have mraa@0.5.4-110-g459ecc0 as the version that Galileo-IO installs, so I will have to update and see what happens.

rwaldron commented 9 years ago

I was able to reproduce your bug with 100% consistency by unplugging the sensor from SDA/SCL.

GrossDesignCo commented 9 years ago

Wow. I just removed an intermediary board (servo shield from Adafruit with stacking headers) and the accelerometer started logging like magic.

raw { x: 112, y: 1881, z: 766 }
raw { x: 5581, y: 1905, z: 766 }
raw { x: 5581, y: 1905, z: 766 }
raw { x: 5581, y: 1905, z: 766 }
raw { x: 5415, y: 4631, z: -372 }
raw { x: 5364, y: 2747, z: -1139 }
raw { x: -165, y: 2747, z: -1139 }
raw { x: -165, y: 2747, z: -6010 }
raw { x: -165, y: 2747, z: -6010 }
raw { x: -51, y: 200, z: -2807 }
raw { x: -51, y: 200, z: -2807 }
raw { x: -51, y: 200, z: -2807 }
raw { x: -51, y: 200, z: 2064 }
raw { x: -4096, y: -670, z: -1008 }
raw { x: -4044, y: -870, z: -3071 }
raw { x: -4044, y: -870, z: -3071 }
raw { x: -4044, y: -870, z: 2253 }
raw { x: -4095, y: -761, z: -253 }
raw { x: -5456, y: 109, z: 2818 }
rwaldron commented 9 years ago

Sounds like it was preventing the sensor from reaching the i2c bus

rwaldron commented 9 years ago

Can we close this?

GrossDesignCo commented 9 years ago

Yep. I think it's closed. Thanks again.

rwaldron commented 9 years ago

Great—thanks for your patience and cooperation :) glad we could get this solved for you.

Please post back any updates about your project as well, either here or on twitter—I'd love to see what you're building

GrossDesignCo commented 9 years ago

Will do! I'm looking forward to getting it off the ground.

Cheers.

GrossDesignCo commented 9 years ago

Followup: It sounds like a dumb obvious solution, but I connected the INT pin on the accelerometer to Digital IO pin 2 on the adafruit servo shield, and the mpu6050 started working like a charm.

I think this is because the shield is also communicating with the edison via i2c, but I don't have a solid enough handle on what the interrupt pin actually does to offer a certain explanation. I also haven't tried it with servos actually running to see if those interfere or not, but it's looking good so far.

codefoster commented 9 years ago

Now I'm getting the same error as the original post. I have the latest version of the OS and the galileo-io module. Any ideas how to troubleshoot?

rwaldron commented 9 years ago

@codefoster I'm setting up an Edison right now, will post back when I know more

GrossDesignCo commented 9 years ago

When I was getting the error, it was being caused by an intermediary board that was preventing the accelerometer from communicating with my edison. (I had mpu6050 > Servo Shield > Edison, but changing it to mpu6050 > Edison got it working. The Edison has two separate connections for i2c, so you can always use the second bus to manage your other devices.)

If you can, I'd double-check your wiring, check for any loose connections & such as well.

rwaldron commented 9 years ago

@GrossDesignCo that's super helpful—thanks!

GrossDesignCo commented 9 years ago

Cheers.

rwaldron commented 9 years ago

From scratch:

var five = require("johnny-five");
var Edison = require("galileo-io");
var board = new five.Board({
  io: new Edison()
});

board.on("ready", function() {
  var accelerometer = new five.Accelerometer({
    controller: "MPU6050"
  });

  accelerometer.on("data", function() {
    console.log([this.x, this.y, this.z]);
  });
});
root@edison:~# node mpu6050.js
1433974964838 Device(s) Intel Edison
1433974964852 Connected Intel Edison
1433974964874 Repl Initialized
>> [ 0.002, -0.0088, 1 ]
[ 0.001, -0.0078, 1 ]
[ 0, -0.0078, 1 ]
[ -0.000061, -0.0073, 1 ]
[ -0.001, -0.0079, 1 ]
[ -0.0022, -0.0077, 1 ]
[ -0.0027, -0.0085, 1 ]
[ -0.0022, -0.0074, 1 ]
[ -0.0022, -0.0068, 1 ]
[ -0.0014, -0.006, 1 ]
[ -0.00024, -0.0063, 1 ]
[ -0.0015, -0.0071, 1 ]
[ -0.0024, -0.0075, 1 ]
[ -0.003, -0.0077, 1 ]
[ -0.0029, -0.009, 1 ]
[ -0.003, -0.0078, 1 ]
[ -0.00043, -0.0051, 1 ]
[ 0.00073, -0.0056, 1 ]
[ 0.0015, -0.0063, 1 ]
[ -0.0013, -0.0057, 1 ]
[ -0.0017, -0.0056, 1 ]
[ -0.0015, -0.0079, 1 ]
[ -0.0021, -0.0066, 1 ]
[ -0.0024, -0.0063, 1 ]
[ -0.00079, -0.0049, 1 ]
[ 0.00024, -0.0045, 1 ]
[ -0.00018, -0.0046, 1 ]
[ -0.00073, -0.0054, 1 ]
[ -0.0012, -0.0042, 1 ]
...

(and so on)
codefoster commented 9 years ago

@GrossDesignCo, I'm getting the error you had at first though when you had a software problem. Anyway, it doesn't hurt to recheck all of the connections. I'm actually using a Xadow kit by Seeed and the accelerometer that came with it. I'll follow the systematic steps that you did @rwaldron and revert to the Arduino dev board as a troubleshooting step and report how it goes. Thanks.

codefoster commented 9 years ago

This accelerometer in the Xadow kit is apparently an ADXL345, but I put a console log in galileo.js:623 just inside the call to i2cRead and the values are: address: 83, register: 50, bytesToRead: 6. I see that register 50 is a read on the X value for the official ADXL345 datasheet, but for the Xadow sample in Wiring it looks like the read on the X value is register 32. I'm still troubleshooting this. I'd love a good pointer on customizing J5 components. I've so far been trying to reverse engineer the existing ones (i.e. accelerometers.js) and that works alright, but I'm not entirely sure where's the best place to put a new file (i.e. pressure.js) and how to deploy and load and such. I'm working on a driver for the BMP180 barometer.

rwaldron commented 9 years ago

If the Xadow kit has an ADXL345, then just switch to that controller:

var accelerometer = new five.Accelerometer({ controller: "ADXL345" });

but I put a console log in galileo.js:623 just inside the call to i2cRead and the values are: address: 83, register: 50, bytesToRead: 6. I see that register 50 is a read on the X value for the official ADXL345 datasheet, but for the Xadow sample in Wiring it looks like the read on the X value is register 32.

The code on this page shows 0x32 which matches the controller in Johnny-Five and the datasheet. 0x32 is a hexadecimal integer literal, so 0x32 === 50

I'd love a good pointer on customizing J5 components.

How do you mean?

I'm working on a driver for the BMP180 barometer.

I realized this morning that I had code for the BMP180 in yet another branch and also that the component is really not straight forward. I will get it pushed out for you to test as soon as I can.

codefoster commented 9 years ago

Ah. Good point on the 0x32 == 50. I am using the ADXL345 controller and the built in five.Accelerometer. That's what I'm having the trouble with. Ball's in my court... you've given me plenty to try. Thanks! Looking forward to the BMP180 code to play with too. I really need to get my head wrapped around I2C. Glad you too think the BMP180 is a relatively difficult one to parse.

rwaldron commented 9 years ago

Glad you too think the BMP180 is a relatively difficult one to parse.

I finished up the algorithm parts today and it's ready to roll. The worst part is that the reading registers aren't contiguous so I can't tell it "do all the measurements" and then get temp and pressure in one read. Blah.

For some reason I think @ashishdatta told me that the Grove accelerometer isn't an ADXL345 anymore? He'll know better

ashishdatta commented 9 years ago

The grove kits we are using are the +/-1.5g 3-axis accelerometer which is the MMA7660 so we do not have to change the IOREF on the board, the Xadow accelerometer is a +/- 16g which is an ADXL345 chip.

rwaldron commented 9 years ago

@ashishdatta ah, got it! Thank you sir :)

codefoster commented 9 years ago

I added a console log for the i2cWrite and i2cRead methods in galileo.js. Here's my code...

var five = require("johnny-five");
var Edison = require("edison-io");

var board = new five.Board({
  io: new Edison()
});

board.on("ready", function() {
  var accelerometer = new five.Accelerometer({
    controller: "ADXL345"
  });

  accelerometer.on("change", function() {
    console.log("accelerometer");
    console.log("  x            : ", this.x);
    console.log("  y            : ", this.y);
    console.log("  z            : ", this.z);
    console.log("  pitch        : ", this.pitch);
    console.log("  roll         : ", this.roll);
    console.log("  acceleration : ", this.acceleration);
    console.log("  inclination  : ", this.inclination);
    console.log("  orientation  : ", this.orientation);
    console.log("--------------------------------------");
  });
});

Here's the output...

root@tweetmonkey:~/drone# node app
1434079595567 Device(s) Intel Edison
1434079595582 Connected Intel Edison
1434079595604 Repl Initialized
>> i2cWrite: {address: 83, cmdRegOrData: 45, inBytes: 0}
i2cWrite: {address: 83, cmdRegOrData: 45, inBytes: 8}
i2cWrite: {address: 83, cmdRegOrData: 49, inBytes: 8}
i2cRead: {address: 83, register: 50, bytesToRead: 6}

RangeError: Trying to access beyond buffer length
    at checkOffset (buffer.js:582:11)
    at Buffer.readUInt8 (buffer.js:588:5)
    at Galileo.<anonymous> (/home/root/drone/node_modules/galileo-io/lib/galileo.js:662:24)
    at wrapper [as _onTimeout] (timers.js:258:14)
    at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)

I'm wondering if this helps narrow down the problem. Specifically I'm wondering if the fact that it does 3 successful i2cWrite calls before it tries an i2cRead call and pukes means that it does have a physical connection to the sensor. It seems that way to me.

codefoster commented 9 years ago

This is the call from within accelerometer.js that throws the buffer error...

io.i2cRead(address, this.COMMANDS.READREGISTER, READLENGTH,
function(data) {
  dataHandler.call(this, {
    x: int16(data[1], data[0]),
    y: int16(data[3], data[2]),
    z: int16(data[5], data[4])
  });
}.bind(this));

As you've shown above, it works fine for your ADXL345 proper plugged into an Arduino dev board, but I'm not getting it to work with the (supposedly) ADXL345 plugged in to this Xadow board. I'm going to run the Arduino sample that Seeed supplies with the board to see if it runs (that would rule out any hardware/connection issues) and then see what's different between the two scripts.

fivdi commented 9 years ago

It looks like the buffer constructed here doesn't contain the 6 bytes it should contain. What does console.log(data.length) output to the screen? 0 perhaps?

As far as I can figure out, the J5 i2cRead method ends up here. If the required 6 bytes can't be read, 0 is returned.

AFAIK, the Edison has the various command line tools like i2cdetect, i2cget, and i2cdump that can be used to scan and access the I2C bus. For example, does i2cdetect -r 1 (or is it i2cdetect -r 6?) detect the ADXL345?

rwaldron commented 9 years ago

ADXL345 plugged in to this Xadow board

Can you link to the exact board you're referring to? Thanks!

codefoster commented 9 years ago

This is the Xadow accelerometer. I think I've narrowed the problem down to a pin mapping issue. The logic in galileo.js says if the pin count is 20 then it's a miniboard. Otherwise it's an Arduino board. I console logged the Pin.IO.getPinCount() and for the Xadow board it returns 56. For the Arduino board it returned 20. I have a mini-board as well and that one returns 20. I'm confused. Shouldn't the Arduino board return the higher pin count according to the logic in galileo.js? The core issue appears to be in i2cRead in galileo.js. When we create the buffer using...

var data = new Buffer(state.i2c.read(bytesToRead)); //where bytesToRead is 6 in our case

...I checked and the value of state.i2c.read(bytesToRead) is an empty string. So the buffer is empty and the subsequent call to data.readUInt8(i) throws the error about "trying to access beyond buffer length".

codefoster commented 9 years ago

@fivdi, I didn't know about the i2c tools. That's exciting. I'll give it a shot.

codefoster commented 9 years ago

@fivdi I can run i2cdetect and i2cdump, but I have no idea what the results mean and can't find an online article/tutorial for translating them. I would expect i2cdetect to indicate something in the 0x77 slot (where the 70 row intersects the 7 column), but I don't I do get 'UU' in 21, 22, and 23.

codefoster commented 9 years ago

Problem solved. The i2c bus for the Xadow programmer board is 0. The galileo.js determines bus 6 for and Arduino dev board or 1 for the miniboard. I can't see any way to determine that the board is a Xadow, so I'll just hack it for now.

rwaldron commented 9 years ago

I have a mini-board as well and that one returns 20. I'm confused.

I'm not sure how that's even possible, since detection is based on testing for a hardware capability of the Arduino board. If it's not found, then it's assumed this the Edison module is connected to a miniboard .

Shouldn't the Arduino board return the higher pin count according to the logic in galileo.js?

The mini board has 56 pinouts, where the arduino board only has 20.

The i2c bus for the Xadow programmer board is 0. The galileo.js determines bus 6 for and Arduino dev board or 1 for the miniboard. I can't see any way to determine that the board is a Xadow, so I'll just hack it for now.

Nor can I. I filed this: https://github.com/intel-iot-devkit/mraa/issues/222

rwaldron commented 9 years ago

Also! I pushed this just now: https://github.com/rwaldron/galileo-io#specify-an-i2c-bus

fivdi commented 9 years ago

@codefoster i2cdetect can be used for several things, one of which is to scan a bus for devices. For example, here's the output of i2cdetect -y -r 6 for an Edison for Arduino with an ADXL345 at address 0x53 and a DS1621 temperature sensor at address 0x48:

root@edison:~# i2cdetect -y -r 6
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- -- 
50: -- -- -- 53 -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                         

I'm not sure why you were expecting something at address 0x77. UU is displayed when a 'Device or resource busy' error is detected at a particular address. This usually happens when the address is reserved for some purpose. Here's the output for i2cdetect -y -r 1 on the Edison for Arduino:

root@edison:~# i2cdetect -y -r 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: UU UU UU UU -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                         

Another interesting one is i2cdetect -l which lists all buses:

root@edison:~# i2cdetect -l
i2c-1   i2c         i2c-designware-1                    I2C adapter
i2c-2   i2c         i2c-designware-2                    I2C adapter
i2c-3   i2c         i2c-designware-3                    I2C adapter
i2c-4   i2c         i2c-designware-4                    I2C adapter
i2c-5   i2c         i2c-designware-5                    I2C adapter
i2c-6   i2c         i2c-designware-6                    I2C adapter
i2c-7   i2c         i2c-designware-7                    I2C adapter
i2c-8   i2c         PMIC I2C Adapter                    I2C adapter
mulderp commented 8 years ago

Just a small note that I tried the MPU-6050 examples on an Intel Edison mini breakout board, but unforuntately it was not working yet. The problem might be 1.8 V levels of I2C. Some notes here: http://electronics.stackexchange.com/questions/214485/i2c-with-1-8v-levels-without-level-shifters