Closed Makodan closed 6 years ago
Hi, this does not make sense. How did you verify that the extracted parameters are correct? Did you check the register reading with an oscilloscope. It looks a bit like you are reading a different address or the data is not properly aligned. Could you please check the I2C with an oscilloscope? Could you share your I2C driver?
Best regards
Thank you for your answer! The scale of extracted parameters are similar to the example parameters. E.g. kVdd = -3904, vdd25 = -11296 The reader function:
int MLX90640_I2CRead(uint8_t slave_address, uint16_t start_address,
uint16_t numb_words, uint16_t *data) {
if (HAL_I2C_Mem_Read(&hi2c1, slave_address, start_address,
I2C_MEMADD_SIZE_16BIT, (uint8_t *) data, 2*numb_words, 500) == HAL_OK) {
return 0;
}
else {
return -1;
}
The writer:
int MLX90640_I2CWrite(uint8_t slave_address, uint16_t write_address,
uint16_t data) {
uint16_t data_check;
if (HAL_I2C_Mem_Write(&hi2c1, slave_address, write_address,
I2C_MEMADD_SIZE_16BIT, (uint8_t*) &data, sizeof(data), 200) != HAL_OK) {
return -1;
}
else {
MLX90640_I2CRead(slave_address, write_address, 2, &data_check);
if (data_check == data) {
return 0;
}
else {
return -2;
}
}
}
After a lot of thinking I came the same conclusion, maybe I write and read to/from wrong addresses, or the data is not properly aligned. I will try to get an oscilloscope, or at least a digital analyzer and I will check the communication, after that I will post the result. What do you think, are the i2c driver functions right?
The functions seem to be OK. Can you share a log of frameData? While you are checking with analyzer or an oscilloscope, I could check the data for something suspicious.
Best regards
I check the I2C waveforms with oscilloscope, the write function and the read function both was bad. I did not make screenshot, but I write down the values.
Write function, 0x0901 value to the 0x800D (a - acknowledge): Start|0x66|a|0x80|a|0x0D|a|0x01|a|0x09|a| As we can see MSB and LSB are in reverse order.
The waveform of the read function is good, but the processing is bad. The function puts the data into the array in reverse order too.
After I fix it, I will write.
Thanks for being so helpful! Best regards
It more or less fits with my suspicion. I could not find a setting for the HAL function to use big-endian storage rather than little-endian so I assumed it simply reads and stores the data as on the bus. It is still a bit strange though, as I would expect that the same arrangement would be applied to the EERPOM and frame data. Thus the parameters should also be wrong.
Okay, I fixed it. I did it rather with low level functions. There is the output. ( my hand, 640x480 pixel interpolated image, made with OpenCV)
There are the I2C read and write functions:
uint16_t MLX90640_I2CReadWord(uint8_t slave_address, uint16_t start_address) {
uint16_t puff;
volatile uint8_t reg_m,reg_l,dat_m,dat_l;
reg_m = (uint8_t) ((start_address & 0xFF00) >> 8); //Address MSB
reg_l = (uint8_t) (start_address & 0x00FF); //Address LSB
while (LL_I2C_IsActiveFlag_BUSY(I2C1)) {
}
//LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_ACK);
LL_I2C_GenerateStartCondition(I2C1);
while (!LL_I2C_IsActiveFlag_SB(I2C1)) {
}
//Send device address
LL_I2C_TransmitData8(I2C1, slave_address);
while (!LL_I2C_IsActiveFlag_ADDR(I2C1)) {
}
LL_I2C_ClearFlag_ADDR(I2C1);
while (!LL_I2C_IsActiveFlag_TXE(I2C1)) {
}
//Send start address MSB
LL_I2C_TransmitData8(I2C1, reg_m);
while (!LL_I2C_IsActiveFlag_TXE(I2C1)) {
}
//Send start address LSB
LL_I2C_TransmitData8(I2C1, reg_l);
while (!LL_I2C_IsActiveFlag_TXE(I2C1)) {
}
//Repeat start condition
LL_I2C_GenerateStartCondition(I2C1);
while (!LL_I2C_IsActiveFlag_SB(I2C1)) {
}
//Send device address again + read
LL_I2C_TransmitData8(I2C1, slave_address | 0x01);
while (!LL_I2C_IsActiveFlag_ADDR(I2C1)) {
}
//Read out data MSB, send ACK
LL_I2C_ClearFlag_ADDR(I2C1);
LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_ACK);
while (!LL_I2C_IsActiveFlag_RXNE(I2C1)) {
}
dat_m = LL_I2C_ReceiveData8(I2C1);
//Read out data LSB, send NACK
while (!LL_I2C_IsActiveFlag_RXNE(I2C1)) {
}
dat_l = LL_I2C_ReceiveData8(I2C1);
LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_NACK);
LL_I2C_GenerateStopCondition(I2C1);
return ((uint16_t) (dat_m << 8)) | ((uint16_t)((dat_l) & 0x00FF));
}
int MLX90640_I2CRead(uint8_t slave_address, uint16_t start_address,
uint16_t numb_words, uint16_t *data){
uint16_t temp_address = start_address;
uint16_t temp_data;
for(int i=0; i < numb_words; i++){
temp_data = MLX90640_I2CReadWord(slave_address,temp_address);
temp_address++;
*(data + i) = temp_data;
}
return 0;
}
void MLX90640_I2CFreqSet(int freq) {
//i2c.frequency(1000*freq);
}
int MLX90640_I2CWrite(uint8_t slave_address, uint16_t start_address,
uint16_t data) {
uint8_t reg_m,reg_l,dat_m,dat_l;
reg_m = (uint8_t) ((start_address & 0xFF00) >> 8); //Address MSB
reg_l = (uint8_t) (start_address & 0x00FF); //Address LSB
dat_m = (uint8_t) ((data & 0xFF00) >> 8); // Data MSB
dat_l = (uint8_t) (data & 0x00FF); //Data LSB
//reg_m = 0x80;
//reg_l = 0x0D;
//dat_m = 0x09;
//dat_l = 0x01;
//Check bus busy flag
while (LL_I2C_IsActiveFlag_BUSY(I2C1)) {
}
LL_I2C_GenerateStartCondition(I2C1);
while (!LL_I2C_IsActiveFlag_SB(I2C1)) {
}
//Send device address
LL_I2C_TransmitData8(I2C1, slave_address);
while (!LL_I2C_IsActiveFlag_ADDR(I2C1)) {
}
LL_I2C_ClearFlag_ADDR(I2C1);
while (!LL_I2C_IsActiveFlag_TXE(I2C1)) {
}
//Send write address MSB
LL_I2C_TransmitData8(I2C1, reg_m);
while (!LL_I2C_IsActiveFlag_TXE(I2C1)) {
}
//Send write address LSB
LL_I2C_TransmitData8(I2C1, reg_l);
while (!LL_I2C_IsActiveFlag_TXE(I2C1)) {
}
//Send data MSB
LL_I2C_TransmitData8(I2C1, dat_m);
while (!LL_I2C_IsActiveFlag_TXE(I2C1)) {
}
//Send data LSB
LL_I2C_TransmitData8(I2C1, dat_l);
while (!LL_I2C_IsActiveFlag_BTF(I2C1)) {
}
LL_I2C_GenerateStopCondition(I2C1);
return 0;
}
Hi @Makodan : I did this with your read and write functions,but it still not work.It will stop here:
//Send device address
LL_I2C_TransmitData8(I2C1, slave_address);
while (!LL_I2C_IsActiveFlag_ADDR(I2C1)) {
}
LL_I2C_ClearFlag_ADDR(I2C1);
But the slave_address was right,I detect it with my raspberry pi.So I don't know why it can't works!Can you give me some advices?I use whole day to do it,but I waste the day...
Hi @imliubo! What kind of device do you use? There are some difference between STM32F and STM32L family's LL library
Hi @Makodan Thanks for reply me.I use STM32F405RGT6 MCU to do it.Do you have any advices?I open a repositry want to slove it,can you share your code with LL functions?I just completed the code to read the temperature value in SWI2C mode. MLX90640-With-STM32
Hello!
I have an interesting problem. I tried to port the driver onto STM32 board. I rewrote the mlx90640_i2c_driver.
With my code, I can dump calibration data, then extract the parameters, and them seem correct. But the "MLX90640_GetFrameData" always stuck in a while loop, because the status register's data ready bit will never be 1.
In debug mode I can clearly see that the status register is always 0x0900.
I tried to solve it with direct register writings:
I noticed another interesting thing, if I write the control register, I can read back the correct value (e.g. 0x1901), so I think I2C communication is OK. But if I write the status register (e.g. 0x0930), I always read back 0x0900. I have two senors, but both produce this (error). Do you have any idea? Thanks
Edit: If I write 0x0901 to control register, i read out 0x0800 from the status register, I don't write to the status register, but new data never comes.