Write data to register with i2c in python

Question:

I need to change value in MLX96014 temperature sensors eeprom with raspberry pi and python. I can read its ram and eeprom without problems, but I cant write to it. Also every python MLX96014 library that I find dont have this function implemented for some reason. I tried to do this with arduino and it works great with this function:

void Adafruit_MLX90614::write16(uint8_t a, uint16_t v) {
  // a is register address
  // v value to write to eeprom 
  // _addr is device address (0x5a)
  uint8_t pec;
  uint8_t pecbuf[4];

  pecbuf[0] = _addr << 1;
  pecbuf[1] = a;
  pecbuf[2] = v & 0xff;
  pecbuf[3] = v >> 8;
  pec = crc8(pecbuf, sizeof pecbuf);

  Wire.beginTransmission(_addr); // start transmission to device
  Wire.write(a);                 // sends register address to write
  Wire.write(v & 0xff);          // lo
  Wire.write(v >> 8);            // hi
  Wire.write(pec);               // pec
  Wire.endTransmission(true);    // end transmission
}

So I tried to rewrite this function in python:

import board
import busio as io
import adafruit_mlx90614
import time
from smbus2 import SMBus, i2c_msg
import crc8
import sys

i2c = io.I2C(board.SCL, board.SDA, frequency=100000)
mlx = adafruit_mlx90614.MLX90614(i2c)

buf = bytearray(4)
buf[0] = 0x5a<<1
buf[1] = 0x24
buf[2] = 0 & 0xff
buf[3] = 0 >>8
pec = crc8.crc8()
pec.update(buf)
pec = pec.hexdigest() # = 0x28

i2c.writeto(0x5a, bytes([0x24]), stop=False)
buffer = bytearray(3)
buffer[0] = 0 & 0xFF
buffer[1] = (0 >> 8) & 0xFF
buffer[2] = 0x28
i2c.writeto(0x5a, buffer, stop=True)

i2cbus = SMBus(1)
emissivity=i2cbus.read_word_data(0x5a,0x24)
print(emissivity) # prints 65535 which is default

Code executes without errors. i2c.writeto() returns "None". So what im missing there?

Edit:

I found this (link) in datasheet but it confuses me. In datasheet it says that write comand bit is low and read is high. But in example both operations uses low. Also it looks like im supposed to send 0xb4 byte instead of 0x5a, but where to put it in pyhton code? If I put it in i2c.writeto() first parameter then I get I/O error because module is on address 5a (i2cdetect shows that).

By the way, I dont have access to osciloscope right now.

communication example

Asked By: PauM

||

Answers:

I dont know exactly why provided python code doesnt work but I have tried other i2c library and it started working. Here is the code snippet:

import board
import busio as io
import crc8
import adafruit_mlx90614
import adafruit_bus_device.i2c_device as ada_i2c
import time

def change_emissivity(value,i2c):
    new_emissivity=round(65535*value)
    buf=bytearray(4)
    buf[0]=0x24
    buf[1]=0x00
    buf[2]=0x00
    buf[3]=0x28  # kai irasomi nuliai
    
    device=ada_i2c.I2CDevice(i2c,0x5a)
    
    with device:
        device.write(buf)
        
    time.sleep(0.01)
    
    buf[0]=0x5a<<1
    buf[1]=0x24
    buf[2]=new_emissivity & 0xff
    buf[3]=(new_emissivity >> 8) & 0xFF
    pec=crc8.crc8()
    pec.update(buf)
    pec=int(pec.hexdigest(),base=16)
    
    buf[0]=0x24
    buf[1]=new_emissivity & 0xff
    buf[2]=(new_emissivity >> 8) & 0xFF
    buf[3]=pec
    
    print(new_emissivity)
    
i2c = io.I2C(board.SCL, board.SDA, frequency=100000)
mlx = adafruit_mlx90614.MLX90614(i2c)
change_emissivity(0.8, i2c)

print("New emissivity: %.2f" %mlx._read_16(0x24))

while(True):
    
    print("Ambient Temp: %.2f" %mlx.ambient_temperature
    print("Object Temp: %.2f" %mlx.object_temperature

    time.sleep(3)

Answered By: PauM

Dont know if anyone will answer to that, but i tried code from answer and now my MLX is useless…

Code did change the emissivity but now im getting max values like 380 or -120 C…

How can i fix it back to where it was?

Answered By: Rubber
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.