Forum: Mikrocontroller und Digitale Elektronik Probleme mit GY-271 (HMC5883) Compass


von Bence (Gast)


Lesenswert?

Ich bin Anfanger und habe Probleme mit gy-271 Modul(based on HMC5883 
chip). Der Wert der y-Achse ist immer -4096. Auserdem, trotz delay ist 
nur 100ms, ist der Program sehr langsam. Bitte hilf mir. Ich habe schon 
keine Idee mehr. Zum TWI benutzte ich Peter Fleurys I2C Master Library 
(http://homepage.hispeed.ch/peterfleury/doxygen/avr-gcc-libraries/group__pfleury__ic2master.html). 
Der Serialausgang sieht so aus:
...
X: 172
Y: -4096
Z: 415
X: 172
Y: -4096
Z: 413
X: 170
Y: -4096
Z: 415
...
Hat jemanden eine Idee, wie könnte ich ermitteln, ob der Chip 
kaputgegangen ist oder noch funktioniert. Das Datasheet befindet man 
hier: https://www.seeedstudio.com/wiki/images/4/42/HMC5883.pdf
Meine Code:
1
/*
2
 * twi.c
3
 *
4
 * Created: 2015.07.17. 15:43:34
5
 *  Author: Bence
6
 */ 
7
8
#define F_CPU 16000000
9
#define BAUD 9600
10
#define MYUBRR F_CPU/BAUD/16-1
11
#define rx_buffer_size 32
12
#define tx_buffer_size 32
13
#define compass_write 0x3C
14
#define compass_read 0x3D
15
16
#include <avr/io.h>
17
#include "i2cmaster.h"
18
#include <avr/interrupt.h>
19
#include <stdio.h>
20
#include <util/delay.h>
21
22
23
unsigned char rx_buffer[rx_buffer_size];
24
unsigned char tx_buffer[tx_buffer_size];
25
volatile unsigned char rx_read_pos=0;
26
volatile unsigned char tx_write_pos=0;
27
volatile unsigned char tx_load_pos=0;
28
volatile unsigned char available=0;
29
30
void initUSART();
31
char serialRead();
32
int serialWrite(char c, FILE *stream);
33
void delay(unsigned int ms);
34
void compass_init();
35
36
FILE uart_io= FDEV_SETUP_STREAM(serialWrite, serialRead, _FDEV_SETUP_RW);
37
38
int main(void)
39
{
40
  sei();
41
  initUSART();
42
  i2c_init();
43
  compass_init();
44
  int x=0;
45
  int y=0;
46
  int z=0;
47
    while(1)
48
    {
49
    i2c_start_wait(compass_write);
50
    i2c_write(0x03);
51
    i2c_rep_start(compass_read);
52
    
53
    x=(i2c_readAck()<<8);
54
    x|=i2c_readAck();
55
    
56
    y=((char)i2c_readAck()<<8);
57
    y|=(char)i2c_readAck();
58
    
59
    z=(i2c_readAck()<<8);
60
    z|=i2c_readNak();
61
    
62
        i2c_stop();
63
    
64
    printf("X: %i\n",x);
65
    printf("Y: %i\n",y);
66
    printf("Z: %i\n",z);
67
    delay(100);
68
    }
69
}
70
71
void initUSART()
72
{
73
  UBRR0H=((MYUBRR)>>8);
74
  UBRR0L=MYUBRR;
75
  
76
  UCSR0B=(1<<RXEN0)|(1<<RXCIE0)|(1<<TXEN0)|(1<<UDRIE0);
77
  UCSR0C=(1<<UCSZ00)|(1<<UCSZ01);
78
  stdin  = stdout = &uart_io;
79
}
80
81
void delay(unsigned int ms)
82
{
83
  for (unsigned int i=0;i<ms;i++)
84
  {
85
    _delay_ms(1);
86
  }
87
}
88
89
char serialRead()
90
{
91
  char c=0;
92
  while(available<=0);
93
  if(rx_read_pos>=available)
94
  {
95
    c=rx_buffer[rx_read_pos-available];
96
  }
97
  else
98
  {
99
    c=rx_buffer[rx_buffer_size+rx_read_pos-available];
100
  }
101
  available--;
102
  return c;
103
}
104
105
int serialWrite(char c, FILE *stream)
106
{
107
  if (c == '\n')
108
  {
109
    serialWrite('\r', 0);
110
  }
111
  tx_buffer[tx_load_pos]=c;
112
  tx_load_pos++;
113
  
114
  if (tx_load_pos>=tx_buffer_size)
115
  {
116
    tx_load_pos=0;
117
  }
118
  return 0;
119
}
120
121
122
void compass_init()
123
{
124
  i2c_start(compass_write);
125
  i2c_write(0x00);
126
  i2c_write(0b0001000);
127
  i2c_stop();
128
129
  i2c_start(compass_write);
130
  i2c_write(0x01); 
131
  i2c_write(0b00100000);
132
  i2c_stop();
133
134
  i2c_start(compass_write);
135
  i2c_write(0x02);
136
  i2c_write(0x00);
137
  i2c_stop();
138
}
139
140
ISR(USART_RX_vect)
141
{
142
  rx_buffer[rx_read_pos]=UDR0;
143
  rx_read_pos++;
144
  
145
  if(rx_read_pos>=rx_buffer_size)
146
  {
147
    rx_read_pos=0;
148
  }
149
  
150
  available++;
151
}
152
153
ISR(USART_UDRE_vect)
154
{
155
  if(tx_write_pos!=tx_load_pos)
156
  {
157
    UDR0=tx_buffer[tx_write_pos];
158
    tx_write_pos++;
159
    
160
    if (tx_write_pos>=tx_buffer_size)
161
    {
162
      tx_write_pos=0;
163
    }
164
  }
165
}
Danke für die Hilfe im voraus.

von Bence (Gast)


Lesenswert?

Ich benutze atmega328p.

von Alex R. (itaxel)


Lesenswert?

Bence schrieb:
1
y=((char)i2c_readAck()<<8);
2
y|=(char)i2c_readAck();

Hallo Bence,

entferne mal das "(char)" und schaue was dann rauskommt.

gr. Alex

von Bence (Gast)


Lesenswert?

Ich hatte es nachträglich ausprobiert, aber es funktioniert so auch 
nicht, und es bleibte in meiner Code.

von Karl H. (kbuchegg)


Lesenswert?

Bence schrieb:
> Ich hatte es nachträglich ausprobiert, aber es funktioniert so auch
> nicht, und es bleibte in meiner Code.

Er ist trotzdem keine gute Idee.
Ein unnötiger Cast sollte nie im Code sein. Im besten Fall bringt er 
nichts, im schlimmsten Fall kann er sich zu einer bösen Falle ausarten.

Unglücklicherweise löst das dein Problem mit den immer gleichen Werten 
nicht.
Das ist sowieso eigenartig, denn laut Datenblatt kann es ein Ergebnis 
von -4096 überhaupt nicht geben. Der Wertebereich läuft von -2048 bis 
+2047. -4096 ist da ausserhalb.

> Auserdem, trotz delay ist nur 100ms, ist der Program sehr langsam.

Das ist logisch.
Dein µC arbeitet sich an der Bearbeitung des UART Data Register Empty 
Interrupts zu Tode. Das ist ein bischen zu naiv angesetzt.
Beheb das erst mal, denn solange du den µC mit diesen Interrupts 
zumüllst, hast du nirgends ein vernünftiges Timing.
Wenn du schon beim Fleury warst, der hat auch schöne UART Funktionen.

: Bearbeitet durch User
von Bence T. (bence)


Lesenswert?

Danke ich werde Fleurys UART library ausprobieren.
Ich habe im Datenblatt habe ich etwas über das Wert -4096 gefunden,aber 
ich weiß es nicht, wie ich damit diese Probleme lösen könnte.

"In the event the ADC reading overflows or underflows for the given 
channel,or if there is a math overflow during the bias measurement, this 
data register  will contain the value -4096 in 2’s complement form. This 
register value will clear when after the next valid measurement is 
made."

Ich verstehe nicht,wie das ADC Lesen überlaufen oder unterlaufen kann, 
und warum es keine gültige Messung machen kann.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.