I'm trying to program my ESP32 in Rust with std library to communicate with my Arduino Uno over I2C and send messages between the two.
This is my Arduino I2C Slave code:
#include <Arduino.h>
#include <Wire.h>
#include <ArduinoLog.h>
/*Arduino Slave I2C*/
void DataReceive(int numBytes)
{
while(Wire.available())
{
Log.infoln("Recieved!");
Log.infoln(Wire.readStringUntil('\n').c_str());
}
}
void DataRequest()
{
Log.infoln("Sent!");
Wire.write("Pong\n");
}
void setup()
{
Wire.begin(0x14);
/*Event Handlers*/
Wire.onReceive(DataReceive);
Wire.onRequest(DataRequest);
Serial.begin(9600);
Log.begin(6, &Serial);
Log.infoln("Started.");
}
void loop()
{
}
And this is the ESP32 Rust I2C master code:
use esp_idf_hal::delay::{FreeRtos, BLOCK, Delay};
use esp_idf_hal::i2c::*;
use esp_idf_hal::peripherals::Peripherals;
use esp_idf_hal::prelude::*;
fn main() {
// It is necessary to call this function once. Otherwise some patches to the runtime
// implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
esp_idf_svc::sys::link_patches();
// Bind the log crate to the ESP Logging facilities
esp_idf_svc::log::EspLogger::initialize_default();
println!("Started sending");
let peripherals = Peripherals::take().unwrap();
let i2c = peripherals.i2c1;
let sda = peripherals.pins.gpio21;
let scl = peripherals.pins.gpio22;
let config = I2cConfig::new()
.baudrate(100.kHz().into());
let mut i2cdriver = I2cDriver::new(i2c, sda, scl, &config).unwrap();
let delay = Delay::new_default();
let mut data = [5];
loop {
if i2cdriver.write(0x14, "Ping\n".as_bytes(), BLOCK).is_ok() {
log::info!("Sent: Ping");
}
let read = i2cdriver.read(0x14, &mut data, BLOCK);
if read.is_ok() {
log::info!("Recieved: {:?}", &data);
}
else {
log::error!("{}", read.unwrap_err());
}
delay.delay_ms(1000_u32);
}
}
The Arduino receives the messages just fine, below the serial output of the arduino:
Connected to /dev/ttyUSB1! Press CTRL-C to exit.
I: Started.
I: Recieved!
I: Ping
I: Sent!
I: Recieved!
I: Ping
I: Sent!
I: Recieved!
I: Ping
I: Sent!
...
But then when the ESP32 returns an error when reading the data as shown by the output below:
...
I (459) app_start: Starting scheduler on CPU0
I (464) app_start: Starting scheduler on CPU1
I (464) main_task: Started on CPU0
I (474) main_task: Calling app_main()
Started sending
I (474) i2c_test_rust: 1
I (484) i2c_test_rust: Sent: Ping
E (484) i2c_test_rust: ESP_ERR_TIMEOUT
I (1484) i2c_test_rust: Sent: Ping
E (1484) i2c_test_rust: ESP_ERR_TIMEOUT
I (2484) i2c_test_rust: Sent: Ping
E (2484) i2c_test_rust: ESP_ERR_TIMEOUT
I (3484) i2c_test_rust: Sent: Ping
E (3484) i2c_test_rust: ESP_ERR_TIMEOUT
I (4484) i2c_test_rust: Sent: Ping
E (4484) i2c_test_rust: ESP_ERR_TIMEOUT
I (5484) i2c_test_rust: Sent: Ping
E (5484) i2c_test_rust: ESP_ERR_TIMEOUT
I (6484) i2c_test_rust: Sent: Ping
E (6484) i2c_test_rust: ESP_ERR_TIMEOUT
...
I really don't understand why this is happening and the only related resource I could find is this blog post.