TransWikia.com

MLX90615 Sensor for Raspberry Pi 3 Model B

Raspberry Pi Asked by hossein nakhaeipoor on November 11, 2021

i have connected mlx90615 Thermometer module to my raspberry i2c pins
but i was not able to find any code or guidance on how to receive measured temperatures from the sensor (i2c bus)
but there are some libraries and code snippets for arduino
i tried a lot to port arduino library to raspberry but every time i run the code the result is the same
this is arduino library
and this is the code that i wrote for raspberry according to the mentioned library :

#include <stdio.h>
#include <stdint.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>

#define SDA_PIN 8   //define the SDA pin (8 is wiringPi pin for raspberry pin 3)
#define SCL_PIN 9   //define the SCL pin (9 is wiringPi pin for raspberry pin 5)

#define i2c_addr 0x5b

#define MLX90615_OBJECT_TEMPERATURE     0x27
#define MLX90615_AMBIENT_TEMPERATURE    0x26

uint8_t const I2C_DELAY_USEC = 4;
uint8_t const I2C_READ = 1;
uint8_t const I2C_WRITE = 0;

typedef unsigned char byte;

uint8_t read(uint8_t);
bool restart(uint8_t);
bool start(uint8_t);
void stop(void);
bool write(uint8_t);
float getTemperature(int);


int main()
{

    printf("RESULT : %fn",getTemperature(MLX90615_AMBIENT_TEMPERATURE));

    return 0;
}

float getTemperature(int Temperature_kind) {

    wiringPiSetup();

    pinMode(SDA_PIN, OUTPUT);
    digitalWrite(SDA_PIN, HIGH);
    pinMode(SCL_PIN, OUTPUT);
    digitalWrite(SCL_PIN, HIGH);

    //wiringPiI2CSetup(0x5b);
    byte dev = (i2c_addr << 1);  // remain to be seen!
    byte dataLow = 0;
    byte dataHigh = 0;
    float celcius = 0.0;

    start(dev | I2C_WRITE);
    write(Temperature_kind);

    // read
    restart(dev | I2C_READ);
    dataLow = read(false);
    dataHigh = read(false);
    read(true);
    stop();
    //This converts high and low bytes together and processes temperature,       MSB is a error bit and is ignored for temps
    double tempFactor = 0.02; // 0.02 degrees per LSB (measurement resolution of the MLX90614)
    double tempData = 0x0000; // zero out the data

    // This masks off the error bit of the high byte, then moves it left 8 bits and adds the low byte.
    tempData = (double)(((dataHigh & 0x007F) << 8) | dataLow);
    tempData = (tempData * tempFactor) - 0.01;

    celcius = (float)(tempData - 273.15);

    return celcius;
    //float fahrenheit = (celcius*1.8) + 32;
 }

uint8_t read(uint8_t last) {
    uint8_t b = 0;
    // make sure pull-up enabled
    digitalWrite(SDA_PIN, HIGH);
    pinMode(SDA_PIN, INPUT);
    // read byte
    for (uint8_t i = 0; i < 8; i++) {
        // don't change this loop unless you verify the change with a scope
        b <<= 1;
        delayMicroseconds(I2C_DELAY_USEC);
        digitalWrite(SCL_PIN, HIGH);
        if (digitalRead(SDA_PIN)) b |= 1;
        digitalWrite(SCL_PIN, LOW);
    }
    // send Ack or Nak
    pinMode(SDA_PIN, OUTPUT);
    digitalWrite(SDA_PIN, last);
    digitalWrite(SCL_PIN, HIGH);
    delayMicroseconds(I2C_DELAY_USEC);
    digitalWrite(SCL_PIN, LOW);
    digitalWrite(SDA_PIN, LOW);

    return b;
}
//--------------------------------------------------------------------------    ----
/** Issue a restart condition.
*
* param[in] addressRW I2C address with read/write bit.
*
* return The value true, 1, for success or false, 0, for failure.
*/
bool restart(uint8_t address) {
    digitalWrite(SDA_PIN, HIGH);
    digitalWrite(SCL_PIN, HIGH);
    delayMicroseconds(I2C_DELAY_USEC);
    return start(address);
}
//------------------------------------------------------------------------------
/** Issue a start condition.
*
* param[in] addressRW I2C address with read/write bit.
*
* return The value true, 1, for success or false, 0, for failure.
*/
bool start(uint8_t address) {
    digitalWrite(SDA_PIN, LOW);
    delayMicroseconds(I2C_DELAY_USEC);
    digitalWrite(SCL_PIN, LOW);
    return write(address);
}
//------------------------------------------------------------------------------
/**  Issue a stop condition. */
void stop(void) {
    digitalWrite(SDA_PIN, LOW);
    delayMicroseconds(I2C_DELAY_USEC);
    digitalWrite(SCL_PIN, HIGH);
    delayMicroseconds(I2C_DELAY_USEC);
    digitalWrite(SDA_PIN, HIGH);
    delayMicroseconds(I2C_DELAY_USEC);
}
//------------------------------------------------------------------------------
/**
* Write a byte.
*
* param[in] data The byte to send.
*
* return The value true, 1, if the slave returned an Ack or false for Nak.
*/
bool write(uint8_t data) {
    // write byte
    for (uint8_t m = 0X80; m != 0; m >>= 1) {
        // don't change this loop unless you verify the change with a scope
        digitalWrite(SDA_PIN, m & data);
        digitalWrite(SCL_PIN, HIGH);
        delayMicroseconds(I2C_DELAY_USEC);
        digitalWrite(SCL_PIN, LOW);
    }
    // get Ack or Nak
    pinMode(SDA_PIN, INPUT);
    // enable pullup
    digitalWrite(SDA_PIN, HIGH);
    digitalWrite(SCL_PIN, HIGH);
    uint8_t rtn = digitalRead(SDA_PIN);
    digitalWrite(SCL_PIN, LOW);
    pinMode(SDA_PIN, OUTPUT);
    digitalWrite(SDA_PIN, LOW);
    return rtn == 0;
}

as i mentioned before the problem with the above code is that the result is always “382.179993”
i have also checked my i2c connection and device address with i2cdetect -y 1 and everything is good but i have been stuck about receiving the correct temperature value!
note that for converting arduino code to be used in raspberry i used wiringPi Library
any help will be highly appreciated…(i have been stuck here for more than one week!!)

One Answer

I may have your solution. It appears that the MLX90615 requires 2 start bits (the second being classified as the "Repeated Start Condition" in the MLX90615 spec sheet). By default, I believe the RPi only sends the first. So you have to configure it to send the second. This is the command line code I found elsewhere on the net:

sudo su -

echo -n 1 > /sys/module/i2c_bcm2708/parameters/combined

exit

Good luck!

Answered by Larry Garber on November 11, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP