MLX90161 IR Thermometer I2C problems - Page 1
Forum section: electronics / general

author: OliverK
author_rank: Contributor
timestamp: June 09, 2017, 07:41:30 pm
content: Code:With a samd 21 i want to read the object temperture of an mlx90616 thermometer. In the datasheet i found that the slave adress is 0x00 but if i google about the mlx90161 i find that the slave adress is 0x5A (even in the arudino IDE), doest anybody know why they are diffent? The RAM adress (where the object temp is begin written to) of the MLX90616 is 0x07. In the datasheet i found how i needed to read the memory : Start bit : slave adress + W : A (from slave): Write byte (RAM memory) : A (from slave) : Start repeat slave adress + R: Upper byte : A (from Master) : Lowerbite (ack master) : PEC : A/N : stop bitI need to keep doing this sequeal to read out the object temp (i want to do it every sencond for as long as uc is powerd), and it would be awsome if i could print the value in the seriel monitor with uartI how do i set the clock frequentie to 100kHz (MLX90616 works betweens 10 and 100kHz)I want to know if its also possible to stop the I2C read after the lower byte is send instead of after the PEC?I tryied using ASF but i dont really understand it? Cant figure out how i need to rewrite the code to make it fit for my project.This was the example code for asf i2c : [http://www.atmel.com/Images/Atmel-42631-SAM-D21-SERCOM-I2C-Configuration_ApplicationNote_AT11628.pdf]Could anybody help me writing this code (would like to do it without asf)?

author: OliverK
author_rank: Contributor
timestamp: June 09, 2017, 07:47:28 pm
content: sorry forgot but ive already withen this code, is this any good?Code:#include <stdlib.h>#include <stdint.h>#include <stdbool.h>#include <string.h>#include "samd21.h"#include "hal_gpio.h"#include "component/sercom.h"#define I2C_ADDRESS 0x00#define RAM_ADDRESS0x07#define I2C_SERCOM SERCOM2#define I2C_SERCOM_PMUX PORT_PMUX_PMUXE_D_Val#define I2C_SERCOM_GCLK_ID SERCOM2_GCLK_ID_CORE#define I2C_SERCOM_CLK_GEN 0#define I2C_SERCOM_APBCMASK PM_APBCMASK_SERCOM2#define T_RISE 215e-9 // Depends on the board, actuallyenum{I2C_TRANSFER_WRITE = 0,I2C_TRANSFER_READ = 1,};enum{I2C_PINS_SDA = (1 << 0),I2C_PINS_SCL = (1 << 1),};//-----------------------------------------------------------------------------static void sys_init(void) // enable 8Mhz OSC, no prescaler{SYSCTRL->OSC8M.bit.PRESC = 0;}//-----------------------------------------------------------------------------int i2c_init(int freq){int baud = ((float)F_CPU / freq - (float)F_CPU * T_RISE - 10.0) / 2.0;if (baud < 0)baud = 0;else if (baud > 255)baud = 255;freq = (float)F_CPU / (2.0 * (5.0 + baud) + (float)F_CPU * T_RISE);PM->APBCMASK.reg |= I2C_SERCOM_APBCMASK;GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(I2C_SERCOM_GCLK_ID) |GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(I2C_SERCOM_CLK_GEN);I2C_SERCOM->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_SWRST;while (I2C_SERCOM->I2CM.CTRLA.reg & SERCOM_I2CM_CTRLA_SWRST);I2C_SERCOM->I2CM.CTRLB.reg = SERCOM_I2CM_CTRLB_SMEN;while (I2C_SERCOM->I2CM.SYNCBUSY.reg);I2C_SERCOM->I2CM.BAUD.reg = SERCOM_I2CM_BAUD_BAUD(baud);while (I2C_SERCOM->I2CM.SYNCBUSY.reg);I2C_SERCOM->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_ENABLE |SERCOM_I2CM_CTRLA_MODE_I2C_MASTER |SERCOM_I2CM_CTRLA_SDAHOLD(3);while (I2C_SERCOM->I2CM.SYNCBUSY.reg);I2C_SERCOM->I2CM.STATUS.reg |= SERCOM_I2CM_STATUS_BUSSTATE(1);return freq;}//-----------------------------------------------------------------------------bool i2c_read(uint8_t *data, int size){// Start + Slave_adress + write (ten ack from slave)// master send RAM adress to read from ( ten ack from slave)// repeted start +read bit (ack slave)// read slave lowebit from slave (ack master)// read save upperbit slave (ack master)// read pec form slave (ack master)// stopI2C_SERCOM->I2CM.ADDR.reg = I2C_ADDRESS | I2C_TRANSFER_WRITE; // I2C adress = 0x00 eni2c wirte = 0x07while (0 == (I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_MB));if (I2C_SERCOM->I2CM.STATUS.reg & SERCOM_I2CM_STATUS_RXNACK){I2C_SERCOM->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);//dbg_log("I2C: RXNACK during write (address)\r\n");return false;}I2C_SERCOM->I2CM.DATA.reg = RAM_ADDRESS; // send ram adrees bytewhile (0 == (I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_MB));if (I2C_SERCOM->I2CM.STATUS.reg & SERCOM_I2CM_STATUS_RXNACK){I2C_SERCOM->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);//dbg_log("I2C: RXNACK during write (data)\r\n");return false;}I2C_SERCOM->I2CM.ADDR.reg = I2C_ADDRESS | I2C_TRANSFER_READ;while (0 == (I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_SB));if (I2C_SERCOM->I2CM.STATUS.reg & SERCOM_I2CM_STATUS_RXNACK){I2C_SERCOM->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);return false;}I2C_SERCOM->I2CM.CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT;for (int i = 0; i < size-1; i++) // read lower bite, upper bite and pec{data = I2C_SERCOM->I2CM.DATA.reg;while (0 == (I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_SB));}if (size){I2C_SERCOM->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT;I2C_SERCOM->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3);data[size-1] = I2C_SERCOM->I2CM.DATA.reg;}if ((I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_MB) ||(I2C_SERCOM->I2CM.INTFLAG.reg & SERCOM_I2CM_INTFLAG_SB)){I2C_SERCOM->I2CM.CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3); // stop bit}return true;}/*Assigning pin to the alternate peripheral function*/static inline void pin_set_peripheral_function(uint32_t pinmux){uint8_t port = (uint8_t)((pinmux >> 16)/32);PORT->Group.PINCFG[((pinmux >> 16) - (port*32))].bit.PMUXEN = 1;PORT->Group.PMUX[((pinmux >> 16) - (port*32))/2].reg &= ~(0xF << (4 * ((pinmux >> 16) & 0x01u)));PORT->Group.PMUX[((pinmux >> 16) - (port*32))/2].reg |= (uint8_t)((pinmux & 0x0000FFFF) << (4 * ((pinmux >> 16) & 0x01u)));}/* I2C pin initialization */void i2c_pin_init(){/* PA08 and PA09 set into peripheral function D*/pin_set_peripheral_function(PINMUX_PA08D_SERCOM2_PAD0); // SDApin_set_peripheral_function(PINMUX_PA09D_SERCOM2_PAD1); // SCL}int main(void){uint16_t value;uint8_t buf;float temp;sys_init();i2c_init(8000000);i2c_read(buf, 4);value = ((uint16_t)buf << 8) | buf; // combining the upper and lower byte value into a 16bit value// convert to temp hex to decimal, devide bij 50 and subsitute 273 (Kelvin to C)temp = ( (float)value/ (float)50) - (float)273;while (1){}return 0;}

author: kenny
author_rank: Newbie
timestamp: June 13, 2017, 01:05:31 pm
content: Do you know how to decode the output stream on the serial port for this device? i've been looking online and this is the first info i've found related to it. thanks

author: OliverK
author_rank: Contributor
timestamp: June 15, 2017, 02:29:40 pm
content: What do u mean with seriele stream from usart? I2C or what?