-
I am not sure how I would go about graphing it, I am running it on a pico via VS Code.
However, I tried printing out a continuous stream of x,y and z values, and I can see a bump in the correct direction when I move the sensor around.And as you wrote it is showing one value as 1 and the other 2 as zero, so it seems to be the acceleration + gravity.
I found a few implementations of the code in JS but for raspberry pi etc, and I can't see how they handle filtering out the gravity, but I'll keep on digging, I'll also look at how Espruino handles other accelerometers, thank you :) -
Ok, I can get a few things consistently from the sensor including the orientation, but I found this section:
Many applications use the accelerometer’s static acceleration readings (i.e., tilt) which measure the change in acceleration
due to gravity only. These functions benefit from acceleration data being filtered with a low-pass filter where high frequency data is
considered noise.In the documentation, I wonder if I'm getting "static acceleration" data rather than actual acceleration data, I'll have to dig more tomorrow, my brain at this point is mushy .. xD
Thanks for your help both of you :) -
Ah, thank you, I am still not getting the accelleration (.. I think), but I just had a breakthrough, by setting stop:false, I just ran the following piece of code.
I2C1.writeTo({ address: 0x1D, stop: false }, 0x0D);I2C1.readFrom(0x1D, 1);
What this is supposed to do is return the device's ID, 0x1A, and I got 26 back, which indeed is 0x1A, I feel like I am really close to cracking this, thank you :D
-
Lol ... so working on that theory, I changed the logIt function to look like this
logIt() { this.i2c.writeTo(this.MMA8451_ADDR, this.MMA8451_REG_OUT_X_MSB); let buffer = this.i2c.readFrom(this.MMA8451_ADDR, 7); let x = buffer[1]; x <<= 8; x |= buffer[2]; x >>= 2; let y = buffer[3]; y <<= 8; y |= buffer[4]; y >>= 2; let z = buffer[5]; z <<= 8; z |= buffer[6]; z >>= 2; const divider = 2048; let x_g = x / divider; let y_g = y / divider; let z_g = z / divider; console.log('x_g', x_g, 'y_g', y_g, 'z_g', z_g); console.log('buffer', buffer); }
Essentially I'm just ignoring the first byte of data and grabbing 1 extra, and now the data at least seems relatively stable, though I think it's the tilt of the sensor, but for some reason in a range between 0 and 8 o_0, but it really doesn't fit with how I've understood I2C to work.
From what I understand you send a write, telling what you want from the device, when you call read the first data you get back is the data you requested. I am rather confused ... xD
-
I've noticed something.
Other implementations of read take a registry variable, and then write to that registry first and then read the first byte from the device, but after a lot of testing it seems that the first byte here is always either 0 or 255
The device sets that byte from 0 to 255 when this is called:// Activate at max rate, low noise mode this.writeRegister8(this.MMA8451_REG_CTRL_REG1, 0x01 | 0x04);
After work I'll go back and look at the datasheet, but I am wondering if perhaps it just always sends the data in the array back in the same order, no matter what is sent to it.
-
I have rewritten my code and cleaned it up a bit, but it still gives the same values as in my previous post
export default class MMA8451 { // @ts-ignore i2c: I2C = new I2C(); MMA8451_ADDR = 0x1D; MMA8451_REG_OUT_X_MSB = 0x01 //!< Read-only device output register MMA8451_REG_PL_CFG = 0x11 //!< Portrait/landscape configuration register MMA8451_REG_CTRL_REG1 = 0x2A //!< CTRL_REG1 system control 1 register MMA8451_REG_CTRL_REG2 = 0x2B //!< CTRL_REG2 system control 2 register MMA8451_REG_CTRL_REG4 = 0x2D //!< CTRL_REG4 system control 4 register MMA8451_REG_CTRL_REG5 = 0x2E //!< CTRL_REG5 system control 5 register writeRegister8(reg: number, value: number) { this.i2c.writeTo(this.MMA8451_ADDR, [reg, value]); } readRegister8(reg: number) { this.i2c.writeTo(this.MMA8451_ADDR, reg); return this.i2c.readFrom(this.MMA8451_ADDR, 1)[0]; } begin() { // @ts-ignore this.i2c.setup({ scl: B6, sda: B7 }); this.writeRegister8(this.MMA8451_REG_CTRL_REG2, 0x40)// reset setTimeout(() => { this.begin2(); }, 500); } begin2() { this.writeRegister8(0x0E, 0b01); // enable 4G range this.writeRegister8(this.MMA8451_REG_CTRL_REG2, 0x02); // High res // DRDY on INT1 this.writeRegister8(this.MMA8451_REG_CTRL_REG4, 0x01); this.writeRegister8(this.MMA8451_REG_CTRL_REG5, 0x01); // Turn on orientation config this.writeRegister8(this.MMA8451_REG_PL_CFG, 0x40); // Activate at max rate, low noise mode this.writeRegister8(this.MMA8451_REG_CTRL_REG1, 0x01 | 0x04); } logIt() { this.i2c.writeTo(this.MMA8451_ADDR, this.MMA8451_REG_OUT_X_MSB); let buffer = this.i2c.readFrom(this.MMA8451_ADDR, 6); let x = buffer[0]; x <<= 8; x |= buffer[1]; x >>= 2; let y = buffer[2]; y <<= 8; y |= buffer[3]; y >>= 2; let z = buffer[4]; z <<= 8; z |= buffer[5]; z >>= 2; const divider = 2048; let x_g = x / divider; let y_g = y / divider; let z_g = z / divider; console.log('x_g', x_g, 'y_g', y_g, 'z_g', z_g); console.log('buffer', buffer); } }
-
Perhaps you are not aware of this, but in C/C++, arrays do not know their own size(an 'array' variable is actually just the memory address of the first entry) so the size must always be supplied separately.
I had no idea no. I've done C# and js/ts, but not much C or C++.
What you write makes me think that I should do something like this
this.i2c.writeTo(this.MMA8451_ADDR, this.MMA8451_REG_OUT_X_MSB); let buffer = this.i2c.readFrom(this.MMA8451_ADDR, 6);
Where I then only send the value the "write_then_read" function sends, and then read 6 bytes from the same address, however the data I get out still seems wrong, here are 4 readings and again it's just lying on the table not moving.
x_g 7.9755859375 y_g 2.25146484375 z_g 5.50146484375 buffer new Uint8Array([255, 59, 72, 13, 176, 12]) x_g 7.9755859375 y_g 0.50146484375 z_g 4.75146484375 buffer new Uint8Array([255, 59, 16, 13, 152, 12]) x_g 7.9755859375 y_g 4.75146484375 z_g 3.75146484375 buffer new Uint8Array([255, 59, 152, 14, 120, 12]) x_g 7.9755859375 y_g 1.00146484375 z_g 6.25146484375 buffer new Uint8Array([255, 59, 32, 13, 200, 12])
-
Thank you for your reply :)
After reading and thinking I tried rewriting all of my read and write calls, though I am still quite confused over exactly what the "writeRegister" function actually does.What I am guessing so far, is that the _sensorID is set via "getSensor", which is called at some point, though as far as I can see it's not called in the code nor in the examples from Adafruit.
From then on it's automagically inserted in the write function called by writeRegister8?I am assuming that
uint8_t buffer[2] = {reg, value}
creates a new "Uint8Array" of length 2, and adds the reg on position 0 and the value on position 1?
Then from what I can read
i2c_dev.write(buffer,2)
in js would be akin to
this.i2c.writeTo(0x1D, [reg, val])
Is that correct? Not certain what to do with the 2 though.
I tried changing my read/write calls to look like the following
this.i2c.writeTo(this.MMA8451_ADDR, [this.MMA8451_REG_CTRL_REG2, 0x02]);
I am still quite confused about how to do this then:
i2c_dev->write_then_read(buffer, 1, buffer, 6);
I attempted to write it like this
let buffer = new Uint8Array([this.MMA8451_REG_OUT_X_MSB, 0, 0, 0, 0, 0]); this.i2c.writeTo(this.MMA8451_ADDR, [buffer, 1]); let val2 = this.i2c.readFrom(this.MMA8451_ADDR, 6);
But I'm pretty sure that's wrong, I am getting changing values at least, but they seem random xD
I just had the chip laying on my desk and ran "logIt" a few times in row, and got these values.x_g 7.97021484375 y_g 6.5048828125 z_g 7.001953125
val2 new Uint8Array([255, 15, 208, 41, 224, 17])x_g 7.97607421875 y_g 4.25146484375 z_g 2
val2 new Uint8Array([255, 61, 136, 12, 64, 3])x_g 7.97607421875 y_g 7.7509765625 z_g 6
val2 new Uint8Array([255, 60, 248, 11, 192, 3])x_g 7.97607421875 y_g 4.0009765625 z_g 3.5
val2 new Uint8Array([255, 63, 128, 11, 112, 3])x_g 7.97607421875 y_g 4.7509765625 z_g 3.00048828125
val2 new Uint8Array([255, 62, 152, 11, 96, 4])x_g 7.97607421875 y_g 1.00146484375 z_g 4.5
val2 new Uint8Array([255, 63, 32, 12, 144, 3])x_g 7.97607421875 y_g 5.5009765625 z_g 4.75
val2 new Uint8Array([255, 62, 176, 9, 152, 3])x_g 7.97607421875 y_g 6.2509765625 z_g 0.5
val2 new Uint8Array([255, 63, 200, 11, 16, 3])x_g 7.9765625 y_g 6.7509765625 z_g 0
val2 new Uint8Array([255, 64, 216, 11, 0, 3])x_g 7.97607421875 y_g 7.2509765625 z_g 7.00048828125
val2 new Uint8Array([255, 61, 232, 8, 224, 4])x_g 7.97607421875 y_g 4.5009765625 z_g 7.00048828125
val2 new Uint8Array([255, 62, 144, 9, 224, 4])x_g 7.97607421875 y_g 0.5009765625 z_g 1.75048828125
val2 new Uint8Array([255, 63, 16, 9, 56, 4])x_g 7.97607421875 y_g 5.00048828125 z_g 6.75048828125
val2 new Uint8Array([255, 62, 160, 7, 216, 4])x_g 7.97607421875 y_g 0.0009765625 z_g 2.50048828125
val2 new Uint8Array([255, 63, 0, 8, 80, 5])x_g 7.97607421875 y_g 3.5009765625 z_g 0.75048828125
val2 new Uint8Array([255, 63, 112, 9, 24, 4])As you can see, despite laying on my desk, X is 7.976 all throughout while Y and Z are fluctuating, so I'm pretty sure I'm still doing something wrong, but I feel as though I'm closer at least :)
-
I've never written stuff for I2C or other protocols, but I have an MMA8451 chip on a breakout board from Adafruit. To my knowledge, there isn't an Espruino library for it, so I've looked at the one provided for Arduino by Adafruit and tried to write one in Espruino, but I'm not getting the expected results and I am rather confused about what I am even doing .. xD
So quickly a few links:
This is the Adafruit guide that I used to hook it up
https://learn.adafruit.com/adafruit-mma8451-accelerometer-breakout/overviewThis is the datasheet
https://cdn-shop.adafruit.com/datasheets/MMA8451Q-1.pdfThis is the header file for the Adafruit library
https://github.com/adafruit/Adafruit_MMA8451_Library/blob/master/Adafruit_MMA8451.hAnd this is the actual code for the library
https://github.com/adafruit/Adafruit_MMA8451_Library/blob/master/Adafruit_MMA8451.cppAlso, I am not proficient in C++, so I've been googling and guessing my way through trying to convert it.
This is my code, it's in typescript but gets transpiled into JS that the board understands :)
export default class MMA8451 { // @ts-ignore i2c: I2C = new I2C(); MMA8451_REG_OUT_X_MSB = 0x01 //!< Read-only device output register MMA8451_REG_PL_CFG = 0x11 //!< Portrait/landscape configuration register MMA8451_REG_CTRL_REG1 = 0x2A //!< CTRL_REG1 system control 1 register MMA8451_REG_CTRL_REG2 = 0x2B //!< CTRL_REG2 system control 2 register MMA8451_REG_CTRL_REG4 = 0x2D //!< CTRL_REG4 system control 4 register MMA8451_REG_CTRL_REG5 = 0x2E //!< CTRL_REG5 system control 5 register begin() { // @ts-ignore this.i2c.setup({ scl: B6, sda: B7 }); this.i2c.writeTo(this.MMA8451_REG_CTRL_REG2, 0x40); // reset setTimeout(() => { this.begin2(); }, 500); } begin2() { this.i2c.writeTo(0x0E, 0b01); // enable 4G range this.i2c.writeTo(this.MMA8451_REG_CTRL_REG2, 0x02); // High res // DRDY on INT1 this.i2c.writeTo(this.MMA8451_REG_CTRL_REG4, 0x01); this.i2c.writeTo(this.MMA8451_REG_CTRL_REG5, 0x01); // Turn on orientation config this.i2c.writeTo(this.MMA8451_REG_PL_CFG, 0x40); // Activate at max rate, low noise mode this.i2c.writeTo(this.MMA8451_REG_CTRL_REG1, 0x01 | 0x04); for (let i = 0x00; i < 0x30; i++) { console.log('index', i, this.i2c.readFrom(i, 16)); } } logAll() { for (let i = 0x00; i < 0x30; i++) { console.log('index', i, this.i2c.readFrom(i, 16)); } } logIt() { let buffer = new Uint8Array([this.MMA8451_REG_OUT_X_MSB, 0, 0, 0, 0, 0]); let val1 = this.i2c.writeTo(buffer, 1); let val2 = this.i2c.readFrom(buffer, 6); let x = buffer[0]; x <<= 8; x |= buffer[1]; x >>= 2; let y = buffer[2]; y <<= 8; y |= buffer[3]; y >>= 2; let z = buffer[4]; z <<= 8; z |= buffer[5]; z >>= 2; const divider = 2048; let x_g = x / divider; let y_g = y / divider; let z_g = z / divider; console.log('x_g', x_g, 'y_g', y_g, 'z_g', z_g); console.log('val1', val1); console.log('val2', val2); console.log('buffer', buffer); } }
So one thing I am noticing right off the bat is that I never actually use the address of the chip (0x1D), but the Adafruit code also only uses two places, which aren't called in the code xD
If I run "runSensor" then I get 48 lines printed out that all look like this:
index 28 new Uint8Array([255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255])Except for one that looks like this:
index 29 new Uint8Array([0, 41, 252, 163, 200, 152, 160, 0, 41, 252, 163, 200, 152, 160, 0, 41])But that line doesn't change no matter how much I move the sensor around
And if I run "logIt"
I get the following data:
x_g 0.03125 y_g 0 z_g 0
val1 undefined
val2 new Uint8Array([255, 255, 255, 255, 255, 255])
buffer new Uint8Array([1, 0, 0, 0, 0, 0])Again it's identical no matter how much I move the sensor around.
If I unplug the sensor, then line 29 in the array becomes an array of 255 like the others, however, the "logIt" still pumps out the same data.Can anyone help me with this? :)
-
Well.. one piece of news is that I am really great at starting projects, many projects, even when the previous projects are not done yet, but I guess that's more of an olds than a news xD
The hat is sort of half complete, it has a mouth that can move, and a nose LED that can blink, but audio seems a really daunting task, so I ended up procrastinating with other projects xD
-
-
I can totally see your point, I may have misunderstood what is happening.
I tried using the convention here:analogWrite(pin, (1+pos) / 50.0, {freq:20, soft: false });
Where what I actually saw was:
{soft: false}
made the motor move to the position and hold that position, while soft: true, or no value would make the servo move to the position and then it would just go slack. I figured that soft in this case meant whether or not it should go slack.How would you suggest the change be implemented? :)
-
-
-
-
Alternatively, if the forum really does need to be replaced, I think more people may be up for an open-source solution like
Discourse
https://github.com/discourse/discourseI think it has all the features that are wanted, like likes etc
-
I wouldn't mind an update to the forum, but to me it would seem a better use of time to upgrade the documentation pages (the layout looks rather dated which sadly reflects back on espruino as a whole), and maybe get a vscode extension going, (something I've personally been tinkering with for a week or two, though I've come to realize that I need to learn more about babel, and perhaps gulp and webpack and how they work together)
-
-
-
-
-
-
-
Just want to post that I finally got something that works, while filtering out the gravity, I am not sure what I did, but I'll clean up my code tomorrow and figure it out xD