View previous topic :: View next topic |
Author |
Message |
(-_-) Guest
|
|
Posted: Sun Jan 07, 2007 5:06 am |
|
|
I've used the code that post by PCM programmer from my hmc6352 sensor, but why is the output that I get from it as shown below?:
Heading in degrees = 6298
Heading in degrees = 6298
Heading in degrees = 6298
Heading in degrees = 6298
Heading in degrees = 6298
Heading in degrees = 6298
Heading in degrees = 5658 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jan 07, 2007 1:26 pm |
|
|
Look at the previous comments in the thread:
Quote: |
I just received two new compasses from Honeywell and they work fine.
The two that I received before were from a "bad batch". |
So it's possible that you also have a bad unit.
Quote: |
I'm not a cracker-jack programmer, but I got the code PCM Programmer
posted to work by changing the return line of the HMC6352_read_heading
function to the following:
return((int16)lsb | ((int16)msb << 8));
|
Did you try this ?
The problem is that I don't have a HMC6352 unit to test. They're very
expensive. The cheapest one at Sparkfun is $60 (US).
http://www.sparkfun.com/commerce/product_info.php?products_id=7915
I don't want to spend $60 just to help someone write a driver. I tried
to help as much as I could by writing a preliminary driver, based on
the data sheet. But I don't guarantee that it works, because I don't
have an actual HMC6352 unit to test. You have to keep this in mind,
when using that driver code. |
|
|
YARGICH
Joined: 19 Jan 2007 Posts: 8
|
|
Posted: Fri Jan 19, 2007 4:19 am |
|
|
Hi,
I try to use my HMC6352 sensor with PIC16f687 and CCS. But I didn't accomplish to use it. When I send a first command, it gives to me ACK. But when I send next command or new command, it gives to me NOACK. Also when I choose "force_HW", it always gives to me "2=Collision". I didn't understand anything about ack answers of my HMC6352 sensor. According to you, is it broken down? or what is my mistake.
This is my test software:
Code: |
#include <16F687.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES PUT
#FUSES NOPROTECT //Code not protected from reading
#FUSES BROWNOUT //No brownout reset
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES HS //Internal RC Osc, no CLKOUT
#use delay(clock=20000000,RESTART_WDT)
#use i2c(Master,slow,sda=PIN_B4,scl=PIN_B6)
#use rs232(xmit=PIN_B7, rcv=PIN_B5)
//Port Adreslerini tanımlama
#byte PORTA = 0x05
#byte PORTB = 0x06
#byte PORTC = 0x07
#byte SSPCON = 0x14
#byte ANSEL = 0x11E
#byte CM1CON0 = 0x119
#byte CM2CON0 = 0x11A
short timeout_error;
byte Byte1,Byte2;
long i,j,k;
//******************************************************************************
//timeout lu com port okuması
char timed_getc()
{
long timeout;
timeout_error=false;
timeout=0;
while (!kbhit()&&(++timeout<50000)) // 1/2 sn
delay_us(10);
if (kbhit())
return (getc());
else {
timeout_error=true;
return (0);
}
}
//******************************************************************************
void init_I2C() {
output_float(PIN_B4);
output_float(PIN_B6);
}
//******************************************************************************
#int_rda
void usart_kesme(){
byte buf1,buf2,buf3,ack;
buf1=Timed_getc();
switch(buf1)
{
case 'a':
I2C_START();
ack=I2C_WRITE(0x42); // write command
ack=I2C_WRITE(0x47); // "G" command
ack=I2C_WRITE(0x74); // RAM adress
ack=I2C_WRITE(0x30); // Standby Mode // I tried to Operating mode
I2C_STOP();
Delay_ms(10);
I2C_START();
ack=I2C_WRITE(0x42); // write command
ack=I2C_WRITE(0x47); // "G" command
ack=I2C_WRITE(0x4E); // RAM adress
ack=I2C_WRITE(0x00); // Output Mode // I tried to Query mode
I2C_STOP();
Delay_ms(10);
I2C_START();
ack=I2C_WRITE(0x41); // 'A' Command (in Standby Mode) // 0x43 Command (in Operating Mode)
buf2=I2C_READ(); // Read MSB of Heading
buf3=I2C_READ(); // Read LSB of Heading
I2C_STOP();
printf("\n\r ack : %u",ack);
printf("\n\r buf2: %u",buf2);
printf("\n\r buf3: %u",buf3);
Delay_us(100);
break;
case 'b':
break;
default: Printf("\n\rDefault "); break;
}
}
//******************************************************************************
#int_RTCC
RTCC_isr()
{
}
//******************************************************************************
//******************************************************************************
// ANA PROGRAM
//******************************************************************************
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_8);
init_I2C();
enable_interrupts(INT_RTCC);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
set_tris_a(0x00);
set_tris_b(0x20);
set_tris_c(0x00);
//ANA_DONGU:
while(TRUE){
}
}
|
|
|
|
YARGICH
Joined: 19 Jan 2007 Posts: 8
|
|
Posted: Fri Jan 19, 2007 5:30 am |
|
|
I want to add something. When I send 0x43 command without force_HW, it gives to me ACK and I read MSB of heading=0 and LSB of heading=255.
I haven't got a oscillascope. So, I don't see my signals. What can I do to use this sensor. |
|
|
Ttelmah Guest
|
|
Posted: Fri Jan 19, 2007 11:07 am |
|
|
First, get rid of Timed_getc. This is used in 'mainline' code, when it is important not to hang, if a charcater doesn't arrive. In the interrupt, it is unecessary (the interrupt only gets called, if there _is_ a character), and using it will result in interrupts being disabled, if you latter use a timing function in main.
Second do the same with your I2C operations. These should move to the main code. In the interrupt, simply receive a character, and store it. Get rid of all delays in the interrupt handler. In the main, check if a character is waiting, and if it is, get it, and execute the required I2C routine.
You don't need to fiddle around with the tris registers yourself. Unless you select 'fast_io', or 'fixed_io', the compiler takes care of this.
Send you mode setting, just _once_ when you initialise the chip.
Then in your main code, send an 'A' command. This triggers a reading to be taken, wait for the reading time, then send another 'A' command, and retrieve the data.
Best Wishes |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jan 19, 2007 2:36 pm |
|
|
In addition to Ttelmah's comments, I have this comment:
Quote: |
I2C_START();
ack=I2C_WRITE(0x41); // 'A' Command (in Standby Mode) // 0x43 Command (in Operating Mode)
buf2=I2C_READ(); // Read MSB of Heading
buf3=I2C_READ(); // Read LSB of Heading
I2C_STOP();
|
Your code to read the data is not correct. It doesn't follow the method
shown in the HMC6352 data sheet.
The data sheet shows how to read two bytes in Example 2, on page 9.
http://www.sparkfun.com/datasheets/Components/HMC6352.pdf
They show this sequence:
Start bit
Send 0x43 to slave
Get ACK from slave
Receive 0x55 from slave
Send ACK to slave
Receive 0x00 from slave
Send NACK to slave (no acknowledge)
Stop bit
I showed how to do this in my sample code posted earlier in this thread. |
|
|
arunb
Joined: 08 Sep 2003 Posts: 492 Location: India
|
RE:" |
Posted: Sat Jan 20, 2007 11:05 am |
|
|
Hi,
Just for your information.
I have had trouble making the standard I2C functions for the 24LC256 memory work for the 16F877A mcu, I was using PCM version 3.228. I noticed that the pic went haywire when I accessed the i2c functions.
I then used PCM version 3.169 instead of 3.228 and this solved the problem !!
thanks
arunb |
|
|
YARGICH
Joined: 19 Jan 2007 Posts: 8
|
|
Posted: Sat Jan 20, 2007 1:56 pm |
|
|
@PCM programmer,
I wrote a new software as you said. But it isn't working. When the program start, it gives NOACK, MSB=255 and LSB=255.
when write only this commands;
Start bit
Send 0x43 to slave
Get ACK from slave
Receive 0x55 from slave
Send ACK to slave
Receive 0x00 from slave
Send NACK to slave (no acknowledge)
Stop bit
it gives ACK, MSB=0 and LSB=0.
is it useful to change my CCS 3.228 to CCS 3.169? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Jan 20, 2007 2:11 pm |
|
|
Quote: | When the program start, it gives NOACK, MSB=255 and LSB=255. |
Do you have pull-up resistors installed on the i2c bus ?
You need them. You need one pull-up on SDA and
one on SCL. A typical value is 4.7K ohms. |
|
|
YARGICH
Joined: 19 Jan 2007 Posts: 8
|
|
Posted: Sat Jan 20, 2007 2:51 pm |
|
|
Yes, I have. But I have 2 pieces 10k pull-up on SDA and SCL. I know that, 10K is needed for 100kHz communication and 1K is needed for 400kHz communication. am I right? What is your opinion about value of pull-up. |
|
|
YARGICH
Joined: 19 Jan 2007 Posts: 8
|
|
Posted: Sat Jan 20, 2007 3:27 pm |
|
|
when I send these commands;
Code: |
I2C_START();
ack1=I2C_WRITE(0x43); // Read from HMC6352
ack2=I2C_WRITE(0x72); // Read from EEprom
ack3=I2C_WRITE(0x00); // EEprom adress 0x00
Byte1=I2C_READ(0); // it must read 0x42 (default slave adress)
I2C_STOP();
|
I see these results;
ack1 : 0
ack2 : 1
ack3 : 1
Byte1: 255
Thank you very much for your interests. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Jan 20, 2007 4:07 pm |
|
|
Quote: | I2C_START();
ack1=I2C_WRITE(0x43); // Read from HMC6352
ack2=I2C_WRITE(0x72); // Read from EEprom
ack3=I2C_WRITE(0x00); // EEprom adress 0x00
Byte1=I2C_READ(0); // it must read 0x42 (default slave adress)
I2C_STOP(); |
That's not the correct protocol to read a byte from EEPROM in the HMC6352.
On page 10 of the HMC6352 data sheet, they show a timing diagram
of how to read a byte from a register. The procedure for reading
EEPROM is similar.
The diagram on page 10 shows the sequence of i2c operations that
are required to read a byte. Your code above is trying to invent a
new protocol, but you can't do that. You can only use the protocol
that the chip designers put into the chip.
HMC6352 data sheet:
http://www.sparkfun.com/datasheets/Components/HMC6352.pdf |
|
|
YARGICH
Joined: 19 Jan 2007 Posts: 8
|
|
Posted: Sat Jan 20, 2007 6:57 pm |
|
|
Thak you very much. I accomplished to run the HMC6352. When @PCM Programmer said that it is like EEPROM, I remembered that I wrote my EEPROM software.
But, in page 10 of HMC6352 datasheet said that I2C_STOP and I2C_START is between write and read commands.
anyway...
Thank you very much again to help me to PCM Programmer.
Best Regards |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jan 21, 2007 5:55 pm |
|
|
I agree that most chip manufacturers specify that a Restart operation
should be done at that point, instead of a Start and a Stop.
This slide show presentation from Microchip goes into some detail on
why a Restart is used when reading from an EEPROM. The slides and
explanations for Restart are mainly on pages 20 to 22:
http://ww1.microchip.com/downloads/en/devicedoc/i2c.pdf |
|
|
Nickmo Guest
|
HMC6352 does not recalculate heading |
Posted: Fri Apr 13, 2007 12:14 pm |
|
|
I've been having trouble interfacing an HMC6352 with a PIC18LF2520.
I call the following function repeatedly, but after the first heading calculation on power-up, the compass does not recalculate heading and just returns the first value, regardless of how I rotate the compass.
Any help would be greatly appreciated.
Code: |
#use I2C(Master, sda=SDA_PIN, scl=SCL_PIN)
void getHeading(){
disable_interrupts(global);
i2c_start();
i2c_write(COMP_W_ADDY);
i2c_write(GET_DATA_CMD);
i2c_stop();
delay_ms(6);
i2c_start();
i2c_write(COMP_R_ADDY);
msb = i2c_read();
lsb = i2c_read();
i2c_stop();
heading = ((int16)lsb | ((int16)msb << 8));
enable_interrupts(global);
} |
|
|
|
|