Closed rdtaps closed 2 years ago
Can you please retest on megaTinyCore 2.4.2 so that we know whether it is an old bug that predates the near-complete reimplementation of Wire (and thus that @MX682X was reimplementing incorrect behavior) or whether it is a new bug introduced in the 2.5.x versions?
Without knowing that it's hard to know what to look for in fixing it.
Thanks
Version megaTinyCore 2.4.2 with Adafruit_MLX90614 mlxtest example not linked.
_C:\Users\roman\AppData\Local\Temp\ccZ7Nfh4.ltrans0.ltrans.o: In function `main':
Lovely, another user besides me having problems with this sensor and Attiny1614.
Jokes aside, the reason I started looking into the library was because of this sensor. When I tried to change the clock, I found the first bug in the old library that locked it up. Then I though, screw it, you can rewrite the rest too...
Anyway, what helped me was changing the Clockspeeds to 120 or 125kHz - weird numbers I know, especially since it is documentated to only work up to 100kHz. But for some weir reason, basically all other frequencies were getting a NACK on my end too. I measured all the timings, too. Of course, you might try to do an Wire.endTransmission(true), which would add a STOP after the Write.
If it helps, my MLX is a DAA5366913
Edit: that is basically the code I used to interact with the sensor,
#include "Wire.h"
uint16_t i = 0;
int16_t tempA;
int16_t tempO;
void setup() {
Serial1.begin(500000);
Wire.begin();
Wire.setClock(125000);
}
void loop() {
digitalWrite(PIN_PC6, HIGH); // Activity
tempA = getTempAmbient();
tempO = getTempObject();
digitalWrite(PIN_PC6, LOW);
Serial1.print(tempA);
Serial1.print(" ");
Serial1.println(tempO);
}
int16_t getTempAmbient()
{
return (getData(0x06) * 2) - 27315;
}
int16_t getTempObject()
{
return (getData(0x07) * 2) - 27315;
}
uint16_t getData(uint8_t reg)
{
Wire.beginTransmission(0x5A);
Wire.write(reg);
Wire.endTransmission(false);
Wire.requestFrom(0x5A, 3, 1);
while (Wire.available() < 3) {}
uint8_t lsb = Wire.read();
uint8_t msb = Wire.read();
Wire.read(); //pec
return (uint16_t) ((msb<<8) | lsb) ;
}
Thank you so much.
I set the clock speed to 110kHz and the sensor works. It's crazy. I don't understand why it works properly with other chips? I tested the sensor with Arduino Nano, Attiny85, Esp32-wroom at 100kHz and it always worked.
I enclose a comparison of communication on i2c.
No Problem!
Since you pointed out that there is quite some time between start and actual sending of bytes, I think the problem lies in the way the TWi module was implemented Hardware wise. When an address is written to the register, the TWI module takes care of sending the START condition and the address. I guess the statemashine of the TWI is clocked by the same prescaler that is used for the SCL generation.
The Sensor is SMBus compatible and they have some timeouts in the specification. I'm not sure how exactly Melexis implemented the sensor though, but if they check the time between two bytes, an increase of the frquency might be enough to not trigger the TO on the sensor, while a too big frequency (>130kHz) is too far out of specs and doesn't work there either.
Best thing to do: Add a notice to the TWI readme about the fact that there is quite some time between START and Address that might confuse some devices in a REPSTART transaction. Workaround: Send Stop after a write/ increase frequency.
Wire.endTransmission(true) - Stop bit does not work after writing. I also tested this on Arduino Nano, Attiny85, Esp32-wroom. The Adafruit library therefore uses the function - _i2c_dev->write_thenread(buffer, 1, buffer, 3) with default bool stop=false.
Thank you for trying it out. I guess it just confirms that the SM is just too slow? I don't know how else the MCu is ignoring this line in the Master_Write function
if ((send_stop != 0) || (TWI_ERR_SUCCESS != TWI_GET_ERROR)) {
module->MCTRLB = TWI_MCMD_STOP_gc; // Send STOP
}
return TWI_GET_ERROR;
but still sends STOPs when there is no Master_Read after that. If you want to help confirming it (I would have to set up the stuff first), add a delay of 1ms between Wire.endTransmission(true) and Wire.requestFrom() at 100kHz.
I set a delay of 1ms between Wire.endTransmission(true) and Wire.requestFrom() at 100 kHz. The returned values are incorrect. (255,255,255) It looks like the sensor responds to a stop bit with a data loss.
This is clearly a very picky part and that causes a lot of problems. I don't understand why, but the long delays in the start and stop conditions are suspicious as is the very narrow spike near the end of the first byte I do not know if any of those are something that can be addressed on the current silicon.
The sensor works at 110kHz. I've been testing for the last 24 hours and no transmission error. I suggest closing the issue.
Attiny1614, 20MHz internal, 5V, pullup 4k7 on SDA,SCL, serialUPDI 230400 CH340 Win
Unable to communicate with mlx90614 sensor via i2c. I tested with the Adafruit_MLX90614 library and also tried my own. A communication error occurs when calling the following sequence of functions.
Adafruit library
uint16_t Adafruit_MLX90614::read16(uint8_t a) { uint8_t buffer[3]; buffer[0] = a; bool status = i2c_dev->write_then_read(buffer, 1, buffer, 3); if (!status) return 0; return uint16_t(buffer[0]) | (uint16_t(buffer[1]) << 8); }
bool Adafruit_I2CDevice :: write_then_read (const uint8_t write_buffer, size_t write_len, uint8_t read_buffer, size_t read_len, bool stop) { if (! write (write_buffer, write_len, stop)) { return false; } return read (read_buffer, read_len); }
Or my own library .. Wire.beginTransmission ((uint8_t) _i2caddr); Wire.write (buffer [0]); Wire.endTransmission (false); bool status = read (buffer, 3);
bool MLX90614 :: read (uint8_t * buffer, uint8_t len) { if (Wire.requestFrom ((uint8_t) _i2caddr, (uint8_t) len) == 0) return false; for (uint16_t i = 0; i <len; i ++) buffer [i] = Wire.read (); return true; }
The problem is writing without stop bit and then reading.
Both examples work on Arduino Nano and Attiny85. I also tried other sensors (BME280, SHT35, etc.) and they work well. But there, the write is always followed by a stop bit and then a read.
I enclose a record of this communication using a logic analyzer. There is a long delay between the end of writing and the beginning of reading on Attiny1614.
Thanks in advance for your help.
attiny1614-mlx90614
nano-mlx90614
Saleae Logic.zip