I was not getting reliable I2C communication between the D1 mini and the ATtiny85, starting with TinyWireS, then moving on to the more developed TinyWire. I would send out 5 bytes from the D1 mini, then try to get 16 bytes back. It will start off well, but a few hours later, something will break and the D1 mini will start getting 0xFFs from the ATtiny85.
Then I found "ATtinyCore" by Spence Konde (V1.1.5), which appears to be a more mature ATtiny core compared to the "attiny" core by David Mellis (V1.0.2). It has integrated I2C support that manifests as the familiar "Wire" library. The installation instructions are here. I did a manual upgrade to the latest git version as some I2C issues have been fixed in the V1.1.6 milestone but have not been officially released. As recommended by the instructions, I bumped up the Arduino version to 1.8.6.
Finally, happy to see reliable I2C communication between the 2 components! The communication has been going non-stop for 2 days now, with 1-minute interval between the send/receiving of messages.
From the D1 mini end, the I2C master code is:
From the ATtiny85, the corresponding I2C code is:
For testing purposes, the D1 mini sends out 5 random bytes, and the ATtiny85 basically copies the received message into the outgoing buffer, with the first byte being the length of the received message (should be always '5').
I found that the maximum number of bytes that can be sent by each requestEvent() is 15 (one less the default value of TWI_RX_BUFFER_SIZE in Wire\src\USI_TWI_Slave\USI_TWI_Slave.h. That could be increased to 32, or 64 (powers of 2 up to 256, as noted in the comment). A workaround will be for the master to make multiple requestFrom() calls, and for the slave to keep track of which block of 15 bytes to send out in requestEvent().
ESPCLOCK1 / ESPCLOCK2 / ESPCLOCK3 / ESPCLOCK4
Then I found "ATtinyCore" by Spence Konde (V1.1.5), which appears to be a more mature ATtiny core compared to the "attiny" core by David Mellis (V1.0.2). It has integrated I2C support that manifests as the familiar "Wire" library. The installation instructions are here. I did a manual upgrade to the latest git version as some I2C issues have been fixed in the V1.1.6 milestone but have not been officially released. As recommended by the instructions, I bumped up the Arduino version to 1.8.6.
Finally, happy to see reliable I2C communication between the 2 components! The communication has been going non-stop for 2 days now, with 1-minute interval between the send/receiving of messages.
From the D1 mini end, the I2C master code is:
1 2 3 4 5 6 7 8 9 10 11 12 | byte outbuf[5]; outbuf[0] = random(128); for (int i=1; i<sizeof(outbuf); i++) outbuf[i] = outbuf[0] + (i*2); Wire.beginTransmission(I2C_SLAVE_ADDR); int rc = Wire.write(outbuf, sizeof(outbuf)); Wire.endTransmission(); debug("Wire.write (%d): %X %X %X %X %X", rc, outbuf[0], outbuf[1], outbuf[2], outbuf[3], outbuf[4]); byte inbuf[15]; Wire.requestFrom(I2C_SLAVE_ADDR, 15); Wire.readBytes(inbuf, 15); Serial.print("Wire.readBytes: "); for (int i=0; i<sizeof(inbuf); i++) { Serial.print(inbuf[i], HEX); Serial.print(' '); } Serial.println(' '); |
From the ATtiny85, the corresponding I2C code is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | volatile byte msg[5], out[15]; void requestEvent() { Wire.write(out, 15); } void receiveEvent(uint8_t numbytes) { if (numbytes > sizeof(msg)) return; int idx = 0; while(idx < numbytes) { if (Wire.available()) msg[idx++] = Wire.read(); } out[0] = numbytes; for (int i=1; i<sizeof(out); i++) out[i] = msg[(i-1) % numbytes]; } |
For testing purposes, the D1 mini sends out 5 random bytes, and the ATtiny85 basically copies the received message into the outgoing buffer, with the first byte being the length of the received message (should be always '5').
I found that the maximum number of bytes that can be sent by each requestEvent() is 15 (one less the default value of TWI_RX_BUFFER_SIZE in Wire\src\USI_TWI_Slave\USI_TWI_Slave.h. That could be increased to 32, or 64 (powers of 2 up to 256, as noted in the comment). A workaround will be for the master to make multiple requestFrom() calls, and for the slave to keep track of which block of 15 bytes to send out in requestEvent().
ESPCLOCK1 / ESPCLOCK2 / ESPCLOCK3 / ESPCLOCK4
Comments
Post a Comment