Forum: Mikrocontroller und Digitale Elektronik Timer1 und UART - Atmega resettet sich


von Thinksilicon (Gast)


Angehängte Dateien:

Lesenswert?

Hallo allerseits,
seit ein paar Tagen sitz ich an einem Problem und weiß nicht, woher es 
kommt. Ich möchte den LTC4151 auslesen, der Strom und Spannung aus 
meinen Solarpanelen ausliest. Das geschieht über i2c und funktioniert 
dank der Bibliothek von Peter Fleury auch prächtig.
Als nächstes sollen diese Daten auf einem LCDisplay angezeigt werden 
(funktioniert auch) und per RS232 ausgegeben werden (hier gibt es Ärger 
- beides jeweils über pfleurys Bibliotheken verwirklicht).

Um die Arbeit zu berechnen, die die Module leisten, wird dazu jede 
Sekunde die aktuelle Leistung auf eine Variable addiert - somit habe ich 
die Ws und geteilt durch 3600s/h die Wh (ich gehe der Einfachheit halber 
davon aus, dass die Leistung innerhalb der Sekunde konstant ist). Die 
Zeit möchte ich möglichst genau haben, weshalb ich einen Timer verwende, 
der jede Sekunde einen Interrupt auslöst. In der Interruptroutine wird 
lediglich eine Variable gesetzt, die dann in meiner Hauptschleife 
ausgewertet wird.

Entferne ich die Kommentare vor den uart-Ausgaben (uart_init stellt 
dabei noch kein Problem dar), wird meine Hauptschleife einmal 
durchlaufen und es erfolgt die korrekte Ausgabe im Terminal; beim 
zweiten Durchlauf der Schleife bricht die Ausgabe bei uart_puts( 
"V\tPsol: " ); ab und der Controller resettet sich.

Meine Vermutung bisher ist, dass der Arbeitsspeicher evtl. voll läuft, 
weil danach eine float-Operation läuft. Dagegen spricht allerdings, dass 
der erste Schleifendurchlauf ja klappt. Wo liegt also mein Problem?

Ursprünglich hatte ich einen Atmega32 vorgesehen, aber keinen mehr übrig 
gehabt, also bin ich auf einen Atmega8 ausgewichen. Der ist mit dem 
Programm derzeit zu etwa 60% belegt (Flash) also auch noch nichts 
dramatisches...

Danke für eure Hinweise!

von Karl H. (kbuchegg)


Lesenswert?

> Programm derzeit zu etwa 60% belegt (Flash) also auch noch nichts
> dramatisches...

Wie hoch ist die SRAM Belastung? (.data)

von Karl H. (kbuchegg)


Lesenswert?

Das einzige echte Problem, das ich auf die Schnelle sehen kann, befindet 
sich hier
1
void uart_putf( float data ) {
2
  char buffer[ 7 ];
3
  uart_puts( dtostrf( data, 7, 2, buffer ) );
4
}

bzw.
1
void lcd_putf( float data, uint8_t digits ) {
2
  char buffer[ digits ];
3
  lcd_puts( dtostrf( data, digits, 2, buffer ) );
4
}

deine Buffer sind um 1 zu klein.

Auch immer drann denken: Was du hier

     dtostrf( data, 7, 2, buffer )
                   ***

angibst ist die >minimale< 'Fieldwidth', d.h. auf welche Zeichenbreite 
dtostrf die Ausgabe formatieren soll (und daher ist das auch kein Bug 
mit den führenden Leerzeichen, das ist genau das was du angefordert 
hast). Das ist NICHT die Größe des bereitgestellten char-Arrays! Deine 
char-Arrays sind damit erst mal mindestens um 1 zu klein, weil ja ein 
String mit strlen==7 ein Array der Größe 8 braucht.

Aber: dtostrf kann und wird diese minimale Fieldwidth auch 
überschreiten, wenn sich das mit der konkret darzustellenden Zahl nicht 
ausgeht. Bei einer Fieldwidth von zb 5 und 2 Nachkommastellen, passt nun 
mal die Zahl -123.45 nicht mehr in ein Feld der Breite 5 und dtostrf 
erweitert das eigenmächtig zu 7, wodurch der von dir bereitgestellte 
Buffer auf jeden Fall viel zu klein ist und du irgendwas am Stack 
überbügelst.

-> an dieser Stelle lohnt es nicht zu kleckern! Dimensioniere deine 
Arrays ausreichend groß und mit fixen Zahlen! Der Speicher wird sowieso 
immer nur kurzzeitig während der Abarbeitung der Funktion benötigt und 
ist danach wieder frei.


Abgesehen davon, sehe ich jetzt erst mal nichts großartig schlimmes. Ok, 
die Sache mit dem _delay_ms kann man noch ankreiden, aber das ist erst 
mal kein Showstopper.

von Thinksilicon (Gast)


Lesenswert?

Hallo,
vielen Dank für die Antworten! Ja, ich denke dann auch mal stark, dass 
es an meinem zu kleinen Buffer liegt; das war mir irgendiwe entgangen. 
Habe es jetzt mal auf 10 hochgestellt, damit für Komma, Minus und ggf. 
String-Terminator Platz ist. Werde es heute Nachmittag gleich testen und 
berichten!

Memory Usage mit Änderungen:
1
avr-size --mcu=atmega8 -C atm32test.elf
2
AVR Memory Usage
3
----------------
4
Device: atmega8
5
6
Program:    4998 bytes (61.0% Full)
7
(.text + .data + .bootloader)
8
9
Data:        194 bytes (18.9% Full)
10
(.data + .bss + .noinit)

Grüße

von Karl H. (kbuchegg)


Lesenswert?

> Data:        194 bytes (18.9% Full)

das reicht noch dicke. Da musst du nicht sparen und mit Buffergrößen 
kleckern.

von Thinksilicon (Gast)


Lesenswert?

Ok,
nochmal meinen herzlichen Dank! Jetzt klappt's!

Steht schön am Display 0,29A bei 36,9V -> 10,6W und entsprechend auch 
alle Werte nochmal aus der Seriellen ;)

Hab jetzt auch noch eine kleine routine drin, die die Arbeit alle 10 
Minuten im EEPROM speichert, d.h. wenn mal Strom für µC ausfällt, hab 
ich die Messwerte noch parat.

Grüße

von Der (Gast)


Lesenswert?

Thinksilicon schrieb:
> Hab jetzt auch noch eine kleine routine drin, die die Arbeit alle 10
> Minuten im EEPROM speichert,

Tipp: Das EEPROM kann man nicht beliebig oft beschreiben, nach x mal 
geht es kaputt. Das Datenblatt gibt über das x Auskunft.

von Thinksilicon (Gast)


Lesenswert?

Deswegen auch nur alle 10 Minuten, vielleicht stell ich auch auf halbe 
Stunde hoch... im Normalfall ist ja Strom da.

von Sonne (Gast)


Lesenswert?

Hallo  Thinksilicon!


Nur ne kleine Idee:

Häng doch ne I²C-Uhr mit Notstrom-Knopfzelle mit ran.
Dadurch hast Du Batterie-gestützten Ram, in dem Du Deine Leistungswerte 
seit Installation ablegen kannst (auf dem EEPROM wird also nicht 
rumradiert) und Du hast stets ne genau Zeit (incl. Sec-Tick), selbst 
wenn Du zu Wartungszwecken o.ä. das Gerät mal zerlegen/abklemmen musst.


Gruss - Sonne

von Thinksilicon (Gast)


Lesenswert?

Ok,
die Idee klingt gut! Vorallem, weil ich da noch genaueres Zeitsignal 
habe. Kannst du da einen Baustein empfehlen? Auf die Schnelle hätte ich 
jetzt mal den DS1307 gefunden, der noch 56 Byte freien nvRAM hat. Da 
gibts auch bei der Bucht paar günstige Module - ja ich glaub, da werd 
ich wohl mal noch ne RTC einbauen ;)

von Bus-Fahrer (Gast)


Lesenswert?

Bisher habe ich nur mit den MCP79410 (von anderen wurde hier im Forum 
wegen mangelnder Genauhigkeit abgeraten) gearbeitet.

http://www.reichelt.de/ICs-MCP-6-9-/MCP-79410-I-SN/3/index.html?;ACTION=3;LA=446;ARTICLE=109808;GROUPID=5473;artnr=MCP+79410-I%2FSN

Eckdaten:

Preis:       1,10€
Spannung:    1,8V bis 5,5V
EEPROM:      1k
SRAM:        64Byte
Calibration: -127 bis +127ppm digital (also kein Trimm-C!)

weiterhin:
1Hz-Signal-Ausgang
Kalender mit Tag/Monat/Jahr incl. Schaltjahr-Berücksichtigung
einfache Schaltung ohne Trimm-C


Habe damit ein Steck-Modülchen gebaut und ist in diversen Schaltungen 
brav mit dabei.


Gruss - Sonne

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.