I2C Issues (Rookie)

Go To Last Post
8 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Gentlemen

 

I am having some issue with reading data from an HMC5338 via I2C. I have limited experience with this interface and sure there is some issue with my code. The data I am receiving are all 0xFF.

 

/*
 * HMC5883 Library.c
 *
 * Created: 8/11/2019 2:51:35 PM
 * Author : Reginal Smith
 */ 

#include <avr/io.h>
#include <util/delay.h>

#include "USART.h"
#include "i2cmaster.h"

#define BAUDRATE 9600
#define HMC5883_ADDRESS 0x3C

int main(void)
{
    char ret;
    /*Start communication systems */
    initUSART(); 
    i2c_init();
    printString("UART:OK\r\n");
    
    /*CONFIGURE HMC5883*/
    ret = i2c_start(HMC5883_ADDRESS); /*Check for HMC5883 presence */
    if (ret) { 
        i2c_stop();
        printString("HMC5883: FAIL\r\n");
    } else { 
        printString("HMC5883:OK\r\n"); 
        
        /*Configure HMC5883 for continuous measurement mode*/
        i2c_write(0x00);
        i2c_write(0x70);
        i2c_start(HMC5883_ADDRESS);
        i2c_write(0x01);
        i2c_write(0xA0);
        i2c_start(HMC5883_ADDRESS);
        i2c_write(0x02);
        i2c_write(0x00);
        i2c_stop();
        printString("DONE");
    }
    while (1) 
    {
        printString("START");
        i2c_start(HMC5883_ADDRESS);
        i2c_write(0x03);
        i2c_stop();
        
        i2c_start(0x3D);
        uint8_t xhi = i2c_readAck();
        uint8_t xlo = i2c_readAck();
        uint8_t zhi = i2c_readAck();
        uint8_t zlo = i2c_readAck();
        uint8_t yhi = i2c_readAck();
        uint8_t ylo = i2c_readAck();
        i2c_stop();
        printString("Data:");
        printHexByte(xhi);
        printHexByte(xlo);
        _delay_ms(200);
        
        
    
        
    }
}

This topic has a solution.

rmsmith10

Last Edited: Tue. Aug 13, 2019 - 05:40 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Try using the 7-bit address 0x1e in every place that you have HMC5883_ADDRESS.   0x3C is the 8-bit address, which is the 7-bit address shifted left by one bit.  I believe that the i2c_start() that you are using requires the 7-bit address.    If the I2C library that you are using doesn't make this distinction clear in its documentation, then you are using the wrong I2C library.  

 

I believe that everyone who is learning to use I2C should start on the Arduino Nano.  Because it is very cheap, and the out-of-the-box I2C library ("Wire.h") for Arduino works 100% of the time with the example code library that the Arduino community provides for the device that you are trying to test.  The Adafruit library for the HMC5883 is very good, works with Wire.h 100% of the time, and is documented as well as Arduino code gets.

 

The HMC5883 is complex device.  Even when you finally do get the I2C working (which is something that no one needs to do since for $3 you can get an AVR development board (the Arduino Nano) that works right out of the box with this device),  the raw results that you will be getting is nearly meaningless without further adjustment and calibration of the HMC data.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

HMC5883 data sheet says:

0x3D for read and 0x3C for write.

"i2cmaster.h" is Fleury library.   It uses 8-bit addresses i.e.  0x3D for read and 0x3C for write

 

Please ignore Simonetta's comment about your code.

However it is always wise to use the return value from i2c_start() function

 

His other advice about using Arduino and Arduino libraries is wise.

Note that "Wire.h" library expects 7-bit address i.e. 0x1E

Even if your final target is not an Arduino,   it is worth buying an Arduino for initial prototype.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ok, up one level as you have seem to have been including some debug stuff in your code, but have not tolled us what you actually see...

 

from this:

printString("UART:OK\r\n");
    
    /*CONFIGURE HMC5883*/
    ret = i2c_start(HMC5883_ADDRESS); /*Check for HMC5883 presence */
    if (ret) { 
        i2c_stop();
        printString("HMC5883: FAIL\r\n");
    } else { 
        printString("HMC5883:OK\r\n"); 
        

I would expect that on the terminal window of your PC you see a:

"Uart:ok" followed by the "HMC5883:ok"

If that happens we can continue to the next stage.

Why, well because if it does give an OK the communication channel should be is ok , and the slave address should be ok.

there is one little snag and that is when the SDA line gets stuck at low level the processor will see that as an ack and be fine with it. But as you reported that you receive all FF that indiactes the SDA line can  go to high level making that a very unlikely situation.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

rmsmith10 wrote:
 i2c_start(0x3D);
        uint8_t xhi = i2c_readAck();
        uint8_t xlo = i2c_readAck();
        uint8_t zhi = i2c_readAck();
        uint8_t zlo = i2c_readAck();
        uint8_t yhi = i2c_readAck();
        uint8_t ylo = i2c_readAck();
        i2c_stop();

 

You must NAK the last byte read so the slave knows the master is done reading data and allows the master to stop the bus!

so try this:

 i2c_start(0x3D);
        uint8_t xhi = i2c_readAck();
        uint8_t xlo = i2c_readAck();
        uint8_t zhi = i2c_readAck();
        uint8_t zlo = i2c_readAck();
        uint8_t yhi = i2c_readAck();
        uint8_t ylo = i2c_readNak();
        i2c_stop();[/

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
stack gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I appreciate all of the knowledge and insight. After reading all the comments, I reviewed the library and it appears that I needed to have included a write or read bit in the address. Interestingly I noticed that the device would send an ack when utilizing the slave address without the write bit. I believe it is getting into a condition where the line is low or the I2C device in sending a "0" for the 8th bit. That left me with the impression that my communication code was good but in actually it wasn't. I am now receiving valid data and will begin work on calibrating the device. 

rmsmith10

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Corrected...Thank you.

rmsmith10

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Turns out the library I am using requires a 8 bit address. I omitted the read/write bit which was causing the issue. Your advice helped get me get pointed in the write direction. 

rmsmith10