PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : HMC5843



hubert_K
04.09.2010, 14:16
Weil ich gerade da bin ;)!

Was stimmt mit meinem Code nicht bzw. was versteh ich falsch beim I2C:

MichaF
04.09.2010, 14:53
Toll wäre es, wenn du sagen würdest wo dein Problem liegt. Kannst du denn überhaupt auf den HMC zugreifen, kommt ein ACK? Wenn ja kannst du Register zurücklesen die zuvor geschrieben wurden? Und warum gleich mit dem Kopf durch die Wand... versuch doch erst mal die standard Config zum laufen zu bekommen, bevor du an sämtlichen Registern drehst.

Mehr Infos, dann gibts auch mehr Infos.

hubert_K
04.09.2010, 17:01
:) danke!!! sorry war wohl etwas überhastet.
Heißt das, dass wenn ich die Standard-Config nicht beschreibe oder ändere es trotzdem funktioniert sprich ich kann die X,Y,Z Register auch ohne Config auslesen?

Vielen Dank schonmal

mfg

hubsi

MichaF
04.09.2010, 17:30
Nein, ganz so einfach geht es leider doch nicht, Du musst zumindest in den "continuous measurement mode" umschalten.

0x3C //Write Mode auswählen
0x02 //zu beschreibendes Register auswählen
0x00 //Register Inhalt schreiben

Anschließend misst der HMC mit 10Hz, und Du kannst die Messwert Register auslesen. Vorausgesetzt, dass ansonsten keine Fehler in der Hardware bzw. in der Software sind.

hubert_K
04.09.2010, 18:55
Danke Micha! Kann es erst am Montag testen da ich jetzt nicht in meiner Bastelstube bin. Kann durchaus an meiner Hardwaredurchführung liegen da ich den Chip selbst auf ein Board gelötet habe und die Lötpunkte dann mit einem großen Tropfen Heißkleber fixiert habe. Naja... Es wird sich am Montag zeigen... bis dahin vielen Dank für deine Hilfe

hubert_K
06.09.2010, 12:22
8-[ Naja ich könnte es auch anders versuchen... mal schaun wie es probiere

MichaF
06.09.2010, 13:22
Zeig mal ein kompilierbares Programm. Steht das alles in einer Schleife? Wie oft wird das aufgerufen? Woher sollen wir das denn alles wissen? Und beantworte mal meine Fragen von oben. Außerdem sehe ich nicht, das du irgendwo Daten vom HMC anforderst, von alleine spuckt der nichts aus. Hast du das datenblatt gelesen?

Ein Schaltplan wäre auch nicht schlecht. Vielleicht hast du da schon was verbockt... single supply, dual supply etc.

hubert_K
07.09.2010, 08:37
Folgendes Problem:
Offensichtliche Unwissenheit


Egal was ich auf den HMC schreiben will er scheint nicht das zu machen was ich will.

Auf SSPADD kam ich durch (Fosc/(4*CLK))-1.

MichaF
07.09.2010, 08:53
Nein, du hast im Datenblatt nichts falsch verstanden. Offensichtlich verstehst du aber mich falsch. Ich kann dir erst helfen wenn du anfängst auf meine fragen einzugehen. Die wichtigste davon lautet:

Bekommst du auf eine read/write ein ACK?

die 2. wichtigste:

Warum zeigst du keinen vollständigen Code?

Du darfst den HMC nicht jedes mal neu initialisieren. Außerdem musst du nach der initialisierung warten bevor du ausliest. Des weiteren musst du die Daten anfordern und dann vollständig auslesen, nur denn zeigt der read Pointer beim nächsten mal wieder auf das X Register.

Hier funktionierender Coode von mir aus Basis der I2C Lib von Peter Fleury. Der Code läuft auf einem AVR. Am Prinzip ändert das aber nichts. Die read_hmc5843() kann 10 mal pro Sekunde aufgerufen werden.




#include <globals.h>
#include "i2cmaster.h"
#include <util/delay.h>
//################################################## ###############

unsigned char hmc5843_init(void){
_delay_ms(10); //nach Power up kurz warten

//Device ansprechbar?
if(i2c_start(HMC5843_ADDRESS+I2C_WRITE)){
i2c_stop();
return 1;
}
//Mode Register
if(i2c_write(0x02)){
return 2;
}
//Continous Mode auswählen (10Hz)
if(i2c_write(0x00)){
return 3;
}

i2c_stop();

return 0;
}

//################################################## ###############

unsigned char read_hmc5843(int* x, int* y, int* z){

if(i2c_start(HMC5843_ADDRESS+I2C_READ)){
i2c_stop();
return 1;
}

*x = (i2c_readAck() << 8); //MSB X
*x += i2c_readAck(); //LSB X

*y = (i2c_readAck() << 8); //MSB Y
*y += i2c_readAck(); //LSB Y

*z = (i2c_readAck() << 8); //MSB Z
*z += i2c_readAck(); //LSB Z + Stop Bedingung

//Read Pointer wieder auf 0x03 bringen
if(i2c_start(HMC5843_ADDRESS+I2C_READ)){
i2c_stop();
return 2;
}
i2c_readNak();

return 0; //Alles ok
}

Edit: Ok, der Schaltplan sieht gut aus :) Was hast du für Kondensatoren verbaut? Das Datenblatt empfiehlt nicht umsons Low ESR Typen, der HMC ist hier sehr empfindlich, bei mir hat das ganze erst mit Keramik Kondensatoren funktioniert.

Edit #2: Ok, ich nehm alles zurück, jetzt haben wir ja ein schönes Programm - fein :)

Edit #3: So... was mir aufgefallen ist:
- Du initialisierst den HMC direkt nach dem Power up. Das sollte man nicht machen. Ich meine die Wartezeit beträgt mindestens 10 ms, sicher bin ich mir da aber nicht mehr. Warten muss man aber auf jeden Fall.
- Ich kenne deine I2C Lib leider nicht. Aber hast du keine Möglichkeit von den I2C Funktionen Rückmeldung zu bekommen, ob der Slave überhaupt reagiert hat? Du gehst in deinem Programm einfach davon aus das alles Fehlerfrei funktioniert - was, wenn nicht?
- Der HMC gibt 2 Byte pro Raaumrichtung zurück. Dein x, y, z passt nicht zu der Raumrichtung welche durch die Variablenbezeichnung suggeriert wird. Siehe dazu mein Code.
- Mir ist nicht ganz klar was AckI2C, IdleI2C und DataRdyI2C machen. Aber in dem Block nach x = getcI2C(); kommt mal ein StopI2C();... bei allen folgenden Zugriffen jedoch nicht. Gewollt?

hubert_K
08.09.2010, 23:46
Bei den Kondensatoren bin ich mir nicht mehr sicher. Hab sie einfach aus meiner Box genommen (SMD 0805). Eine Pause hab ich eingebaut... war aber auch nicht des Rätsels Lösung. Anscheinend hab ich vergessen die Start-Condition auszuführen (StartI2C())... das hat mir schon mal beschert dass er mir nun lauter 6er ausgibt. Ich hab jetzt noch ein paar Sachen versucht. Ich weiß noch nicht wann er von mir ein AckI2C() braucht bzw. ein NotAckI2C... Diese Funktionen erzeugen eine (Not)-Acknowledge-Bedingung für den I2C. Hier mal der Code bis jetzt...




#pragma config WDTEN = OFF
#pragma config STVREN = OFF
#pragma config XINST = OFF
#pragma config CP0 = OFF, IESO = OFF, WDTPS = 1, DSWDTOSC = INTOSCREF
#pragma config OSC = INTOSC, T1DIG = OFF, LPT1OSC = OFF, FCMEN = OFF

//Include-Files

#include "p18f26j11.h"
#include "adc.h"
#include "stdlib.h"
#include "delays.h"
#include "stdio.h"
#include "usart.h"
#include "i2c.h"





//-----Main
void main(void)
{
unsigned char x=0;
unsigned char y=0;
unsigned char z=0;
int i=0;
int k=0;
int delay_var=10;
char degree;


//-----USART-Verbindung Bluetooth
Open1USART( USART_TX_INT_OFF &
USART_RX_INT_OFF &
USART_ASYNCH_MODE &
USART_EIGHT_BIT &
USART_CONT_RX &
USART_BRGH_HIGH
, 12);

Delay10KTCYx(1000);

OpenI2C(MASTER,SLEW_OFF);
// SSPADD = 0x09;
StopI2C();

StartI2C();

if(WriteI2C(0x3C))
{

CloseI2C();
printf("Error 1");

}


if(WriteI2C(0x02))
{

CloseI2C();
printf("Error 2");

}

if(WriteI2C(0x00))
{

CloseI2C();
printf("Error 3");

}
IdleI2C();
StopI2C();



printf("test1\n\r");
/*
if(DataRdyI2C());
{
Delay10KTCYx(100);
printf("test2\n\r");

StartI2C();
WriteI2C(0x3D);
x = ReadI2C();
x = (x<<8)+ReadI2C();
IdleI2C();
StopI2C();
Delay10KTCYx(100);
}
*/

StartI2C();
IdleI2C();
if(DataRdyI2C());
{
printf("dataisready");
}

StopI2C();


while(1)
{
StartI2C();
IdleI2C();
WriteI2C(0x3D);
StopI2C();
Delay10KTCYx(100);

printf("flag1");

printf("flag2");
StartI2C();
IdleI2C();
x = ReadI2C();
IdleI2C();
x = (x << 8)+ReadI2C();
IdleI2C();
AckI2C();
IdleI2C();



StartI2C();
IdleI2C();
x = ReadI2C();
IdleI2C();
y = (y << 8)+ReadI2C();
IdleI2C();
AckI2C();
IdleI2C();

StartI2C();
IdleI2C();
z = ReadI2C();
IdleI2C();
z = (z << 8)+ReadI2C();
IdleI2C();
NotAckI2C();
IdleI2C();

StopI2C();


Delay10KTCYx(10);



printf("%d %d %d\n\r",x,y,z);
Delay10KTCYx(10);

if(Read1USART()=='1');
{
break;
}

}


}

hubert_K
09.09.2010, 11:41
Eine Frage zu deinem Code MichaF
was macht eigentlich der Befehl: i2c_start(HMC5843_ADDRESS+I2C_WRITE) bzw. welche Werte haben HMC5843 und I2C_Write?


MfG

hubsi

MichaF
09.09.2010, 13:30
was macht eigentlich der Befehl: i2c_start(HMC5843_ADDRESS+I2C_WRITE) bzw. welche Werte haben HMC5843 und I2C_Write?

Die Funktion initialisiert eine Übertragung in die gewünschte Richtung (schreiben bzw. lesen). Die defines dahinter sind nur um das ganze für mich persönlich übersichtlicher zu gestalten:


#define HMC5843_ADDRESS 0x3C //Write Address
#define I2C_READ 1
#define I2C_WRITE 0

Bist du dir denn sicher, das deine I2C Funktionen überhaupt etwas zurück geben? Ansonsten ist diese Fehlerabfrage nämlich reichlich sinnfrei ;) Kommen denn Meldungen? Poste mal eine Beispielausgabe vom UART.

Prinzipiell kannst du dem HMC nach einer lesenden Übertragung mit einem ACK mitteilen, das du noch weitere Daten lesen willst. Gibt es kein ACK, folgt sinnigerweise ein Stop -> Die Übertragung ist beendet.