Go Down

Topic: Need help getting the MAX9611 correct (Read 1 time) previous topic - next topic

combib

Dec 26, 2012, 05:15 am Last Edit: Jan 03, 2013, 03:21 am by combib Reason: 1
Could please help me. I am using the Arduino UNO and a Maxim MAX9611, the communication is i2C with the Wire.h I am confused where to start. I understand I2c but need getting communication correct between UNO & MAX9611. How to I start talking to the MAX9611 and reading the information? The datasheet is at the following website http://datasheets.maximintegrated.com/en/ds/MAX9611-MAX9612.pdf

Nick Gammon


combib

I do understand i2c, but my difficulty is the structure talking to the MAX9611

Nick Gammon

Have you tried anything? What is "my difficulty" exactly?

What have you tried?

I would expect at this stage to see a bit of code where you initialize I2C, try to communicate with the device at the documented address, try to read a register, that sort of thing.

combib

#4
Dec 26, 2012, 10:22 pm Last Edit: Dec 26, 2012, 10:35 pm by combib Reason: 1
I have tried. Following is my program: (My result is "Temp is 31.14" on the LCD, which is incorrect and does not track the temperature)
Code: [Select]

#include <TimerOne.h>
/*
Analog pins 4 (SDA),5(SCL)
*/
#include <Wire.h>
#include <Adafruit_MCP23017.h>
#include <Adafruit_RGBLCDShield.h>
// The LCD and DS3132 use the I2C SCL on analog pin 5 and SDA on analog pin 4.
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();

int temp_MSB;
int temp_LSB;
double tempresolution = 0.48;

void setup()
{
 lcd.begin(16, 2);
 Serial.begin(9600);
 Wire.begin();
}

void loop()
{
 int i, sign, temp1; //added sign and temp1. JZ 05/21/2012
 double temperature;
 lcd.setCursor(0,1);
 while (1) {
   Wire.write(0xE0);
   Wire.write (0x08);
   Wire.requestFrom(0xE1, 1);
   temp_MSB = Wire.read();

   Wire.write(0xE0);
   Wire.write (0x09);
   Wire.requestFrom(0xE1, 1);
   temp_LSB = Wire.read();

   // changed for MAX9611 internal temperature output (9 bits with sign). JZ 05/21/2012
   sign = (temp_MSB>>8 & 0x1); //extract sign bit
   temp1 = (((temp_MSB<<1) & 0xFE)|((temp_LSB>>8)&0x1)); //extract internal temperature ADC steps
   if(sign)
   {
     temperature = (-1)*((~temp1 & 0xFF) + 1)*tempresolution; //sign bit=1, temperature is negative (two's compliment)
   }
   else
   {
     temperature = temp1 * tempresolution; //otherwise, the temperature is a positive number
   }
   temperature = ((temperature * 1.8) + 32); //convert to degree F

 lcd.setCursor(0,1);
 lcd.print("Temp is ");
 if (sign==0)
 {
   lcd.print("-");
 }
 lcd.print(temperature);
 }

}


Nick Gammon

Oh, right! You have code. It was a secret, though.

Read this before posting a programming question


Please edit your post, select the code, and put it between [code] ... [/code] tags.

You can do that by hitting the # button above the posting area.

Nick Gammon

You would have got a much faster response if you had read the sticky, and posted your code, in the first place. A day has been gone because you didn't.

combib

My apologies, I made a mistake.  Can someone help?

Nick Gammon

Code: [Select]

  while (1) {
    Wire.write(0xE0);
    Wire.write (0x08);
    Wire.requestFrom(0xE1, 1);
    temp_MSB = Wire.read();

    Wire.write(0xE0);
    Wire.write (0x09);
    Wire.requestFrom(0xE1, 1);
    temp_LSB = Wire.read();



Quote

I do understand i2c,  ...


OK, now go read my page, which you obviously haven't so far:

http://www.gammon.com.au/i2c

Things that jump out at me:


  • You need Wire.beginTransmission

  • You need Wire.endTransmission

  • I2C device addresses go up to 119 (x77) but you are using 0xE1


combib

I am reading your I2c instructions. I have changed my program to include:
    Wire.beginTransmission(0xE0);
    Wire.write(0x08);
    Wire.endTransmission(); // This function sets the pointer to the registerLocation from where we want to read the data
    Wire.requestFrom(0xE1,1);
    temp_MSB = Wire.read();

Also the address of the MAX9611 starts at 0xE0 thru 0xEF

Nick Gammon


Also the address of the MAX9611 starts at 0xE0 thru 0xEF


The library shifts the address left one and adds in the read/write bit. You want to use 0x70 (half of 0xE0) and leave that part to the library. In other words use 0x70 for both reading and writing.

Nick Gammon


combib

That worked, and yes something showed up on 70, although it still does not function correctly. I will work on it further and get back to you. Thank you for all your help

combib

Thanks for your help. Following is my code and so far it is working. Next I will add power supply and load.

Code: [Select]
#include <TimerOne.h>
/*
Analog pins 4 (SDA),5(SCL)
*/
#include <Wire.h>
#include <Adafruit_MCP23017.h>
#include <Adafruit_RGBLCDShield.h>
// The LCD and DS3132 use the I2C SCL on analog pin 5 and SDA on analog pin 4.
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();

int temp_MSB;
int temp_LSB;
double tempresolution = 0.50;

void setup()
{
  lcd.begin(16, 2);
  Serial.begin(9600);
  Wire.begin();
}

void loop()
{
  int i, sign, temp1; //added sign and temp1. JZ 05/21/2012
  double temperature;
  lcd.setCursor(0,1);
  while (1) {
    Wire.beginTransmission(0x70);
    Wire.write(0x08);
    Wire.endTransmission();

    Wire.requestFrom(0x70,2);
    temp_MSB = Wire.read();
    temp_LSB = Wire.read();
 
    // changed for MAX9611 internal temperature output (9 bits with sign). JZ 05/21/2012
    sign = (temp_MSB>>8 & 0x1); //extract sign bit
    temp1 = (((temp_MSB<<1) & 0xFE)|((temp_LSB>>8)&0x1)); //extract internal temperature ADC steps
    if(sign)
    {
      temperature = (-1)*((~temp1 & 0xFF) + 1)*tempresolution; //sign bit=1, temperature is negative (two's compliment)
    }
    else
    {
      temperature = temp1 * tempresolution; //otherwise, the temperature is a positive number
    }
    temperature = ((temperature * 1.8) + 32); //convert to degree F

  lcd.setCursor(0,0);
  lcd.print("Temp is ");
  if (sign==1)
  {
    lcd.print("-");
  }
  lcd.print(temperature);
  }
}

combib

I have written a program (see following) to read the MAX9611 Data and display it on an LCD. I will be changing the program to output to a screen and also have the ability to have up to 16 different addressed MAX9611 ICS reporting.  The problem this I have is that the Arduino  used a 7 bit i2c address and assumes that the 8th bit is either a one or a zero. In the case of the MAX9611, the write and read addresses are E0/E1, E2/E3, E4/E5, E6/E7, ..... FE/FF. My question is, how do I tell the Arduino  that the write/read bit is not necessarily a one or a zero?

Code: [Select]

/*********************************************************************
* FileName: MAX9611.h
* Dependencies: None
* Overview: Defines function prototypes, I2C address, global
* variables.
********************************************************************/


// ***************** User-configurable parameters ********************


// main voltage range
#define voltage_max 56.3
#define main_voltage_min 1.0

// main current range
#define current_max 10000
#define current_min 0

// I2C address
#define MAX9611_address 0x70 //0x70 is the Arduino MAX9611 address actual address is 0xE0

// Sense resistor values

// *******************************************************************

// Function prototypes

double get_MAX9611_voltage(void);
double get_MAX9611_current(void);

//void init_MAX9611 ();


Code: [Select]
/*********************************************************************
* FileName: MAX9611.cpp
* Dependencies: MAX9611.h (include here and in main)
* Wire.h (include here and in main)
********************************************************************/


/*********************************************************************
* Function:        void get_MAX9611_voltage (void),
* void get_MAX9611_current (void)
* PreCondition:    None.
* Input:            None.
* Output:          None.
* Side Effects:    None.
* Overview:        Function for obtaining MAX9611 voltage via I2C
* bus.
*
********************************************************************/

#include "MAX9611.h"
#include "Wire.h"

double MAX9611_voltage;
double MAX9611_current;

double get_MAX9611_voltage (void){
int msb;
int lsb;


    Wire.beginTransmission(0x70);
    Wire.write(0x0A);
    Wire.write(0x03);
    Wire.endTransmission();
   
    Wire.beginTransmission(0x70);
    Wire.write(0x02);
    Wire.endTransmission();

    Wire.requestFrom(0x70,2);
    msb = Wire.read();
    lsb = Wire.read();
    Wire.endTransmission();

    MAX9611_voltage = ((msb)<<4)+(lsb>>4);
    MAX9611_voltage = ((MAX9611_voltage/4096)*57.3);

return MAX9611_voltage;
}

double get_MAX9611_current (void){
int msb;
int lsb;
int result;

    Wire.beginTransmission(0x70);
    Wire.write(0x0A);
    Wire.write(0x00);
    Wire.endTransmission();
   
    Wire.beginTransmission(0x70);
    Wire.write(0x00);
    Wire.endTransmission();

    Wire.requestFrom(0x70,2);
    msb = Wire.read();
    lsb = Wire.read();
    Wire.endTransmission();

    result = ((msb)<<4)+(lsb>>4);
    MAX9611_current = (((result/4096)*440)/.05);

    return MAX9611_current;
}


Code: [Select]

#include <MAX9611.h>
#include <Wire.h>
/*
Analog pins 4 (SDA),5(SCL)
*/
#include <Adafruit_MCP23017.h>
#include <Adafruit_RGBLCDShield.h>
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();

int msb;
int lsb;

void setup()
{
  lcd.begin(16, 2);
  Serial.begin(9600);
  Wire.begin();
}

void loop()
{
  double volts;
  double current;
 
  lcd.setCursor(0,1);
  while (1) {

 
  volts = get_MAX9611_voltage();
 
  lcd.setCursor(9,0);
  lcd.print(volts, 3);
  lcd.print(" V");
 
    current = get_MAX9611_current();

  lcd.setCursor(0,0);
  lcd.print(current, 3);
  lcd.print(" A");

 
  lcd.setCursor(2,1);
  lcd.print((current * volts), 6);
  lcd.print(" Watts");
  }
}

Go Up