-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
CircuitPython version
Adafruit CircuitPython 8.2.6 on 2023-09-12; TinyS3 with ESP32S3Code/REPL
import board
import time
import sys
from adafruit_bus_device.i2c_device import I2CDevice
delay = 0.1
bytes_to_read = 12
print("")
print(f"Reading {bytes_to_read} bytes from I2C every {delay} seconds")
reads = 0
errors = 0
while True:
try:
with board.I2C() as i2c:
device = I2CDevice(i2c, 0x08)
data = bytearray(bytes_to_read)
with device:
device.readinto(data)
reads = reads + 1
except ValueError as e:
print(f"No I2C response: {e}")
except Exception as e:
print(f"{type(e)}: {e} after {reads} reads: {e}")
errors = errors + 1
if errors > 3:
sys.exit()
time.sleep(delay)Behavior
Reading 12 bytes from I2C every 0.1 seconds
<class 'OSError'>: [Errno 5] Input/output error after 2347 reads: [Errno 5] Input/output error
No I2C response: No I2C device at address: 0x8
<class 'OSError'>: [Errno 5] Input/output error after 2347 reads: [Errno 5] Input/output error
No I2C response: No I2C device at address: 0x8
<class 'OSError'>: [Errno 5] Input/output error after 2347 reads: [Errno 5] Input/output error
No I2C response: No I2C device at address: 0x8
Soft resetting the board then give the following error:
soft reboot
Auto-reload is off.
Running in safe mode! Not running saved code.
You are in safe mode because:
CircuitPython core code crashed hard. Crikey!
Hard fault: memory access or instruction error.
Please file an issue with your program at github.com/adafruit/circuitpython/issues.
Press reset to exit safe mode.
Press any key to enter the REPL. Use CTRL-D to reload.
Description
After at most a couple of minutes polling I2C for responses (and getting them), the above code will give the detailed exceptions and stop. The Arduino board works just fine and once the CircuitPython board has been reset, will continue responding correctly to I2C requests without having been reset itself
I've seen read counts vary between 400 and 2500 before the fault appears.
Additional information
The code on the Arduino board (an Adafruit Pro Trinket 3.3V) that responds to the I2C request:
#include <Wire.h>
void setup()
{
Serial.begin(115200);
Wire.begin(8); // join i2c bus with address #8
Wire.onRequest(i2crequest);
pinMode(LED_BUILTIN, OUTPUT);
Serial.println("Setup OK");
}
void loop()
{
}
void i2crequest() {
digitalWrite(LED_BUILTIN, HIGH);
byte tosend[15] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
Wire.write(tosend,15);
digitalWrite(LED_BUILTIN, LOW);
}
The Arduino Wire library is clever enough to stop sending responses once they stop being accepted (by a NACK) from the CircuitPython board. There is no change in behaviour if the Arduino is configured to send the same amount of bytes as requested, or to send more.
Looking at the I2C bus with a logic analyzer shows the expected behaviour every tenth of a second (as configured above):
