Pages: [1] 2 3 4   Go Down
Author Topic: HMC6352  (Read 8824 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi All,

I'm trying to get the Arduino Mini to work with the HMC6352(http://www.sparkfun.com/commerce/product_info.php?products_id=7915) .

I've connected the analogue pin 4 to SDA and pin 5 to the SCL of the Compass, both lines are connected to the +5V with a 1,8R resistor.

This is the output I get:
Start
Step 1
Step 2
Stop
<41-0->

I've noticed if i remove the 2 resistors the code runs to Step 2 and stops, than I get the following output:
Start
Step 1
Step 2

I'm using the following code:
Code:
#include <Wire.h>

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  
  digitalWrite(13,HIGH);
}

byte val = 0;

void loop()
{
  Serial.println("Start");
  Wire.beginTransmission(0x42);
  Serial.println("Step 1");
  Wire.send(0x41);
  Serial.println("Step 2");
  Wire.endTransmission();
  Serial.println("Stop");
  
  delayMicroseconds(7000);
  
  Wire.requestFrom(0x42, 2);
  
  Serial.print('<');
  while(Wire.available())
  {
    char c = Wire.receive();
    Serial.print(c,HEX);
    Serial.print('-');
  }
  Serial.print('>');
  
  delay(500);
}


What is wrong?

Thanks,
Frederik
Logged

Daniel
Guest
 Bigger Bigger  Smaller Smaller  Reset Reset

haven't used this module but your post rang a bell.. see this one
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1163405566/2

D
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 13
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

How did you wire up to the HMC6352? - as I remember, it's a really small BGA chip?
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

At Sparkfun you can by one that is already soldered on a print.



http://www.sparkfun.com/commerce/product_info.php?products_id=7915
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am trying to get the same setup to work and I keep hitting the same problem  :-/

Ardunio NG connected to a Sparkfun HMC6352, SDA is connected to analog pin 4, SCL is connected to analog pin 5, both SDA & SCL are pulled high with 1.8 kOhm.

The odd thing is that this setup works with my PIC18 microcontroller! That's the code I use there

Code:
// controlling HMC6352 via I2C bus

#include "18f452.h"

#fuses hs,nowdt,put,noprotect
#use delay(clock=20000000)    // 20 MHz
#use i2c(master, sda=PIN_C4, scl=PIN_C3)
#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7)

#define SLAVE 0x42            // address of slave
#define ACK 0x01
#define NACK 0x00


// functions
byte readByte(byte *buffer, int len);
byte writeByte(byte command, byte *buffer, int len);


void main()
{
  byte buffer[2] = {0,0};
  float yaw;
  long sum;

  // set operational mode
  buffer[0] = 0x74;          // register address
  buffer[1] = 0x62;          // 20 Hz, continuous mode
  writeByte(0x47, buffer, 2);
  delay_ms(70);

  // get data
  writeByte(0x41, 0, 0);
  delay_ms(6000);

  while (true)
  {
     readByte(buffer, 2);

     sum = buffer[0];
     sum = sum << 8;         // can't shift buffer[n] itself
     sum += buffer[1];
     yaw = sum/10.0;
     printf("%05.1f\n", yaw);
  }
}

byte readByte(byte *buffer, int len)
{
  byte i;

  i2c_start();

  if (i2c_write(SLAVE+1))
  {
     // no ACK received

     // this fails quite often, maybe we should wait somewhere?
     //printf("readByte: i2c_write() failed\n");
     return 0;
  }

  for (i=0; i<len; i++)
  {
     // fill buffer
     *(buffer+i) = i2c_read(ACK);
  }

  // might be needed..
  //i2c_stop();

  return 1;
}


byte writeByte(byte command, byte *buffer, int len)
{
  byte i;

  i2c_start();

  if (i2c_write(SLAVE))
  {
     // no ACK received

     // DEBUG (never occured so far)
     //printf("writeByte: i2c_write() failed for address\n");
     return 0;
  }

  if (i2c_write(command))
  {
     // no ACK received

     // DEBUG (never occured so far)
     //printf("writeByte: i2c_write() failed for command\n");
     return 0;
  }

  for (i=0; i<len; i++)
  {
     // send buffer
     if (i2c_write(*(buffer+i)))
     {
        // no ACK received

        // DEBUG (never occured so far)
        //printf("writeByte: i2c_write() failed for data byte %u\n", i);
        return 0;
     }
  }

  // might be needed..
  //i2c_stop();

  return 1;
}

(the PICC suite lacks high level I2C routines, and as you see from the comments in readByte and writeByte, this does not all work according to the spec here either, but it does work and maybe this gives a hint..)
Using similar code with Arduino or even trying to read values from EEPROM returns just (static) garbage. Help!



I am not that much into electronics, but maybe something is wrong wrt to levels or the pull-up resistors? The HMC6352 spec says

Quote
The HMC6352 Serial Clock (SCL) and Serial Data (SDA) lines do not have internal pull-up resistors, and require resistive pull-ups (Rp) between the master device (usually a host microprocessor) and the HMC6352. Pull-up resistance values of about 10k ohms are recommended with a nominal 3.0-volt supply voltage. Other values may be used as defined in the I2C Bus Specification 2.1.

And I am also unsure whether or not pull-up resistors are even needed, because http://research.techkwondo.com/blog/julian/279 is quoting Nicolas

Quote
I have pull-up resistors on those lines, but Nicolas explains that his library enables the internal pull-ups on the Atmega, so I can probably pull those from my breadboard.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Just tried, using 10kOhm pull-up resistors does not change anything.. I get exactly the same 41 0 pattern (which seams to mirror the byte sent) as freddotnet :/
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 61
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am encountering the same problem with the HMC6352.  I'm using a 168, but the pins should be the same for SCL and SDA.  Have either of you gotten this to work with Arduino yet?

Thanks,

D.
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 61
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm still working on this, and have learned a few things.  First of all, in Fred's example code, we never recieve anything at all.  The buffer used by Wire is the same for transmit and receive - if we received anything, it would replace the 0x41 command.  I tried to put the device in continuous mode, and when I attempted to read I just got my old command back.  

Looking at the Wire code, it doesn't seem like it knows if a read has occurred or not.  If you ask for N bytes, you just get the first N bytes of the buffer.

Looking at the ATMega 168 datasheet, it seems like the hardware is supposed to wait if the slave device holds SCL low, and I don't see any way to wait for SCL to change.

I did find a non-interrupt driven TWI project at AVR Freaks - I have gotten it to compile under Arduino, and since we are just trying to figure out why ONE device doesn't behave, this seems like it will be much easier to debug.  

If anyone else is still interested in getting this device, and TWI in general, working smoothly with Arduino, I would be glad for any help or suggestions.  I don't have a scope or much experience with this, but I do have time to work on getting this device to talk to us.

D.
Logged

Brisbane
Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi drd!


Thanks for working on this! I too am struggling to get satisfactory results, although I have managed to get the Arduino Mini working with a DS1307 real-time clock using Wire - so I'm glad I've gotten that far.

Have you looked at the HMC6352 lines on an oscilloscope? I'm looking at the waveforms here;

http://www.ssec.honeywell.com/magnetic/datasheets/hmc6353_i2c_operational_overview.pdf

Two things I've noticed (but I have a *terrible* oscilloscope, so this isn't guaranteed correct)

i) there appear to be 9 clock cycles between each acknowledge, but the HMC6352 is expecting only 8. Perhaps the Wire library includes a parity bit that shouldn't be there?

ii) the documented waveforms suggest that the SDA line should set up each bit in time for the next rising SCL edge, but what I'm seeing on the oscilloscope is that the SDA line changes at the same instant as the SCL rising edge (which seems a bad thing).

Have you seen the comment on the sparkfun forum concerning 'clock stretching' on the HMC?

(http://forum.sparkfun.com/viewtopic.php?t=6236)

Please keep me posted on your efforts - many thanks!
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 61
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi mattp!

Thanks for the information - it helps make a little more sense out of this.  I got the software TWI code to start doing things, had to redefine some pins for the avr168.  The way this code works is to actually time out the data on the SCL and SDA lines using a loop and delays instead of using the twi hardware.

Initially, I couldn't get an ACK when I sent out the 0x42 to the sensor.  I mistakenly shifted the 0x42<<1 and suddenly started getting an ACK for that and the next 0x41 command to generate a heading.  After waiting 7 ms, I issue another start, send address 0x43<<1, and try to read two bytes.  Unfortunately, they are always 0xFF.  I notice the code isn't looking at the SCL line before reading the data, I think I can change it so it will wait on SCL - I'll work on that.  It seems there is a timing problem, or why would I need to left shift the adress to make it work.  This might have something to do with you seeing an extra bit in there?

I don't have an oscilloscope, so can only shoot in the dark as of now.  If you have any interest in playing with the software twi code for Arduino, I'd be happy to send you what I have.  It would be interesting to know if it is actually doing what it is trying to do.

I'd also be curious to see how you got the DS1307 to work with Wire.

D.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

mattp, I also would love to see the DS1307 code if you're willing to share it.
Logged

Brisbane
Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Unfortunately, the code for the DS1307 isn't that exciting...

Code:
#include <Wire.h>

// TWI (I2C) sketch to communicate with the DS1307 Real Time Clock

void setup()

{
  Wire.begin(); // join i2c bus (address optional for master)
  Serial.begin(9600);

  // program the time & enable clock  (each hex digit corresponds to one clock digit)
  Wire.beginTransmission(0x68);
  Wire.send(0);
  Wire.send(0x00);          //seconds
  Wire.send(0x30);          //minutes
  Wire.send(0x80 | 0x21);    //hours (24hr time)
  Wire.endTransmission();


}

void loop()
{
  Wire.beginTransmission(0x68);
  Wire.send(0);
  Wire.endTransmission();

  Wire.requestFrom(0x68, 3);
  byte secs = Wire.receive();
  byte mins = Wire.receive();
  byte hrs = Wire.receive();
  
  Serial.print(hrs,HEX);    
  Serial.print(":");
  Serial.print(mins,HEX);
  Serial.print(":");
  Serial.println(secs,HEX);

  delay(1000);    //wait a second before next output

}


I've found that the Wire library doesn't send any data until the Wire.endTransmission line is executed. ie: all the other commands are just to initialise parameters and fill the buffer.

By way of debugging, I've been looping the following;

  Wire.beginTransmission(0x68);
  Wire.endTransmission();

this just sends the address of the DS1307 over and over. When I view this on an oscilloscope, I can confirm that the DS1307 drives the SDA line low during an ACK (acknowledge). I confirmed this by removing the DS1307 from circuit and saw that the SDA line then remains high.

Also, if I send the wrong address for the DS1307, there is no change on the SDA lines (as expected).

No such luck with the HMC6352. When I loop its address over and over there is no ACK.

How did you get the HMC6352 to acknowledge, drd? Care to post your code?
« Last Edit: March 13, 2007, 11:13:29 pm by mattp » Logged

Brisbane
Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Okay - FINALLY got an acknowledge from the HMC6352 using the Wire library...

There seems to be timing troubles within the Wire library (in the case of this compass) because sending the actual address of 0x42 doesn't work...

However, I had a hunch when looking at the oscilloscope and decided to shift the address right:

loop:

  Wire.beginTransmission(0x21);      //HMC6352 address bit shifted right
  Wire.endTransmission();


THIS gets an acknowledge, so now I can work on fixing the timings...

(I should mention, I'm running everything at 5V and have a 4.7k pullup resistor on each of the I2C lines).
« Last Edit: March 13, 2007, 11:26:43 pm by mattp » Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 61
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi mattp,

I think the ACK I'm getting may just be accidental.  Reading the AVR168 twi reference some more, it seems like both the SDA and SCL lines are "wire ANDed", so the master tries to raise SCL, but if the slave holds it low SCL stays low until until slave raises SCL.  I'm sure my code doesn't do this, and I'm trying to change it so it does.  There are multiple states a port can be left in, and I'm trying to figure out how to write HI on SCL, then release the line and check SCL, and wait till it goes HI to start timing the SCL pulse.  

From what you've observed, I bet Wire isn't waiting for slave to raise SCL, and is just writing or reading data at whatever rate it wants.  It may be that it isn't leaving the SCL pin in the right state for the twi hardware to recognize SCL being held low.

I gotta get me an oscilloscope!  Are any of the inexpensive USB scopes usable for stuff like this?

I'm going to pursue the software twi for now to try and understand twi, and it also has the advantage that you could use other pins, and run it on microcontrollers that don't have hardware twi.

Good luck!

D.
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 61
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

mattp - I stumbled onto some more information.  There is a software twi application from Atmel called AVR300 which is a single-master, written in assembler, but it has some good documentation.  It seems the only time that the slave holds SCL low is immediately following an ACK - not for each SCL pulse in each 8-bit transfer.  This is the way this software behaves, anyway.  I'm wondering if you see something like this on your scope, for example, following the ACK after the 0x43 we use to read the heading from the 6352.  If you see SCK staying low after the ACK for the read request that would be what we are looking for.

I understand the reason for pull-up resistors now - if either master or slave hold a line low, it will be low - otherwise it will be HI.  So the SCL is used for handshaking between master and slave.

Based on you needing to shift the 0x42 right, it seems like we have timing issues even within each 8-bit transfer - I'll try to learn about that.

D.
Logged

Pages: [1] 2 3 4   Go Up
Jump to: