Closed tomgidden closed 9 years ago
Thanks. Yes, that's a pain.
Are there any other patterns apart from write then read? I guess it might end up being easier to just have a new function that did just that.
Or perhaps:
I2C.writeTo({address:0x55, stop:false}, data);
I2C.readFrom({address:0x55, stop:false}, count);
I don't know of any other patterns, but it's possible I guess. Maybe keep writeTo
and readFrom
as-is for a higher-level capability where it doesn't matter, but also build beginTransmission
,write
,requestFrom
,read
and endTransmission
to match Arduino when greater control is needed. A bit like fopen
/fread
/fclose
vs. open
/read
/close
in C.
It would be handy to have an I2C.readRegister(address, register, count=1)
convenience function, although I don't know how widespread Repeated Start is. I've only programmed a few I2C devices, and this is the first one I've encountered that needs Repeated Start. I don't know whether other devices allow it, prefer it or prohibit it. Apparently it is an official thing, though: http://www.i2c-bus.org/repeated-start-condition/
I'm sort of against re-implementing Arduino's functions, because they tend to complicate things and provide more opportunity for error. Also a silicon problem on the STM32F1 means that you can totally lock up the I2C peripheral if you send a STOP at the wrong time, so it's good not to let people have that choice :)
I don't think that allowing an object instead of a numeric address would cause any backwards compatibility problems though - at least not unless people were doing something really nasty.
Just tried to fix this... it should work like:
I2C.writeTo({address:0x55, stop:false}, data);
I2C.readFrom({address:0x55, stop:false}, count);
I don't have anything to test with though, so please let me know how this works.
A build should be up soon at: http://www.espruino.com/binaries/git/commits/a939ef6285ca9c6f639d4edaaf86fe7606176829
Looks like this may not work - but I'll have to get some hardware to test with first.
@gfwilliams : unfortunately I'm not going to have a chance to test this for a while, thanks to real life. However, I'd be happy to buy you an MPL3115A2 if you want to have a go with it... if so, email or DM me with postal address.
@gfwilliams I just tested this with 1v70:
var _read_reg = function (_i2c, _reg) {
_i2c.writeTo({address:MPL3115A2_ADDRESS /* 0x60 */, stop:false}, _reg);
var bs = _i2c.readFrom(MPL3115A2_ADDRESS, 1);
return bs[0];
};
var whoami = _read_reg(_i2c, MPL3115A2_WHO_AM_I /* 0x0C */);
console.log("WHOAMI (should return 196 apparently): "+whoami);
returns:
WHOAMI: undefined
Uncaught InternalError: Timeout on I2C Read BUSY
I've been using https://github.com/sparkfun/MPL3115A2_Breakout/blob/master/firmware/MPL3115A2/MPL3115A2.ino#L355 as a reference.
I'm currently using BMP180 instead as it's cheaper, more accurate, and simpler. However the MPL3115A2 does have on-board altitude calculation (lower memory footprint?) and has interrupt lines (ultra low power capability). The I2C Repeated Start is, however, probably worth fixing for other devices I suppose.
Hi - thanks for testing it out (and for the offer of a sensor)... I've actually just bought one though - when it arrives I'll see if I can fix the repeated start issue. It should only be a few lines I hope!
Incidentally, while hacking the libraries on nrf51, I noticed that the MPU6050 code write/read routine for that SDK uses Repeated Start too. I believe it's optional on that sensor.
I'm trying to get an MMA8451 (http://www.adafruit.com/datasheets/Freescale_MMA8451QR1.pdf) working and it doesn't seem like the repeated start is working properly? I get
Uncaught InternalError: Timeout on I2C Read BUSY
when I try to read after writing an address with stop set to false. Reading gives me the same 7 bytes every time.
Relevant Arduino code: https://github.com/adafruit/Adafruit_MMA8451_Library/blob/master/Adafruit_MMA8451.cpp
Ok, thanks. Will try and look into it when I get back to the UK.
What board was this on? The I2C implementations are different on different chips
What board were you using? a Pico?
yup, using a pico
Fixed. On the MPL3115, the following code now works:
function r(addr) {
i2c.writeTo({address:0x60, stop:false}, addr);
return i2c.readFrom(0x60,1)[0];
}
var i2c = I2C3;
i2c.setup({sda:B4,scl:A8});
r(0x0c)==196; // WHOAMI
Just came back to this project, using 1v85 and I cannot get it to connect on I2C1. On I2C3 (on a different board) it works fine. Unfortunately for my current project i'm using those pins for SPI so a way to get this working with I2C1 would be super helpful. Same Uncaught InternalError: Timeout on I2C Write BUSY
error as before. Using the code snippet from above but different (obviously) addresses.
You sure it's not that you're missing pullup resistors or having SDA/SCL mixed? The code is identical for I2C1/2 and 3 - so the chances of it working on one and not the other are pretty minimal.
I'm trying to write a library for MPL3115A2 (note, NOT the existing MPL115A2) but according to the Arduino library along with various Google results, it appears that it needs Repeated Start capability on I2C: I think this means not sending a STOP command after a read or a write.
Whether or not this is correct behaviour for I2C slave devices (which as far as I can see should be able to support with and without repeated starts), it's been an issue on Raspberry Pi (since fixed), and was added to Arduino in v.1.0.1.
Related code (from the MPL3115A2 Arduino driver):
and also, http://raspberry.znix.com/2013/03/raspberry-pi-and-repeated-start-i2c.html
I'd guess this might be best presented as an extra optional boolean parameter on
I2C.readFrom
andI2C.writeTo
, although the fix for #370 might scupper that.