GPS Empfänger an ATmega8

OP Persönliche Seite #994311
Lesenswert?

Hallo,
habe will einen von den GPS- Empfängern aus diesem Thread hier 
(Beitrag "GPS - Empfänger günstig bei Ebay")
an einen ATmega8 anschliessen, und erstmal die aktuelle Geschwindigkeit 
auf einem LCD ausgeben.
Ich habe die lcd-lib hier aus dem Forum, und die UART-lib von Peter 
Fleury verwendet. Das LCD funktioniert, und das GPS- Modul ist korrekt 
an RX und TX angeschlossen.
Allerdings empfange ich keine Daten von GPS- Modul.....(oder vielleicht 
doch, aber sie werden nicht auf dem LCD ausgegeben?)

Hier mal mein Sourcecode, der übrigends bis auf 7 Warnings fehlerfrei 
erstellt wird:
1
#include <avr/io.h>
2
#define F_CPU 4000000
3
#include <util/delay.h>
4
#include <stdlib.h>
5
#include <avr/interrupt.h>
6

7
#include "lcd-routines.h"
8
#include <uart.h>
9

10
#define UART_BAUD_RATE  9600   
11

12

13
int main(void)
14
{
15
unsigned char empfangen[5],nmea[3] ="",kmh_string[4],temp;
16
float kmh,nurzumrechnen;
17

18
//Uart und LCD initialisieren
19
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
20
lcd_init();
21
lcd_string("Start!");
22

23

24
while(1)
25
{
26

27
temp = uart_getc();
28
//Zum Überprüfen
29
lcd_string(temp);
30

31

32
if(temp == '$')
33
{
34
//zwei Zeichen nach $ verwerfen
35
temp = uart_getc();
36
temp = uart_getc();
37
//Variablen zum Testen, ob RMC
38
nmea[0] = uart_getc();
39
//jeweils zum Test auf Display ausgeben
40
lcd_string(nmea[0]);
41
nmea[1] = uart_getc();
42
lcd_string(nmea[1]);
43
nmea[2] = uart_getc();
44
lcd_string(nmea[2]);
45
}
46

47
//Nach "E," kommt Geschwindigkeit in Knoten
48
if(temp == 'E')
49
{
50
//Nur RMC auslesen, denn nur dort ist Geschwindigkeit (in Knoten)
51
if(uart_getc() == ',' && nmea[0] == 'R' && nmea[1] == 'M' && nmea[2] == 'C') 
52
{
53
lcd_string("Fix gefunden!");
54

55
//Geschwindigkeit enpfangen
56
empfangen[0] = uart_getc();  
57
empfangen[1] = uart_getc();
58
empfangen[2] = uart_getc();
59
empfangen[3] = uart_getc();
60
empfangen[4] = uart_getc();
61

62
//Wenn Geschwindigkeit noch 2-stellig vor dem Komma, 2. Stelle hinter dem Komma = 0
63
}
64
if(empfangen[2] == '.')
65
{
66
empfangen[4] = '0';
67
}
68
//Den String "empfangen" in float umwandeln, zum Rechnen
69
nurzumrechnen=atof(empfangen);
70
//Knoten in kmh umrechnen
71
kmh = nurzumrechnen * 1.852;
72
//float wieder in String umwandeln, zum auf LCD ausgeben
73
itoa(kmh,kmh_string,10);
74
//kmh auf LCD ausgeben
75
lcd_string(kmh_string);
76
}
77
}
78
}

Vielleicht fällt ja jemandem etwas auf, was ich noch verbessern kann.
Wie man das GPS- Modul auf 9600 Baud einstellen kann, weiß ich nicht 
genau, ich hab einfach mit SIRFDemo das NMEA- Protokoll eingestellt, und 
dabei auch 9600 Baud. Allerdings weiß ich nicht, ob die Einstellungen 
gespeichert werden, oder ob ich das über den µC jedesmal neu 
konfigurieren muss.

Vielen Dank schon einmal im Voraus.
Gruß, Steffen
OP Persönliche Seite #994353
Lesenswert?

Aha, muss ich dann noch eine Funktion machen, die solange wartet, bis 
ein Zeichen da ist, also z.B. so:
1
void getchar()
2
{
3
unsigned char zeichen[1];
4

5
do
6
{
7
zeichen=uart_getc();
8
} while (zeichen=="Wie schreiben, dass zeichen nichts enthält??")
9

10
return zeichen[0];
11
}

Würde das so funktionieren? Wie kann ich schreiben, dass die Variable 
"zeichen" nichts enthält?

Gruß, Steffen
Gast #994374
Lesenswert?

>Aha, muss ich dann noch eine Funktion machen, die solange wartet, bis
>ein Zeichen da ist, also z.B. so:

Gute Idee.

>void getchar()

void ist aber nicht gut wenn man einen Wert zurückgeben will ;)

Und unsigned char zeichen[1]; kann man auf char zeichen, reduzieren.

Aber damit bist du immer noch nicht am Ziel.

>Wie kann ich schreiben, dass die Variable
>"zeichen" nichts enthält?

uart_getc() gibt einen bestimmten Wert zurück wenn
noch kein Zeichen da ist. Einfach mal in den Beispielcode schauen?
Der Wert ist ein unsigned int und kein char.
OP Persönliche Seite #994390
Lesenswert?

Sir alan Teplotaxl wrote:
>zeichen==0
>Wie wärs damit?

Aber wenn uart_getc() noch  nchts empfängt, dann steht doch in der 
Variable zeichen gar nichts, auch keine 0, oder?


holger wrote:
>>Aha, muss ich dann noch eine Funktion machen, die solange wartet, bis
>>ein Zeichen da ist, also z.B. so:
>
> Gute Idee.
>
>>void getchar()
>
> void ist aber nicht gut wenn man einen Wert zurückgeben will ;)

Ja, ich werde dann int verwenden ;-).

> Und unsigned char zeichen[1]; kann man auf char zeichen, reduzieren.

Ok, mach ich auch.

> Aber damit bist du immer noch nicht am Ziel.

>>Wie kann ich schreiben, dass die Variable
>>"zeichen" nichts enthält?
>
> uart_getc() gibt einen bestimmten Wert zurück wenn
> noch kein Zeichen da ist. Einfach mal in den Beispielcode schauen?
> Der Wert ist ein unsigned int und kein char.

Im Beispiel von Peter Fleury wird das so gemacht:
1
unsigned int c;
2
....
3
c= uart_getc();
4
        if ( c & UART_NO_DATA )
5
        {
6
            /* 
7
             * no data available from UART 
8
             */
9
        }
10
        else
11
        {
12
            /*
13
             * new data available from UART
14
             * check for Frame or Overrun error
15
             */
16
            if ( c & UART_FRAME_ERROR )
17
            {
18
                /* Framing Error detected, i.e no stop bit detected */
19
                uart_puts_P("UART Frame Error: ");
20
            }
21
            if ( c & UART_OVERRUN_ERROR )
22
            {
23
                /* 
24
                 * Overrun, a character already present in the UART UDR register was 
25
                 * not read by the interrupt handler before the next character arrived,
26
                 * one or more received characters have been dropped
27
                 */
28
                uart_puts_P("UART Overrun Error: ");
29
            }
30
            if ( c & UART_BUFFER_OVERFLOW )
31
            {
32
                /* 
33
                 * We are not reading the receive buffer fast enough,
34
                 * one or more received character have been dropped 
35
                 */
36
                uart_puts_P("Buffer overflow error: ");
37
            }
38
            /* 
39
             * send received character back
40
             */
41
            uart_putc( (unsigned char)c );
42
        }

Soll ich einfach das alles in die Funktion getchar() packen?

Gruß, Steffen
OP Persönliche Seite #994425
Lesenswert?

Ich hab die Funktion getchar() nun mal so gemacht:
1
int getchar()
2
{
3
unsigned int c;
4
do
5
{
6
c = uart_getc();
7
        
8
    if ( c & UART_NO_DATA )
9
        {
10
            /* 
11
             * no data available from UART 
12
             */
13
        }
14
        else
15
        {
16
            /*
17
             * new data available from UART
18
             * check for Frame or Overrun error
19
             */
20
            if ( c & UART_FRAME_ERROR )
21
            {
22
                /* Framing Error detected, i.e no stop bit detected */
23
                lcd_string("UART Frame Error: ");
24
            }
25
            if ( c & UART_OVERRUN_ERROR )
26
            {
27
                /* 
28
                 * Overrun, a character already present in the UART UDR register was 
29
                 * not read by the interrupt handler before the next character arrived,
30
                 * one or more received characters have been dropped
31
                 */
32
                lcd_string("UART Overrun Error: ");
33
            }
34
            if ( c & UART_BUFFER_OVERFLOW )
35
            {
36
                /* 
37
                 * We are not reading the receive buffer fast enough,
38
                 * one or more received character have been dropped 
39
                 */
40
                lcd_string("Buffer overflow error: ");
41
            }
42
      }
43
      }while(c==0);
44
      
45
      return( (unsigned char) c);
46
}

Laut Bsp. müsste das doch richtig sein, oder?

Gruß, Steffen
Gast #994464
Lesenswert?

>Kommt eigentlich bei jeder Baudrate was an, wenn es die falsche ist,
>eben nur Unsinn?

In der Regel ja. Hast du vieleicht RxD und TxD vertauscht? GND 
angeschlossen?
Wie sieht deine Schaltung aus?
Persönliche Seite #994574
Lesenswert?

holger wrote:
> Vieleicht brauchst du einen MAX232 am ATMega?
Quatsch! Hab das Modul auch an nem Mega16 hängen ohne alles.... Versuch 
mal 38400baud, das ist die Standardeinstellung des Moduls.
Ich hab das zu debugging zwechen so gemacht das ich RX des Megas 
zusätzlich an eine MAX232 und an die Serielle des PCs dann sieht man 
alles was der µC empfangen sollte nochmal auf dem PC und kann dann 
leichter verifizieren was überhaupt ankommt.
Ich würde an deiner Stelle erstmal so anfange, das du alle Empfangenen 
Zeichen bis zum \r\n auf dem LCD darstellst so das du siehst ob der 
String überhaupt korrekt ankommt.

Ich mache das folgendermaßen: (Pseudocode!)
1
Buffer[100]
2
counter = 0;
3
while(1) {
4
 c = getChar();
5
 if (c == '$') {
6
  counter = 0;
7
 }
8
 if(c == '\n') {
9
  break;
10
 }
11
 Buffer[counter++] = c;
12
}
13
toLCD(Buffer);
Danach kannst du den String in Ruhe zerlegen :)
OP Persönliche Seite #994593
Lesenswert?

Ok, ich werd dann morgen mal meinen PC parallel dazu dranhängen, dann 
sieht man was ankommt, bzw. sollte.
Ich hab nun mal 38400 Baud eingestellt, dann kommt nach dem Einschalten 
UART Frame Error, und danach beide Zeilen des Dislays voll mit X und 
einem Strich jeweils darüber.
Kann es auch sein, dass es nicht klappt, weil die Leitungen des 
Breadboards bei 38400 Baud irgendwie nicht mehr mitspielen?

Hast du auch die rote Leitung an RX, und die weiße an TX?

Ich hab nun mal deine Funktion verwendet, aber ich bekomme weiterhin 
einen UART Frame Error, nun eben nicht mit den X und den Strichen 
drüber....


Vielen Dank schon einmal im Voraus.
Gruß, Steffen
Gast #994663
Lesenswert?

Hi

Zumindest wollte ich erst mal sicherstellen, das kein RC-oszillator im 
Spiel ist.

Welche Teile deines Programms hast du schon einzeln getestet, und bist 
sicher das die funktionieren. Nur als Hintergrund: Schaltung aufbauen, 
Programm schreiben und geht, läuft selten.

Mein persönlicher Ansatz wäre einen kompletten NMEA-Sring in einen 
Puffer einlesen, und dann in Ruhe auswerten

MfG Spess
OP Persönliche Seite #995849
Lesenswert?

So, nun hab ich den Empfänger an den Mega8 angeschlossen, und dazwischen 
einen Pegelwandel, der an den PC mit nem Terminalprogramm angeschlossen 
ist.
Der GPS-Empfänger sendet brav seinen NMEA Datensatz, bei 9600 Baud, wie 
ich es eingestellt hatte. Am Terminalprogramm kann ich alle Strings gut 
lesen, und es sind keine falschen Zeichen dabei.

Also liegt es definitiv am µC, bzw. der Software. Ich poste hier nochmal 
meinen kompletten Code, der eigentlich bei 4Mhz funktionieren sollte, 
vielleicht wisst ihr ja noch was.
1
#include<avr/io.h>
2
#define F_CPU 4000000
3
#include<util/delay.h>
4
#include <stdlib.h>
5
#include <avr/interrupt.h>
6

7
#include "lcd-routines.h"
8
#include <uart.h>
9

10
#define UART_BAUD_RATE   9600
11

12
int getchar()
13
{
14
unsigned int c;
15
do
16
{
17
c = uart_getc();
18
        
19
    if ( c & UART_NO_DATA )
20
        {
21
            /* 
22
             * no data available from UART 
23
             */
24
        }
25
        else
26
        {
27
            /*
28
             * new data available from UART
29
             * check for Frame or Overrun error
30
             */
31
            if ( c & UART_FRAME_ERROR )
32
            {
33
                /* Framing Error detected, i.e no stop bit detected */
34
                lcd_string("UART Frame Error: ");
35
            }
36
            if ( c & UART_OVERRUN_ERROR )
37
            {
38
                /* 
39
                 * Overrun, a character already present in the UART UDR register was 
40
                 * not read by the interrupt handler before the next character arrived,
41
                 * one or more received characters have been dropped
42
                 */
43
                lcd_string("UART Overrun Error: ");
44
            }
45
            if ( c & UART_BUFFER_OVERFLOW )
46
            {
47
                /* 
48
                 * We are not reading the receive buffer fast enough,
49
                 * one or more received character have been dropped 
50
                 */
51
                lcd_string("Buffer overflow error: ");
52
            }
53
      }
54
      }while(c==UART_NO_DATA);
55
      
56
      return( (unsigned char) c);
57
}
58

59
int main(void)
60
{
61
unsigned char empfangen[5],nmea[3] ="",kmh_string[4],temp,Buffer[100];
62
float kmh,nurzumrechnen;
63
int counter,c;
64

65
//Uart und LCD initialisieren
66
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
67
lcd_init();
68
lcd_string("Start!");
69
_delay_ms(1000);
70
lcd_clear();
71

72
sei();
73

74

75
while(1)
76
{
77

78
temp = getchar();
79
//Zum Überprüfen
80
lcd_string(temp);
81

82

83
if(temp == '$')
84
{
85
//zwei Zeichen nach $ verwerfen
86
temp = getchar();
87
temp = getchar();
88
//Variablen zum Testen, ob RMC
89
nmea[0] = getchar();
90
//jeweils zum Test auf Display ausgeben
91
lcd_string(nmea[0]);
92
nmea[1] = getchar();
93
lcd_string(nmea[1]);
94
nmea[2] = getchar();
95
lcd_string(nmea[2]);
96
}
97

98
//Nach "E," kommt Geschwindigkeit in Knoten
99
if(temp == 'E')
100
{
101
//Nur RMC auslesen, denn nur dort ist Geschwindigkeit (in Knoten)
102
if(getchar() == ',' && nmea[0] == 'R' && nmea[1] == 'M' && nmea[2] == 'C') 
103
{
104
lcd_string("Fix gefunden!");
105

106
//Geschwindigkeit enpfangen
107
empfangen[0] = getchar();  
108
empfangen[1] = getchar();
109
empfangen[2] = getchar();
110
empfangen[3] = getchar();
111
empfangen[4] = getchar();
112

113
//Wenn Geschwindigkeit noch 2-stellig vor dem Komma, 2. Stelle hinter dem Komma = 0
114
}
115
if(empfangen[2] == '.')
116
{
117
empfangen[4] = '0';
118
}
119
//Den String "empfangen" in float umwandeln, zum Rechnen
120
nurzumrechnen=atof(empfangen);
121
//Knoten in kmh umrechnen
122
kmh = nurzumrechnen * 1.852;
123
//float wieder in String umwandeln, zum auf LCD ausgeben
124
itoa(kmh,kmh_string,10);
125
//kmh auf LCD ausgeben
126
lcd_string(kmh_string);
127
}
128
}
129
}

Auf dem Display erscheinen, wenn ich alles angeschlossen habe 
irgendwelche Zeichen, in !beiden! Zeilen, und irgendwo dazwischen kommen 
mal Bruchstücke von Overflow Error, usw..
Irgendwann kommt auch mal ein Teil von "Fix gefunden".....

Ich bin echt scheon ein wenig verzweifelt, weil ich nicht weiß, woran es 
liegt, und es partout nicht klappen will :-(.
Ich hoffe, jemand weiß noch Rat....

Vielen Dank schon einmal im Voraus.
Gruß, Steffen
Gast #995859
Lesenswert?

>lcd_string(temp);
>lcd_string(nmea[0]);

temp ist kein String. nmea[0] ist auch kein String.
Wenn du lcd_string() nur ein char übergibst jagt es
quer durch den Speicher und gibt alles aus was nicht 0 ist.
OP Persönliche Seite #995881
Lesenswert?

Also soll ich dann "temp" mit unsigned char temp[1] initialisieren, und 
immer wenn es gebraucht wird eben temp[0] schreiben?
Und bei der Ausgabe mit lcd_string nicht einen einzelnen Wert (temp[0]), 
sondern einfach lcd_string(temp) ?

Wenn dann alles ausgegeben wird, was nicht 0 ist, würde das erklären, 
warum da überall irgendwelche Zeichen auf dem Display erscheinen.
Ich werde es mal versuchen.

Gruß, Steffen

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren