Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blank I2C output ESP32 simple program #910

Closed
drbh opened this issue Nov 8, 2023 · 22 comments
Closed

Blank I2C output ESP32 simple program #910

drbh opened this issue Nov 8, 2023 · 22 comments
Labels
bug Something isn't working peripheral:i2c I2C peripheral

Comments

@drbh
Copy link

drbh commented Nov 8, 2023

Chip type:         esp32 (revision v1.0)
Crystal frequency: 40MHz
Flash size:        4MB
Peripheral:        MLX90614
VCC:               3V3
GND:               GND
SDA:               GPIO 21
SCL:               GPIO 22

Thank you for the awesome library. I am having issues connecting a MLX90614 (on a breakout board with 4.7K pull-up resistors on sda and scl) to my ESP32.

I've been able to validate that the device works via the Ardunio IDE using this library and this program.

#include <Adafruit_MLX90614.h>

Adafruit_MLX90614 mlx = Adafruit_MLX90614();

void setup() {
  Serial.begin(115200);
  while (!Serial);

  if (!mlx.begin()) {
    Serial.println("Error connecting to MLX sensor. Check wiring.");
    while (1);
  };
}

void loop() {
  Serial.print("Ambient temperature = "); 
  Serial.print(mlx.readAmbientTempC());
  Serial.print("°C");      
  Serial.print("   ");
  Serial.print("Object temperature = "); 
  Serial.print(mlx.readObjectTempC()); 
  Serial.println("°C");

  Serial.println("-----------------------------------------------------------------");
  delay(500);
}

However I cannot seem to get a useful response when trying to communicate with the I2C bus via esp-hal

I've tried to manually write_read at the address 0x5A and always get a response of [ff, ff, ff].

Additionally I've attempted to scan for all I2C devices and send all 1 byte messages and always get a response of [00, 00, 00] or [ff, ff, ff]. Please see the example code below.

I am an embedded newbie so its very likely I'm doing something (or everything) completely wrong. Is there a better/correct way to read data from an I2C bus?

#![no_std]
#![no_main]

use esp32_hal::{
    clock::{ClockControl, Clocks},
    entry,
    gpio::{Gpio6, GpioPin, Output, PushPull, Unknown, IO},
    i2c::I2C,
    interrupt,
    peripherals::{Peripherals, I2C0, I2C1, RTC_I2C},
    prelude::*,
    Delay,
};
use esp_backtrace as _;
use esp_println::println;

#[entry]
fn main() -> ! {
    let peripherals = Peripherals::take();
    let system = peripherals.SYSTEM.split();
    let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
    let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);

    let sda = io.pins.gpio21;
    let scl = io.pins.gpio22;

    let mut i2c = I2C::new(peripherals.I2C0, sda, scl, 100u32.kHz(), &clocks);

    for addr in 0..=127 {
        if let Ok(_) = i2c.write(addr, &[0x07]) {
            println!("Found device at address: 0x{:02X}", addr);
            for msg in 0..=255 {
                let to_send: [u8; 1] = [msg];
                let mut data = [0u8; 3];
                i2c.write_read(addr, &to_send, &mut data).ok();
                println!("Sent: 0x{:02X}, Received: {:02x?}", msg, data);
            }
        }
    }

    loop {}
}
@bjoernQ
Copy link
Contributor

bjoernQ commented Nov 8, 2023

Code looks fine. Worth to try is using the pins we use in the examples (32,33). If that changes things for you it's probably a bug on our side (since 21,22 are the default pins, they should also work)

If that doesn't work you might want to use a logic analyzer (for the clock speeds of I2C a very cheap one is more than enough) and see what is happening on the wires

@jessebraham jessebraham added the bug Something isn't working label Nov 9, 2023
@elpiel
Copy link
Contributor

elpiel commented Nov 9, 2023

@bjoernQ I'm also experiencing issues with I2C async version.
After running a simple task for a few minutes by reading out the humidity and temp. from the Rust ESP32-C3 board I start getting ack. checks errors:

Combined: 27.001 °C / 77.862 %RH
Combined: 26.94 °C / 77.856 %RH
Combined: 26.98 °C / 77.891 %RH
Combined: 26.972 °C / 77.868 %RH
Combined: 26.969 °C / 77.871 %RH
Combined: 27.001 °C / 77.862 %RH
Combined: 26.988 °C / 77.865 %RH
Combined: 26.98 °C / 77.853 %RH
Combined: 26.969 °C / 77.864 %RH
Combined: 26.961 °C / 77.87 %RH
Combined: 26.988 °C / 77.885 %RH
Combined: 26.972 °C / 77.836 %RH
Combined: 26.98 °C / 77.873 %RH
Combined: 27.001 °C / 77.882 %RH
Combined: 26.969 °C / 77.851 %RH
Combined: 26.969 °C / 77.915 %RH
Combined: 26.969 °C / 77.861 %RH
Combined: 26.996 °C / 77.891 %RH
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)
(shtc3::start_measurement) Error: I2c(AckCheckFailed)

I've experiening issues with the IMU I2Csensor as well, though I'm not sure if it's only the esp-hal impl or a driver crate bug included in there, see PR #862

@bjoernQ
Copy link
Contributor

bjoernQ commented Nov 10, 2023

Thanks! Oh, I somehow missed #862 - need to look into that

@elpiel
Copy link
Contributor

elpiel commented Nov 10, 2023

Thanks! There's definitely something broken in I2C but I'm far from my equipment so can't provide you with further info.

@drbh
Copy link
Author

drbh commented Nov 10, 2023

@bjoernQ I've acquired a logic analyzer and got it working with saleae's Logic2 however I'm not 100% sure what I should be looking for 😅

I've written a simple program to request the IR data every second and then attached the logic analyzer to the SDA and SCL pins. Please see the schematic, screenshot and code below.

Schematic

This is how I've wired the analyzer to the circuit (I had to add a diode in order for the circuit to run... not sure if this can cause any issues).

 graph TD;

subgraph ESP32
GPIO21
GPIO22
GND_ESP
3V3
end

GPIO21 --- SDA
GPIO22 --- SCL
GND_ESP --- GND_MLX
3V3 --- VCC

subgraph MLX90614
SDA
SCL
GND_MLX
VCC
end


GND_MLX --- GND_LOGIC
SDA --- CH0
SCL --- DIODE_1N4148 --- CH1

subgraph DIODE_1N4148
end

subgraph LOGIC_ANALYZER
GND_LOGIC
CH0
CH1
end

Loading

Logic Analyzer Capture

I can see some communication on the wires but am not sure what a correct/incorrect patterns looks like

logic2-esp32-mlx90614

Program

#![no_std]
#![no_main]

use esp32_hal::{
    clock::ClockControl, entry, gpio::IO, i2c::I2C, peripherals::Peripherals, prelude::*, Delay,
};
use esp_backtrace as _;
use esp_println::println;

#[entry]
fn main() -> ! {
    // Initialize peripherals
    let peripherals = Peripherals::take();
    let system = peripherals.SYSTEM.split();
    let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
    let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);

    // Initialize I2C specific pins
    let sda = io.pins.gpio21;
    let scl = io.pins.gpio22;

    // Open I2C0
    let mut i2c = I2C::new(peripherals.I2C0, sda, scl, 100u32.kHz(), &clocks);

    // Delay configuration
    let mut delay = Delay::new(&clocks);

    println!("Scanning for devices...");
    // Scan for devices
    if let Ok(_) = i2c.write(0x5A, &[0x07]) {
        // 0x04 is the command to read the raw sensor data
        let to_send: [u8; 1] = [0x04];
        loop {
            let mut data = [0u8; 3];
            i2c.write_read(0x5A, &to_send, &mut data).ok();
            println!("Sent: 0x{:02X}, Received: {:02x?}", 0x00, data);
            delay.delay_ms(1000u32);
        }
    }

    loop {}
}

Thank you for the help 🙏

@bjoernQ
Copy link
Contributor

bjoernQ commented Nov 13, 2023

Great you got a logic analyzer. Will definitely be helpful in the future. Seems like for whatever reason the clock signal looks "interesting".

The Saleae software also contains a protocol decoder which you could use to make more sense of the signals but, in this case, SCL already looks suspicious.
SDA looks good.

Would be good if you could use different pin (32 or 33) as SDA and compare what the logic analyzer captures

@georgik
Copy link

georgik commented Nov 23, 2023

As I mentioned in #862, it's possible to simulate similar problem, by connecting ungrounded wire to PIN 8, or by touching the board.

It seems that I2C clocks are simply thrown out of balance.

Workaround: Decrease frequency of I2C to 2 kHz.

@elpiel
Copy link
Contributor

elpiel commented Nov 23, 2023

Possible suspect 1

fn master_write_read(
&mut self,
addr: u8,
bytes: &[u8],
buffer: &mut [u8],
) -> Result<(), Error> {
// it would be possible to combine the write and read
// in one transaction but filling the tx fifo with
// the current code is somewhat slow even in release mode
// which can cause issues
self.master_write(addr, bytes)?;
self.master_read(addr, buffer)?;
Ok(())
}
}
fn add_cmd<'a, I>(cmd_iterator: &mut I, command: Command) -> Result<(), Error>
where

icm42670 crate example

It's used both in async and current block Api for the crate:

   /// Read a register at the provided address.
    async fn read_reg_async(&mut self, reg: &dyn Register) -> Result<u8, Error<I2C::Error>> {
        let mut buffer = [0u8];
        self.i2c
            .write_read(self.address as u8, &[reg.addr()], &mut buffer)
            .await
            .map_err(|e| Error::BusError(e))?;

        Ok(buffer[0])
    }

Will try with lowered frequency next

@elpiel
Copy link
Contributor

elpiel commented Nov 23, 2023

at 2 kz

With a breadboard

20231123_183452

Without a breadboard

20231123_183524

@pedrominatel
Copy link
Member

I'm investigating this issue on the Rust board.

@pedrominatel
Copy link
Member

Hello guys,

I can reproduce it in different ways and the initial conclusion is the bus trace capacitance is too high.
The main reason for that is the trace length on both lines (SCL and SDA) and the trace path.

Screenshot 2023-11-24 at 10 28 25

As you can see here, the SCL (400kHz) signal is far from the ideal with the 10k resistor:
i2c_issue

Then I tested with 5k1 resistors and this is the result:
i2c-5k1

With the 5k1 resistor, I2C SCL @ 400kHz looks better and the issue is almost gone.

IMO, we need to fix the capacitance issue by removing the second GPIO8 pin on the left side, keeping the one on the right for the Feather pinout compatibility retracing both signals. The pullup resistor should be around 3k-5k.

For now, to reduce the I2C issue, you can change the 0402 pullups or add an external resistor 10k in parallel (current value is 10k) then you will have a 5k pullup, or reduce the clock on the I2C.

I'll start working on the hardware fix ASAP.

@drbh
Copy link
Author

drbh commented Nov 27, 2023

Thank you everyones help!

After much trial and error I was able to capture better samples of the i2c communication.

I believe the issue is related to the master_write_read method implementation. It appears that the write_read is implemented as two transactions rather than a single transaction (as seen in source and mentioned in the comment).

/// Write bytes from the `bytes` array first and then read n bytes into
/// the `buffer` array with n being the size of the array.
fn master_write_read(
&mut self,
addr: u8,
bytes: &[u8],
buffer: &mut [u8],
) -> Result<(), Error> {
// it would be possible to combine the write and read
// in one transaction but filling the tx fifo with
// the current code is somewhat slow even in release mode
// which can cause issues
self.master_write(addr, bytes)?;
self.master_read(addr, buffer)?;
Ok(())
}
}

Working Example Capture

Looking at a capture of working cpp code we can see the communication is:

The write:

START - ADDRESS - DATA 

then without a STOP the read is

START - ADDRESS - DATA - DATA - DATA - STOP

for completeness the full command flow is

START - ADDRESS - DATA - START - ADDRESS - DATA - DATA - DATA - STOP
write_read_one_tx

esp-rs Example Capture

The esp-rs implementation has two instances of STOP when trying to write_read

The full command flow

START - ADDRESS - DATA - STOP - START - ADDRESS - DATA - DATA - DATA - STOP

also its worth noting that there is a significant amount of time between the write and read while in the working example the read immediately follows.

write_read_two_tx

I'm not sure if this is the exact issue however it seems to be the major difference between the working example and this i2c impl.

Again, I am new to embedded so please let me know if this makes sense, or if I am on the wrong track 🙏

**I attempted to craft a working command flow by removing the Stop command in setup_write but don't have enough domain knowledge to make the changes needed..

Thank you!

@elpiel
Copy link
Contributor

elpiel commented Nov 27, 2023

I've also gave it a stab @drbh - #979

@drbh
Copy link
Author

drbh commented Nov 27, 2023

I've also gave it a stab @drbh - #979

awesome thank you! I just pulled it down and got similar results. However it appears that you're changes are for async i2c and I am currently not using embassy which I believe is needed for async?

Do you know if these changes will work in the sync case? Also quick note but it appears there is still a STOP command emitted as part of the write. My impressions was that a transaction has a single STOP so this does not reduce the two transactions into one...

@elpiel
Copy link
Contributor

elpiel commented Nov 27, 2023

I haven't tested my implementation but decided to share it because you commented on the issue.

And no I don't believe you can do this in the blocking version. In async you can wait for two futures too complete in parallel.

@drbh
Copy link
Author

drbh commented Nov 27, 2023

@elpiel got it, thank you for sharing I really appreciate the information and am going to use the code to help debug the issue further 🙏

@bjoernQ
Copy link
Contributor

bjoernQ commented Dec 7, 2023

@drbh the time between write and read seem to be huge. Are you running in release mode?

This is how it looks like for me (other i2c device so it looks different)

image

Maybe the MLX90614 just doesn't like the long pause between write and read

@bjoernQ
Copy link
Contributor

bjoernQ commented Dec 20, 2023

Is this resolved? Can we close this issue?

@drbh
Copy link
Author

drbh commented Dec 22, 2023

@bjoernQ unfortunately I still cannot read data from the MLX90614, you were right I was originally compiling in debug. Building release did improve the timing (shown below) but I still get a response of [ff, ff, ff]

The only difference between the arduino and rust logic output seems to be the number of transactions sent over the bus. I believe this is due to master_write_read being implemented as two transaction rather than one (note the example below has one more stop frame than the cpp example).

readingfff

It may make sense to close this issue since I cannot confirm that the issue is related to master_write_read and this issue has been open for a long time.

Thanks for all of the help!

@DeppLearning
Copy link

DeppLearning commented Feb 12, 2024

I think I am experiencing the same, or very similar issue. Please let me know if I should open another issue elsewhere. I am using different boards (esp32-s3 and esp32-c6 DevKitC-1) targeting a different I2C device (Adafruit Atecc608A, not that it seems to matter yet at this point) though. When I try a slightly adapted version of @drbh s code (chip has a config zone that can be locked, don't wont to write random commands and ruin the chip), the program gets stuck after 2 iterations of the for loop:

#![no_std]
#![no_main]

use esp32s3_hal::{clock::ClockControl, prelude::*, timer::TimerGroup, Delay, IO};
use esp_backtrace as _;
use esp_println::println;
use esp32s3_hal::i2c::I2C;

#[entry]
fn main() -> ! {
    esp_println::logger::init_logger(log::LevelFilter::Info);

    let peripherals = Peripherals::take();

    let system = peripherals.SYSTEM.split();
    
    let clocks = ClockControl::boot_defaults(system.clock_control).freeze();

    // Set up SCL & SDA
    let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
    let scl = io.pins.gpio1;
    let sda = io.pins.gpio2;

    // Construct I2C
    let mut i2c = I2C::new(peripherals.I2C0, scl, sda, 100u32.kHz(), &clocks);

    let mut delay = Delay::new(&clocks);

    for addr in 0..=127 {
        println!("Scanning Address {}", addr as u8);
    
        // Scan Address
        let res = i2c.read(addr as u8, &mut [0]);
    
        // Check and Print Result
        match res {
            Ok(_) => println!("Device Found at Address {}", addr as u8),
            Err(err) => println!("No Device Found: {:?}", err),
        }
    }

    loop {
        println!("Loop...");
        delay.delay_ms(500u32);

    }
}

Output of stuck program:

Scanning Address 0
No Device Found: AckCheckFailed
Scanning Address 1
No Device Found: AckCheckFailed
Scanning Address 2

I expected that it would run through the for-loop and get back with one device found. I didn't expect the reads to get hung up in any case.

I tried

  • with and without I2C device connected, same results
  • with different versions of esp32s3_hal (0.14.0, 0.15.0, current main branch), same results
  • on esp32s3 and esp32c6 boards
  • with and without breadboard (not touching it), same results
  • using different gpio pins (bunch of randoms, 1 & 2), same results
  • starting the for loop at different addresses, same results
  • repeatedly writing 0x00 at address 0x60 which is supposed to make the chip wake up and have it respond with some data. Same result at the read (writes don't come through either)
  • setting lto = "off" in my cargo.toml results in my for loop getting stuck one iteration earlier
  • using 50kHz I2C clock speed, it runs one iteration of the for loop less before it gets hung up
  • using 2kHz or 400kHz the loop runs through, however, I am only seeing AckCheckFailed on all addresses including the one where I am expecting the device according to it's specs (0x60), also my original problem persists :(

(I am new to embedded, I hope this counts as minimal example, my original goal is to get this library supported on my hardware but when trying to wake up the chip, the program either get's stuck or fails here https://github.com/BlackbirdHQ/at-cryptoauth-rs/blob/46db006c2da43e82bba4508e79e9db41bf84ce94/src/datalink.rs#L122)

@bjoernQ
Copy link
Contributor

bjoernQ commented Feb 13, 2024

I think I am experiencing the same, or very similar issue. Please let me know if I should open another issue elsewhere. I am using different boards (esp32-s3 and esp32-c6 DevKitC-1) targeting a different I2C device (Adafruit Atecc608A, not that it seems to matter yet at this point) though. When I try a slightly adapted version of @drbh s code (chip has a config zone that can be locked, don't wont to write random commands and ruin the chip), the program gets stuck after 2 iterations of the for loop:

#![no_std]
#![no_main]

use esp32s3_hal::{clock::ClockControl, prelude::*, timer::TimerGroup, Delay, IO};
use esp_backtrace as _;
use esp_println::println;
use esp32s3_hal::i2c::I2C;

#[entry]
fn main() -> ! {
    esp_println::logger::init_logger(log::LevelFilter::Info);

    let peripherals = Peripherals::take();

    let system = peripherals.SYSTEM.split();
    
    let clocks = ClockControl::boot_defaults(system.clock_control).freeze();

    // Set up SCL & SDA
    let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
    let scl = io.pins.gpio1;
    let sda = io.pins.gpio2;

    // Construct I2C
    let mut i2c = I2C::new(peripherals.I2C0, scl, sda, 100u32.kHz(), &clocks);

    let mut delay = Delay::new(&clocks);

    for addr in 0..=127 {
        println!("Scanning Address {}", addr as u8);
    
        // Scan Address
        let res = i2c.read(addr as u8, &mut [0]);
    
        // Check and Print Result
        match res {
            Ok(_) => println!("Device Found at Address {}", addr as u8),
            Err(err) => println!("No Device Found: {:?}", err),
        }
    }

    loop {
        println!("Loop...");
        delay.delay_ms(500u32);

    }
}

Output of stuck program:

Scanning Address 0
No Device Found: AckCheckFailed
Scanning Address 1
No Device Found: AckCheckFailed
Scanning Address 2

I expected that it would run through the for-loop and get back with one device found. I didn't expect the reads to get hung up in any case.

I tried

  • with and without I2C device connected, same results
  • with different versions of esp32s3_hal (0.14.0, 0.15.0, current main branch), same results
  • on esp32s3 and esp32c6 boards
  • with and without breadboard (not touching it), same results
  • using different gpio pins (bunch of randoms, 1 & 2), same results
  • starting the for loop at different addresses, same results
  • repeatedly writing 0x00 at address 0x60 which is supposed to make the chip wake up and have it respond with some data. Same result at the read (writes don't come through either)
  • setting lto = "off" in my cargo.toml results in my for loop getting stuck one iteration earlier
  • using 50kHz I2C clock speed, it runs one iteration of the for loop less before it gets hung up
  • using 2kHz or 400kHz the loop runs through, however, I am only seeing AckCheckFailed on all addresses including the one where I am expecting the device according to it's specs (0x60), also my original problem persists :(

(I am new to embedded, I hope this counts as minimal example, my original goal is to get this library supported on my hardware but when trying to wake up the chip, the program either get's stuck or fails here https://github.com/BlackbirdHQ/at-cryptoauth-rs/blob/46db006c2da43e82bba4508e79e9db41bf84ce94/src/datalink.rs#L122)

This doesn't seem to be related to the issue here and probably it's better to create a separate issue for it

@jessebraham jessebraham added the peripheral:i2c I2C peripheral label Mar 12, 2024
@jessebraham
Copy link
Member

This issue has grown stale, and I'm not sure there's anything actionable here, so gonna go ahead and close this. Everybody involved, please feel free to open a new issue if you are still experiencing any problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working peripheral:i2c I2C peripheral
Projects
Archived in project
Development

No branches or pull requests

7 participants