Hallo, Ich habe einen ATMega1280 auf einem Arduino Mega Board, und programmiere ihn auch mit der Arduino IDE. Bislang hat alles super geklappt, aber jetzt bin ich an einem Punkt angekommen, wo eine zusätzliche Lib plötzlich Arrays überschreibt. Ich nehme an, dass ich da irgendeine Grenze überschritten habe. Als Info: Ich lese seriell diverse Sensoren aus, und packe alle zu einem großen String zusammen, den ich dann seriell im ganzen ausgebe. Der Ausgangsstring ist dabei jetzt schon auf 902 Bytes angestiegen, daher die frage, ob es überhaupt sinvoll ist, die Daten erst in einem Ausgangsstring zusammenzufassen, und als Paket zu übertragen, oder einfach alle Werte einzeln zu übertragen. Und dann die Frage, ob das überhaupt mein Problem ist. Ich hatte auch eine Funktion zum hinzufügen einer Checksumme eingebaut, aber bei der war das das selbe: Wenn ich nur einen Sensor auslese, kein Problem. Setze ich aber alles zusammen, gehts durcheinander. Ich hoffe, Ihr versteht mein Problem. Danke schonmal für Anregungen!
Jürgen Papadopolis schrieb: > Als Info: Ich lese seriell diverse Sensoren aus, und packe alle zu einem > großen String zusammen, den ich dann seriell im ganzen ausgebe. Das kann bis zu einem gewissen Grad Sinn machen. > Der Ausgangsstring ist dabei jetzt schon auf 902 Bytes angestiegen, 902 Bytes macht allerdings keinen Sinn mehr. > daher die frage, ob es überhaupt sinvoll ist, die Daten erst in einem > Ausgangsstring zusammenzufassen, und als Paket zu übertragen, oder > einfach alle Werte einzeln zu übertragen. Wenn du es richtig machst, kann dein Empfänger sowieso keinen Unterschied feststellen. Ich weiß nicht, wie die Arduino eigenen Übertragungsfunktionen arbeiten, aber wenn die halbwegs was taugen (und davon gehe ich aus), dann arbeiten die Interrupt gesteuert im Hintergrund, d.h. während dein Hauptprogramm den nächsten Sensor abfrägt und den Teilstring zusammensetzt, findet im Hintergrund die Übertragung des zuletzt abgefragten Sensors statt. Und ehe die fertig ist, hat dein Hauptprogramm schon wieder den nächsten Teil fertig, so dass es zu keiner Unterbrechung im Datenstrom nach aussen kommt. > Und dann die Frage, ob das überhaupt mein Problem ist. Das kannst nur du beantworten. Du hast 8K SRAM zur Verfügung. Wieviel davon vom Arduino System selbst belegt wird, kann ich nicht sagen. > aber bei der war das das selbe: Wenn ich nur einen Sensor auslese, kein > Problem. Setze ich aber alles zusammen, gehts durcheinander. Kann aber auch genausogut ein Fehler in deinem Programm sein
Anregung 1 : Zeige dein Quelltext. Wir können nicht hell sehen. Anregung 2 : Schaue in dein Map-File. Dort steht drin ob du Grenzen überschritten hast. Anregung 3 : Beschreibe deinen Fehler genauer. Wo (Anfang Ende) wird was uberschrieben. Anregung 4 : Gebe nur immer kleine Teile aus. z.B. jeden Sensor für sich. Ergiebt einen kleinen Buffer.
Also, den kompleten Code will ich euch nicht um die Ohren hauen, ist mittlerweile sehr umfangreich. Aber hier mal die Funktion, mit der ich 4 Zeilen aus einem GPS auslese:
1 | /*****************************************************************
|
2 | ** GPS **
|
3 | ** Umschalten eines UART-Kanals über HCT4052 auf ein **
|
4 | ** angeschlossenes GPS-Gerät **
|
5 | ** Auslesen der über GPS_Zeilen vorgegebenen Anzahl an NMEA- **
|
6 | ** Datensätzen **
|
7 | ****************************************************************/
|
8 | |
9 | char* GPS(void){ |
10 | // Umschalten der YB auf GPS
|
11 | digitalWrite(swPinS0, HIGH); |
12 | digitalWrite(swPinS1, LOW); |
13 | GPSstart:
|
14 | i=0; |
15 | int Zeile=0; |
16 | |
17 | while(1) { |
18 | GPSin[i]=Serial.read(); |
19 | // Wenn Datensatz nich am Anfang eingelesen wurde nochmal
|
20 | // GPS versuchen
|
21 | if(GPSin[0] != 36){ |
22 | goto GPSstart; |
23 | }
|
24 | // Wenn LF gelesen wurde, Zeile erhöhen
|
25 | if(GPSin[i]==10) { |
26 | Zeile++; |
27 | // Per 'GPS_Zeilen' festgelegte Anzahl von NMEA-Datensätzen auslesen
|
28 | if(Zeile==GPS_Zeilen) break; |
29 | }
|
30 | // Wenn kein Byte gelesen wird, Zähler nicht erhöhen
|
31 | if(GPSin[i]!=-1) i++; |
32 | }
|
33 | GPSin[i+1] = 0; |
34 | //Ausgabe print hier nur zum debuggen
|
35 | Serial2.print(GPSin); |
36 | return GPSin; |
37 | }
|
Ein Datensatz mit eingebundenen lib sieht so aus: $GPHDT,,T*1B $GPGGA,,,,,M,,,6 GPG,,,,NK,2C$GSA,1,,,,,,,* $GHDT,,T*1B $GPGGA,,,,,,0,,,,M,,M,,*66 korrekt wäre aber $GPHDT,,T*1B $GPGGA,,,,,,0,,,,M,,M,,*66 $GPVTG,,T,,M,,N,,K,N*2C $GPGSA,M,1,,,,,,,,,,,,,,,*12 So kommt es auch an, wenn ich die Library rausschmeiße. GPSin ist ein Array mit 330 Bytes. Das GPS liefert NMEA-Daten. Pro Datensatz kommen 82 Bytes enthalten sein, daher so groß. Es wird auch bisher nur in der Funktion für das GPS überschriebeb, und nicht bei jedem Durchlauf. Jeder zweite oder dritte Datensatz kommt korrekt.
wie gross ist denn GPSin? du prüfst in der schleife nicht die länge ab, wenn du zu viele zeichen bekommst dann überschreibst du dir alles was nach GPSin im Ram liegt.
Also wie gesagt, GPSin ist deklariert als
1 | char GPSin[330]; |
Größer kann der Datensatz nicht werden, der übertragen wird. Ich hab grade nochmal alle anderen Funktionen rausgeschmissen, und lasse nur das GPS auslesen. Soabal ich die Library drin habe, kommt der selbe Quatsch raus. Ohne ist alles super.
Jürgen Papadopolis schrieb: > Größer kann der Datensatz nicht werden, der übertragen wird. das sagst du, denn mach aber auch eine Prüfung in die schleife damit du bei 330 auch schluss machst.
Ok, ich unterbreche die While-Schleife nun, wenn i > 330 ist. Aber das Problem ist damit nicht behoben.
Jürgen Papadopolis schrieb: > Also, den kompleten Code will ich euch nicht um die Ohren hauen, ist > mittlerweile sehr umfangreich. Aber hier mal die Funktion, mit der ich 4 > Zeilen aus einem GPS auslese: Was mit an deinem Code nicht gefällt, ist zb. dass i offenbar ein gloable Variablen ist. Speziell bei dem Namen i (der gerne mal für Schleifenzähler u. dgl. verwendet wird) steht hier Tür und Tor offen, dass es irgendwo anders verändert wird. Solche Variablen solltest du immer funktionslokal definieren um eben genau das zu verhindern. Grundsätzlich möchtest du die Sichtbarkeit einer Variablen soweit wie möglich einschränken, genau aus dem Grund um nicht den Überblick zu verlieren, welcher Code sich an welcher Variablen zu schaffen macht. Speziell wenn Interrupts ins Spiel kommen, bzw. Funktionsaufrufe über mehrere Hierarchiebenen gehen, dann wird das ziemlich rasch unnötig komplex zu durchschauen. Auch solltest du goto vermeiden, wenn es Alternativen gibt, die einfacher zu durchschauen sind.
1 | /*****************************************************************
|
2 | ** GPS **
|
3 | ** Umschalten eines UART-Kanals über HCT4052 auf ein **
|
4 | ** angeschlossenes GPS-Gerät **
|
5 | ** Auslesen der über GPS_Zeilen vorgegebenen Anzahl an NMEA- **
|
6 | ** Datensätzen **
|
7 | ****************************************************************/
|
8 | |
9 | char* GPS(void){ |
10 | int i = 0; |
11 | int Zeile = 0; |
12 | |
13 | int Zeichen; |
14 | |
15 | // Umschalten der YB auf GPS
|
16 | digitalWrite(swPinS0, HIGH); |
17 | digitalWrite(swPinS1, LOW); |
18 | |
19 | //
|
20 | // alles bis zum nächsten '$' einfach überlesen
|
21 | //
|
22 | do { |
23 | Zeichen = Serial.read(); |
24 | } while ( Zeichen != '$' ); |
25 | |
26 | //
|
27 | // der Anfang des nächsten NMEA Satzes wurde gefunden
|
28 | // ab hier Zeichensammeln, bis eine entsprechende Anzahl an Zeilen
|
29 | // zusammengekommen ist
|
30 | //
|
31 | GPSin[0] = Zeichen; |
32 | |
33 | while( Zeile < GPS_Zeilen && i < sizeof(GPSin) - 1 ) { |
34 | Zeichen = Serial.read(); |
35 | |
36 | if( Zeichen != -1 ) { |
37 | GPSin[i++] = Zeichen; |
38 | if( Zeichen == '\n' ) |
39 | Zeile++; |
40 | }
|
41 | }
|
42 | |
43 | //
|
44 | // die Zeilen sind soweit vollständig. Den String noch abschliessen
|
45 | //
|
46 | GPSin[i] = '\0'; |
47 | |
48 | Serial2.print(GPSin); |
49 | |
50 | return GPSin; |
51 | }
|
Beachte auch: if(GPSin[0] != 36 if(GPSin[i]==10) Benutze keine direkten ASCII Codes wie 36 oder 10, wenn es nicht notwendig ist! Du gewinnst nichts dadurch. Bei if(GPSin[0] != '$' if(GPSin[i] == '\n') ist es um einiges leichter zu durchschauen, was hier die Absicht ist.
wo kommt i überhaupt her? Ist i etwa Global? kann es sein das jemand anderes i noch ändert?
i ist eigentlich global, wird aber in den Funktionen immer auf 0 gesetzt. Da sollte doch nichts dazwischenfunken können innerhalb einer Funktion, oder? Hab jetzt mal alles ausgeschlossen, indem ich das Programm komplett eingedampft habe nur auf die GPS Funktion. Also wird auch i von sonst niemandem benutzt. Der Fehler ist trotzdem da. Der momentan komplette Code ist:
1 | #include <NewSoftSerial.h> |
2 | |
3 | #define GPS_Zeilen 4 // Anzahl zu lesender GPS NMEA-Datensätze
|
4 | |
5 | char GPSin[330]; |
6 | int i; |
7 | |
8 | int swPinS0 = 26; |
9 | int swPinS1 = 27; |
10 | int WLANreset = 48; |
11 | int SerialCommandMode = 49; |
12 | int SerialACT = 51; |
13 | |
14 | |
15 | NewSoftSerial Wind(50,60); |
16 | |
17 | void setup() { |
18 | |
19 | Serial.begin(19200); // INC / GPS |
20 | Serial2.begin(19200); // RS232 OUT |
21 | Wind.begin(4800); // Windmuehle über SoftSerial |
22 | |
23 | pinMode(swPinS0, OUTPUT); // SchaltPins fuer Umschaltung INC/GPS ueber HTC4052 |
24 | pinMode(swPinS1, OUTPUT); // " |
25 | pinMode(SerialCommandMode, OUTPUT); // SchaltPin fuer WLAN-Modul CommandMode |
26 | pinMode(SerialACT, OUTPUT); // LED Ansteuerung SerialAct |
27 | pinMode(WLANreset, OUTPUT); // WLAN-Modul Reset-Pin |
28 | }
|
29 | |
30 | /*****************************************************************
|
31 | ** GPS **
|
32 | ** Umschalten eines UART-Kanals über HCT4052 auf ein **
|
33 | ** angeschlossenes GPS-Gerät **
|
34 | ** Auslesen der über GPS_Zeilen vorgegebenen Anzahl an NMEA- **
|
35 | ** Datensätzen **
|
36 | ****************************************************************/
|
37 | |
38 | char* GPS(void){ |
39 | // Umschalten der YB auf GPS
|
40 | digitalWrite(swPinS0, HIGH); |
41 | digitalWrite(swPinS1, LOW); |
42 | GPSstart:
|
43 | i=0; |
44 | int Zeile=0; |
45 | |
46 | while(1) { |
47 | GPSin[i]=Serial.read(); |
48 | // Wenn Datensatz nich am Anfang eingelesen wurde nochmal
|
49 | // GPS versuchen
|
50 | if(GPSin[0] != 36){ |
51 | goto GPSstart; |
52 | }
|
53 | // Wenn LF gelesen wurde, Zeile erhöhen
|
54 | if(GPSin[i]==10) { |
55 | Zeile++; |
56 | // Per 'GPS_Zeilen' festgelegte Anzahl von NMEA-Datensätzen auslesen
|
57 | if(Zeile==GPS_Zeilen) break; |
58 | }
|
59 | // Wenn kein Byte gelesen wird, Zähler nicht erhöhen
|
60 | if(GPSin[i]!=-1){ |
61 | i++; |
62 | if (i >330) break;} |
63 | }
|
64 | GPSin[i+1] = 0; |
65 | //Ausgabe print hier nur zum debuggen
|
66 | Serial2.print(GPSin); |
67 | return GPSin; |
68 | }
|
69 | |
70 | /****************************************************************
|
71 | * MAIN *
|
72 | ***************************************************************/
|
73 | |
74 | void loop(){ |
75 | |
76 | digitalWrite(SerialCommandMode, HIGH); |
77 | digitalWrite(WLANreset, LOW); |
78 | GPS(); |
79 | }
|
Jürgen Papadopolis schrieb: > i ist eigentlich global, wird aber in den Funktionen immer auf 0 > gesetzt. Da sollte doch nichts dazwischenfunken können innerhalb einer > Funktion, oder? Tus trotzdem nicht. Eine Variable mit dem Namen i macht man nicht global. Das schreit förmlich nach schwer zu findenden Fehlern. Und geh besser nicht davon aus, dass du nie Fehler machst.
Jürgen Papadopolis schrieb: > ist eigentlich global, wird aber in den Funktionen immer auf 0 > gesetzt. Da sollte doch nichts dazwischenfunken können innerhalb einer > Funktion, oder? doch, wir wissen ja nicht was in Serial.read() passiert, vielleicht verwendest du dort auch i.
Ja, hab ich auch grade drüber nachgedacht, und alle i durch GPS_i ersetzt...Leider ohne Erfolg. Ich tippe langsam darauf, dass die Lib NewSoftSerial irgendwie fehlerhaft ist. Ich weiß nicht, wie weit Ihr Euch mit der Arduino-Umgebung und den Libs auskennt. Hatte vorher die SoftwareSerial drin, die über einen Digital i/o Pin einen UART simuliert. Das ging auch ganz gut, bis ich den Sensor daran ersetzen musste, und die Funktion nur Müll lieferte. Ich schätze, dass framing stimmte damit nich mehr. Die NewSoftSerial funktioniert für sich alleine eigentlich super, aber scheinbar macht sie doch irgendwie ärger... Son mist!
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.