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!!)
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
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP