Open Koepel opened 7 years ago
Hi Koepel,
Nice that you're looking in ;-)
This code is still very much a work in progress. I'm trying to make the it multi-tasking (Automaton) freindly. If I remember correctly you are right as far as the Wire.h library is concerned (somewhat to my disappointment). The whole i2c transaction takes around 700 us, which is a pretty long time to be idle waiting for a buffer to fill up. (see this: https://github.com/arduino/Arduino/issues/1476)
Fortunately there's the i2c_t3 library (for the Teensy 3.x/LC controllers) which does have a non-blocking function. I was trying to write an interface that would accommodate blocking as well as non-blocking.
Anyway the MPU6050cf variant has the non-blocking code for teensies, it uses the sendRequest() method and then checks sampleReady() to see if the data is in yet. And then it does work. Automaton can keep doing other things while the data is requested from i2c.
void MPU6050cf::requestSample( void ) {
Wire.beginTransmission( address );
Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
#ifdef __AVR_ATmega328P__
Wire.requestFrom( address, 14, true );
#else
Wire.sendRequest(address,14, I2C_STOP ); // request a total of 14 registers
#endif
}
bool MPU6050cf::sampleReady( void ) {
return Wire.available() >= 14;
}
Of course that creates a new problem. What if two Automaton state machines want to use the same i2c bus to request data from the same or different devices? That's what the lockChannel() call is for.
It's cool to get coding advice just by putting code up on Github ;-)
Rgdz, Tinkerspy
I'm sorry, I spoke too soon. I know the non-blocking Teensy Library: https://github.com/nox771/i2c_t3
I think you can test for __AVR__
, since all AVR chips use the same Wire library.
In an embedded system an event from outside should not be able halt the code. I think at this moment, the Arduino Wire library for AVR chips can halt if for example SDA or SCL is shorted to GND.
In AVR mode, if the I2C bus has a collision or something that will not halt the Wire library but it detects a problem, then the Wire.available() probably returns zero. You would be stuck in a while loop, waiting for data. Therefor it might still be a good idea to remove the waiting in AVR mode.
My ideal I2C library would have a sendRequest with a call-back function and multitasking.
When the function Wire.requestFrom() returns, the I2C transaction has completely finished and the received data is waiting in a buffer in the Wire library. There is no need to wait for something before reading that data from the buffer.
In the file "MPU6050jb .cpp", the function "sampleReady()" is therefor not needed. You can combine "requestSample()" and "readSample" into one function even without the Wire.available().
When the Wire library is able to detect something wrong with the hardware I2C bus, then the Wire.available() might return zero (the Wire.request() of the Wire library for AVR microcontrollers might never return, but that is another story). You could add a extra check to see if the same number of bytes was received as was requested. But that extra check is not needed, and you don't have that extra check at the moment.