Hallo zusammen, bin bei meinem uC-Projekt jetzt das zweite mal mit meinem Latein am Ende und hoffe, dass mir hier jemand helfen kann. Worum geht es überhaupt? Ziel des Projektes ist es einen Hager EHz-Zweirichtungszähler auszulesen und den Momentanverbrauch/Einspeisewert anzuzeigen. Hierzu benutze ich einen atmega8, welcher den Wert auf 4 7-Segmentanzeigen wiedergibt. Beschaltung: Versorgungsspannung beträgt 12V Gleichstrom die mit einem 1000uF Kondensator stabilisiert wird und dann mit der im AVR-Tutorial vorgeschlagenen Schaltung auf 5V gebracht wird. Der uC läuft mit einem 4 MHz Quarz, PortD wird zur ansteuerung der einzelnen Segmente genutzt(100 Ohm Wdst), während PortC 0-3 die einzelnen Displays zum Multiplexen steuert(1000/10000 Ohm an Transistorbasis). C5 ist mit einem externen 10kOhm Pull-up belegt, und über einen Phototransistor mit Masse verbunden, hier wird die Infrarotschnittstelle des Zählers ausgelesen. Der UART wurde nicht benutzt, da der mir PortD zerlegen würde. Über B0 soll später ein Relais angesteuert werden (Idee hierzu: Transistor Kollektor-Emitter liegen 12 V and und die Basis wird mit den 5V vom uC geschaltet), aktuell liegt hier eine LED drauf zur Funktionsprüfung. Code: Befindet sich im Anhang, ist soweit auch gut kommentiert hoffe ich, falls fragen nur her damit. Das Problem: Im Prinzip funktioniert das ganze super und alles was noch fehlt wäre die Relaisansteuertung, allerdings hört der uC in unregelmäßigen Abständen auf die Anzeige korrekt zu Multiplexen, im gegebenen Fall bedeutet das, dass nur noch die ganz rechte Ziffer angezeigt wird, der rest nicht mehr. Zusätzlich fällt auf, dass die angezeigte Ziffer flackert, also nicht mehr die 60Hz wiedergabe Frequenz hat, die sie eigentlich durch das Multiplexen haben sollte. Resette ich den uC(Strom klauen und wieder anschließen, also Poweronreset) funktioniert wieder alles. Den genauen Zeitraum des Ausfalls kann ich nicht benennen, da ich weder Zeit noch Lust habe, mich die ganze Zeit in den Keller zu setzen und auf einen Ausfall zu warten. Bisher haben Ausfälle Zeiträume zwischen ein paar Stunden und einigen Tagen gedauert. Gruß Florian
Hallo Florian, wieviel SRAM besitzt der ATMEGA8 und wieviel SRAM verbraucht Dein Programm? Wenn Du die 500 Bytes der Variablen "log" erheblich reduzierst, dann dürfte das Programm vielleicht laufen. Ein Tip am Rande: Informiere Dich über Speicherklassen in "C". Bernhard
Flash hab ich 8kB davon sind laut Eclipse 6792 Byte belegt, SRam hat der Käfer 1kB davon sind laut Eclipse 417 Byte belegt. Das Programm läuft ja auch, nur steigen die Segmentanzeigen aus. Die log[] Variable soll demnächst auch komplett verschwinden, da ich das einlesen on-the-fly implementieren möchte. Gruß Florian
Gast
#2763968
> SRam hat der Käfer 1kB davon sind laut Eclipse 417 Byte belegt.
Schieb mal die funktionslokalen Variablen in den globalen Bereich, dann
bekommst Du eine grobe Abschätzung (hier: 970 Bytes) was Du tatächlich
verbrauchen kannst.
Ich tippe auf einen Speicherüberlauf.
Gast
#2763972
Florian T. schrieb: > Flash hab ich 8kB davon sind laut Eclipse 6792 Byte belegt, SRam hat der > Käfer 1kB davon sind laut Eclipse 417 Byte belegt. Die ganzen Float-Variablen sind ziemlich überflüssig, da der Wertebereich sehr begrenzt ist und mit höherer Genauigkeit durch passend normierte Integer abgebildet werden kann. Was passiert denn auf den Datenleitungen zum Display, wenn die Anzeige hängt?
Bestätige: 6468 Flash, 917 SRam. Inwiefern würde ein Speicherüberlauf zum Versagen des Multiplexens führen? Das eingelesene Protokoll ist immer gleich groß und kürzer als die 500 Byte. Es kommt etwa alle 1-4 Sekunden ein Protokoll rein und es läuft über mehrere Tage stabil, wieso sollte es dann plötzlich nach x tausend Paketen einen überlauf geben? Auch ist die im Einlese abschnitt
1 | |
2 | |
3 | |
4 | |
5 | |
in der Bedingung festgemacht, das es nicht zu einem Speicherüberlauf kommen kann, nach 500 Zeichen bricht er einfach ab. Aus meinem Blickwinkel kann es an diesem Stück zu keinem Überlauf kommen, oder übersehe ich was essentielles? Florian Edit: @Werner: Müsste ich auf den nächsten Ausfall warten und mich dann mal mit nem Multimeter dransetzen. Wenns soweit ist werde ich das dann hier posten.
Gast
#2764006
> Das eingelesene Protokoll ist immer gleich groß und kürzer > als die 500 Byte. Was passiert bei einem Übertragungsfehler? Oder bei mehreren? Der Stack brauch ja auch noch Platz. Ein mögliches Szenario ist dass das Ende vom 'log'-Puffer normalerweise(tm) nicht vollschreibst weil das Endsymbol rechtzeitig gefunden wird. Wenn das mal nicht kommt müllst zu möglicherweise fröhlich fremden Speicher voll ('fremd' wegen Überlappung, z.B. mit dem Stack). Das Beispielpaket, das Du im Quellcode angegeben hast, hat etwa 157 Zeichen. Braucht also wei weitem keine 500 Bytes. Und mit etwas State-Machine könnte man das noch auf < 20 Bytes (!!) runterbrechen.
g457 schrieb: > Wenn das mal nicht kommt müllst zu > möglicherweise fröhlich fremden Speicher voll Da steht aber immer noch die Abbruchbedingung im Weg, das Array soll im Endeffekt sowieso rausfliegen, steht auch irgendwo im Code also TODO markiert. Und selbst angenommen ich mülle fremden Speicher zu, warum sollte dann das Display ausfallen? Überschreibe ich die Multiplexfunktion? Kaum sonst würde ja nach einem reset nicht alles wieder gehen. Soweit ich das beurteilen kann funktioniert das restliche Programm auch bei spinnen der Anzeige richtig, sprich ich sehe sowohl den im Quellcode als "Einlesepunkt" als auch den "Verarbeitungspunkt" bezeichneten DP auf den Anzeigen aufblitzen wenn er liest und verarbeitet Florian
Gast
#2764044
> Da steht aber immer noch die Abbruchbedingung im Weg, Nein, tut sie nicht, weil im angegebenen Szenario der Speicher überlappt. Und nein, das sieht man an den Ausgaben von avr-size nicht. > das Array soll im Endeffekt sowieso rausfliegen, steht auch irgendwo im > Code also TODO markiert. Mach das. Und wenn Du es richtig(tm) machst brauchst Du statt grob 500 Bytes nur noch die vorhin vorgeschlagenen < grob 20. > warum sollte dann das Display ausfallen? Warum sollte es nicht? Fremden Speicher begrapschen == undefinierter Zustand. Räum doch mal auf und schau ob sich was tut. Kann auch gut sein, dass das Problem ganz woanders herkommt. Aber wissen wirst Du es nicht bis Du es ausprobiert hast.
Gast
#2764048
Florian T. schrieb: > Müsste ich auf den nächsten Ausfall warten und mich dann mal mit nem > Multimeter dransetzen. Eher ein DSO/LA. Wenn du verstanden hast, was der Prozessor dann tut, kannst du ihn wenigstens per Watchdog rausreißen, auch wenn die Ursache damit natürlich noch nicht behoben ist. Beim nächsten Mal kannst du dann das DSO/LA gezielt auf die Bedingung triggern.
Hallo nochmal, hatte grad wieder einen Ausfall, das Programm ist mittlerweile umgeschrieben, das on the fly funktioniert nicht, aber das log[] array wurde um 340 Byte verkleinert, also noch 160 Byte groß. Hab mir dann auch gleich mal ein Multimeter geschnappt und geguckt was an den Pins los ist, n Oszi hab ich noch nicht deshalb Multimeter. Ergebniss der Messungen: An den Pins tut für die Transistorsteuerung tut sich gar nichts mehr, kein Strom keine Spannung, sind also auf GND Niveau. Werner schrieb, dass man sowas via Watchdog "retten" kann, wie soll das Funktionieren? Florian
So ein Interrupt-Aufruf brauch immer etwas Speicher auf dem Stack. Sollte nun das Programm bedingt durch Stacküberlauf diesen Speicher verheizt haben, wird zwar trotzdem ein Interrupt immer noch ausgelöst, aber der Stackpointer sitzt im Nirvana und eine Rücksprungadresse wird nicht sinnvoll abgespeichert. Wird die Rücksprungadresse dann gelesen aus dem Nichtdefinierten Speicherbereich gibts einen Crash. Wenn es dir nicht zuviel Aufwand ist, könntest du in der ISR ja mal (vorausgesetzt ein ISR wird immer ausgelöst) einen Punkt auf dem Display setzen wenn der Stackpointer seinen legalen Bereich verläßt.
Gast
#2765053
Hast du Die Avr beschaltung komplett? Sprich 100n zwischen Vcc und Gnd, Vcc 10k zu Reset, Gnd 47n Reset Ich hatte durch einen nicht ordentlich verlöteten Reset Pin recht Ähnliche unerklährliche ausfälle in einem Mega 16 Mfg
Das ist ne Idee, allerdings hab ich keine Ahnung wie man sowas implementieren soll, kannst du mir da mal einen Denkanstoss geben? Wie würde ich denn raus kriegen, dass er seinen legalen Bereich verlässt? Florian Edit: Spannung ist mit Kondensatoren stabilisiert und Reset wird mit 10k auf VCC gezogen, GND ist allerdings nicht über nen Kondensator mit RESET verbunden, warum sollte das so sein?
Der Legale Bereich beim AVR Mega8 ist zwischen 0x0060 und 0x045F. Dieser Beinhaltet natürlich dann auch noch alle global angelegten Variablen im unteren Bereich. Hat aber so noch keinen Einfluß auf den ISR selbst. Die Passenden IO-Register des Stackpointers sind SPL & SPH für Low und HighByte. Was mir aber gerade nochmal einfällt, der SRAM-Bereich zwischen 0x0000 und 0x005F sind die üblichen IO-Register endend mit S-REG und SPL/SPH. Du solltest dann vielleicht schon den Stackpointer < 0x0065 oder ähnlich prüfen. Ein Stack-PUSH bei Stackpointer Adresse 0x005F löst noch lange keinen Fehler aus, überschreiben aber schon SREG & SPH/SPL (den Stackpointer selbst). Wenn der Stackpointer natürlich schon 0x005F ist, ist schon alles zu spät. Alle Globalen Variable sind verhunzt.
Ich würde sogar sagen, wenn der Stack dein Problem wäre, würdest du das früher bemerken. Durch Überschreiben der Globalen Variablen müßte da viel Falsch berechnet werden etc.
Ich werd bei nach meiner letzten Klausur am Mittwoch mal deinen vorgeschlagenen Test implementieren. Du sagst aber das es eher was anderes ist, weil es erst sehr spät auftritt? Würde sich mit meiner Unschuldsvermutung decken, da bisher immer sinnvolle Werte angezeigt werden, außer wenn er sich halt grad mal getötet hat.
Gast
#2765138
Florian T. schrieb: > Werner schrieb, dass man sowas via Watchdog "retten" kann, wie soll das > Funktionieren? Dazu mußt du erstmal verstehen, welcher Programmteil im Fehlerfall nicht geordnet durchlaufen wird. Dort kann man den Befehl zum Löschen des Watchdog Timers einbauen. Im Fehlerfall wird dann der WDT nicht mehr regelmäßig gelöscht und es erfolgt automatisch ein Reset. Besser wäre aber auf jeden Fall, die wahre Fehlerursache zu beseitigen.
ISR(TIMER0_OVF_vect){
icount++;
PORTC=0;
PORTD=show[display[pos]];
PORTC|=(1<<pos);
if(pos==0&&einspeisen==1) /*Punkt ob eingespeist wird oder nicht*/
PORTD&=~(1<<7);
if(pos==1&&powered==1) /*Punkt ob WP gepowered oder nicht*/
PORTD&=~(1<<7);
pos++;
if(pos>3) /*Display hat nur 4 Elemente*/
pos=0;
}
Die globalen Variablen dürften erst spät überschrieben werden.
Den Inhalt von display[pos] solltest du vielleicht vor show[ prüfen.
Ein paar Ideen zur Optimierung:
Die Variable pos wird außerhalb des Refresh-LED-ISR genutzt ?
Wenn nicht mach es als static mit in den ISR.
- ein "if(pos>3)pos=0" kann man auch als "pos &=3" schreiben.
- volatile unsigned char show[11] kannst du in den ROM verschieben.
(PROGMEM) oder mindestens als const deklarieren (volatile wird
überflüssig, da es sich nicht ändert)
while(1){
icount=40; /*Protokoll einlesen und Auswerten dauert etwa 40
Interrupts die nicht gezählt werden*/
sei();
while(PINC&(1<<5));
cli();
ist es möglich das dieses sei() nicht mehr erreicht wird im Fehlerfall ?
Hab die Optimierungen mal umgesetzt und werd das ganze bei Gelegenheit mal auf den Käfer packen. Bei der PROGMEM optimierung bin ich mir unsicher, muss ich da nicht pgm_read_byt verwenden um da dann drauf zuzugreifen? Florian
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmspeicher_.28Flash.29 Dein volatile unsigned char show[11]={0b11000000,0b11111001,0b10100100,0b10110000,0b10011001,0b10010 010,0b10000010,0b11111000,0b10000000,0b10010000,0b00000000}; /*Segmentcodes für Display*/ ist ja eh nur ein Byte. const unsigned char show[11] PROGMEM = {0b11000000,0b11111001,0b10100100,0b10110000,0b10011001,0b10010010,0b100 00010,0b11111000,0b10000000,0b10010000,0b00000000 }; in der ISR dann PORTD=show[display[pos]]; wird zu PORTD=pgm_read_byte(show+display[pos]);
Ah super genauso hab ichs gemacht, außer das da nicht PORTD=pgm_read_byte(show+display[pos]); sondern PORTD=pgm_read_byte(show[display[pos]]); steht ich nehme an das + war ein Tippfehler? Werde zusätzlich mal vergleiche etwas kleiner machen, auf 7, das spart dann 12 Floats ein, also 12*32 Byte. Das ganze auf den Käfer und beobachten. Florian
Nach kurzem Schockmoment (auf einmal zeigte er Sachen wie n und P an), hab ich nochmal genauer nachgelesen und gesehen, dass da ein Adressoperator fehlt, läuft jetzt erstmal mit den ganzen Optimierungen. Mal schauen ob er immer noch zu schwachsinn übergeht oder nicht. Florian
Da bin ich wieder, hatte vorhin nach etwa 23 Std Laufzeit wieder einen Ausfall. Angezeigt wurde wie immer nur noch das rechte Display. Was mir aufgefallen ist, dass ein nicht vorhandener Segmentcode angezeigt wird. Quasi eine 6 ohne Segment a. Datenempfang findet immer noch statt, ich sehe sowohl den DP vom ganz linken Digit aufblinken wenn empfangen wird, also auch den DP vom Digit rechts daneben wenn die Daten verarbeitet werden. Habe auch direkt nochmal die Pins vermessen, komplett tot! Bis ich ihn resette, dann geht wieder alles. So langsam hab ich Lust es auf den Controller zu schieben, Datenpakete kommen im Takt 1-4 Sekunden, das heißt die Main ist zwischen 82800 und 20700 mal durchgelaufen ohne Probleme zu machen. Die ISR ist in den 23 Stunden etwa 20 Millionen mal durchgelaufen. Spannungseinbrüche können mMn auch kein Problem sein, da zum einen die Versorgungsspannung per Kondensator stabilisiert ist und ich die Brown out detection anhabe und diese auf 4.8 Volt steht. Angenommen es wäre ein Stack-Problem, dann müsste ich ja irgendwo Datenmüll erzeugen, der den Stack mit der Zeit wachsen lässt. Nicht sicher ob das überhaupt geht. Florian
Schreibe mal auf die letzten paar Bytes des Stackbereiches bekannte Werte. Wenn die Kiste wieder abschmiert, lässt Du dir die Werte nach Tastendruck zuschicken und vergleichst die mit den reingeschriebenen Werten. Wenn da was anderes drin steht, dann hast Du (d)ein Problem. unn tschuess Bernhard
Hab Bernhards Variante mal ausprobiert (schön das man bei nem Steckbrett einfach alles umsortieren kann). Ergebniss: Stack läuft nicht über. Habe mir jetzt einen Watchdog in die ISR eingebaut, da die ja Auszufallen scheint. Es wird ja nur das erste Digit angezeigt. In der ISR wird der Watchdog jetzt beim Anzeigen der 3. Digit resettet. In der Main ist der Watchdog leider nicht zu realisieren, da die bis zu 4 Sekunden für einen Durchlauf braucht. Des weiteren hab ich noch eingebaut, dass nach 30k Programmdurchläufen resettet wird, durch den Watchdog, einfach Interrupts aus und _delay_ms(2000) bei ner anschlagzeit von 500ms. Hätte noch eine Frage zum Hund und zwar bleibt das ja an nachdem durch ihn resettet wurde. Jetzt steht im Tutorial, dass ich den nach Möglichkeit früh kille weil er ansonsten zubeißt bevor er zurückgesetzt wird und der uC dadurch auf ewig im Watchdogreset festhängt. Laut Tutorial soll der Reset/abschalten des Hundes vor der Variableninitialisierung passieren. Ich hab aber im Kopf, dass die initialisierung das erste ist was im C Code passieren muss, wie soll ich den WD also vorher abschalten? Florian
Gast
#2772068
> Ich hab aber im Kopf, dass die [Variablen]initialisierung das erste ist > was im C Code passieren muss Nein, klücklicherweise ist dem nicht so. > wie soll ich den WD also vorher abschalten? in einer der init-Sections [0]. HTH [0] http://www.nongnu.org/avr-libc/user-manual/mem_sections.html
Gast
#2772088
Ich hatte ein ähnliches Problem, Programm lief mehrere Stunden stabil, dann Absturz bzw. Einfrieren, selbst der Watchdog lief nicht weiter. Ich hatte versehendlich den ADC zu schnell laufen. Kannst du EMV ausschließen? Ingo
Das könnte natürlich ein Problem sein, das Ding hängt immerhin mitten im Stromkasten drinne, hab ich bisher gar nicht dran gedacht. Das Kabel ist allerdings lang genug, dass ich den Käfer da mal raus holen kann. Lief bisher die letzten 3 Tage ohne Probleme. Danke für den Hinweis Florian
Gast
#2772109
Was ich schon oft beobachten konnte ist, wenn z.B. ein Aussenleiter Kontakt mit einer Leiterplatte (Der Platine selber) Kontakt bekommt und diese kein definiertes Potential führt, es zu abstürzen kommen kann. Abhilfe schafft es z.B. einen 1nF oder weniger von Masse nach Erde. Wirkt Wunder :). Auch große Metalkörper ohne definiertes Signal können Bei Berührung zum Absturz führen, wenn ein Ladeungaustausch stattfindet. Ingo
Undefinierte Kabel oder sonstige Sachen die da dran kommen kann ich Glücklicherweise ausschließen, es sei denn die Meinzelmännchen kommen nachts um mich zu ärgern :) Werd ihn mal aus dem Zählerschrank rausnehmen und gucken wie er sich dann macht. Könnte es ja schon gewesen sein. Florian
Florian T. schrieb: > Da bin ich wieder, hatte vorhin nach etwa 23 Std Laufzeit wieder einen > Ausfall. > Angezeigt wurde wie immer nur noch das rechte Display. Was mir > aufgefallen ist, dass ein nicht vorhandener Segmentcode angezeigt wird. > Quasi eine 6 ohne Segment a. > Datenempfang findet immer noch statt, ich sehe sowohl den DP vom ganz > linken Digit aufblinken wenn empfangen wird, also auch den DP vom Digit > rechts daneben wenn die Daten verarbeitet werden. > Habe auch direkt nochmal die Pins vermessen, komplett tot! Bis ich ihn > resette, dann geht wieder alles. > > So langsam hab ich Lust es auf den Controller zu schieben, Datenpakete > kommen im Takt 1-4 Sekunden, das heißt die Main ist zwischen 82800 und > 20700 mal durchgelaufen ohne Probleme zu machen. Die ISR ist in den 23 > Stunden etwa 20 Millionen mal durchgelaufen. > Spannungseinbrüche können mMn auch kein Problem sein, da zum einen die > Versorgungsspannung per Kondensator stabilisiert ist und ich die Brown > out detection anhabe und diese auf 4.8 Volt steht. > Angenommen es wäre ein Stack-Problem, dann müsste ich ja irgendwo > Datenmüll erzeugen, der den Stack mit der Zeit wachsen lässt. Nicht > sicher ob das überhaupt geht. > > Florian Ich versuchs mal so auszudrücken. Die ISR läuft ja noch ( sonst wären die Dots nicht mit aktualisiert ). Ich tippe da immernoch auf nicht legale Werte für die Segmentdaten. Warum auch immer.
Was hälst du davon diesen Teil PORTD=show[display[pos]]; zu reduzieren auf reines PORTD=display[pos]; und in "display" nur noch die fertigen Segmentdaten hälst ? Dein Fehler muß irgendwie in der Main liegen. Bereichsüberlauf o.ä. (vielleicht sowas hier http://www.bbc.co.uk/news/uk-12751404)
Dennis Heynlein schrieb: > Ich versuchs mal so auszudrücken. > Die ISR läuft ja noch ( sonst wären die Dots nicht mit aktualisiert ). Das stimmt so nicht ganz, die Dots die ich sehe werden von der Main gehandelt. Mit den ungültigen Segmentcodes hab ich schonmal mit einer if Bedingung geguckt gehabt. Sprich if dispay>10 dann gib mir nen Errorcode aus. Hat aber nichts gebracht gehabt, sprich ist auch ausgestiegen ohne entsprechenden Errorcode anzuzeigen.
/*Timeroverflowinterrupt für das Multiplexen der 4 7-Segment Anzeigen*/
ISR(TIMER0_OVF_vect){
icount++;
PORTC=0;
PORTD=show[display[pos]];
PORTC|=(1<<pos);
************************************************************************
if(pos==0&&einspeisen==1) /*Punkt ob eingespeist wird oder nicht*/
PORTD&=~(1<<7);
if(pos==1&&powered==1) /*Punkt ob WP gepowered oder nicht*/
PORTD&=~(1<<7);
************************************************************************
pos++;
if(pos>3) /*Display hat nur 4 Elemente*/
pos=0;
}
ohne die Zeilen in der ISR wären deine DOTs nicht an.
Die ISR läuft also schon.
Kannst du vielleicht den SRAM beim nächsten Absturz mal rausspielen (über U(S)ART und Main+Taste z.b.). Eine Zuordnung welche SRAM-Adresse welche Variable ist sollte nicht so schwierig sein.
Gast
#2773204
Die Punkte die aufleuchten sind allerdings diese hier aus der Main
/*Einlesepunkt einschalten*/
PORTD=0b01111111;
PORTC=0b00001000;
/*Protokoll einlesen*/
for(i=0;i<loggr;i++){
log[i]=readchar();
if(log[i]=='!')
break;
}
/*Verarbeitungspunkt einschalten*/
PORTC=0b00000100;
der eine Punkt der ganz rechts an ist kann aus nem Fehlerhaften
Segmentcode entstehen.
Fürn UART müsst ich leider die Segmentanzeige zerrupfen. Aber ich schau
mal was sich da machen lässt.
Florian
Muß ja nicht UART sein, solange du weißt wie es codiert ist, kannst du es an jeden beliebigen Port rausspielen. SoftUart liese sich einfach realisieren, zumal es nur ums ausgeben geht mit womöglich fester Bitrate. (Ein Pegelwandler wäre vielleicht aber dann notwendig) Und neben SRAM-Zustand wäre auch der Zustand - des I-Bits im Statusregister nach dem "Absturz". - des Timer-Interrupt-Freigabe TIMSK - des Timer-Control-Registers TCCR0 interessant. Poste mal deine neuesten Sources wenns geht. Welche Ports sind noch frei ?
Frei ist noch PORTB bis auf B0, aktueller Quelltext ist im Anhang. Habe inzwischen einen Watchdog eingebaut der nach beim hängenbleiben einspringt. Außerdem ist noch ne Eepromnutzung hinzugekommen, er soll immer wenn er zwischen powered/unpowered wechselt den Status ins Eeprom schreiben, sodass er wenn der Watchdog zubeißt immer wieder im selben Zustand neu startet. Diese Funktion funktioniert allerdings noch nicht, keine Ahnung warum. Florian Edit: Der Code frisst inzwischen 90% des Flash, ist zu überlegen da auch auf nen größeren Käfer umzusteigen? atmega16 bzw atmega32?
Vielleicht kannste auf Fliesskomma verzichten und eher zu Festkomma greifen ? Thema Watchdog. Mich würde diese Angstlösung nicht ruhen lassen und ich würde unbedingt den Fehler finden wollen ;)
Auf Fließkomma verzichten geht, dann brauch ich aber trotzdem 32 Bit Variablen, Speichergewinn gibts es dadurch also eher nicht. "Angstlösung" ist nicht wirklich die richtige Bezeichnung eher: "Damit-ich-weitermachen-kann" Lösung xD Hast du eine Idee warum der Eeprompart nicht funktioniert? Prinzipiell soll er den ersten Eintrag suchen der 255 ist und dann den Wert davor als powered nehmen, wenn der 0. Eintrag schon 255 ist nimmt er einfach 0 an. Zum schreiben sucht er den ersten Eintrag der 255 ist und schreibt da dann den aktuellen status rein. Zumindest in meinem Kopf^^ Wenn im 511. also letzten Eintrag kein 255 ist das Array voll und er schreibt es einmal komplett neu mit 255 bevor er ins erste wieder den Status schreibt. Eine mögliche Fehlerquelle die ich heut morgen noch gefunden hab ist der Phototransistor, der ist über die Zeit immer weiter weg vom Zähler gewandert und je weiter weg der war, desto öfter stand da nur schwachsinn. Florian
Die Fliesskomma-LIB frisst ziemlich viel Platz. Eine mögliche Fehlerquelle die ich heut morgen noch gefunden hab ist der Phototransistor, der ist über die Zeit immer weiter weg vom Zähler gewandert und je weiter weg der war, desto öfter stand da nur schwachsinn. Das Passt dann gut zur Überlauftheorie in der Main. Du prüfst auch nicht direkt, ob deine Zahlen wirklich Dezimalzeichen sind und nicht fehlerhaft gelesenes irgendwas.
Dann mach ich mich mal dran in die Protokollauswertung noch ne Überprüfung einzubauen die schaut das da wirklich 0-9 steht und nichts anderes. Das ganze auf unsigned long umstellen müsste auch gehen. Ich meld mich dann nichmal wenn ichs soweit am laufen hab. Florian
So ein EEPROM-Schreibzyklus braucht ne weile. "EEPROM Write (from CPU) 8448 CLKrc 8.5ms" Hoffentlich wird nicht während deinem Schreiben der Watchdog ausgelöst.
Ich behaupte mal, dass das nicht passieren kann weil
1 | |
2 | |
3 | |
4 | |
5 | |
Edit: Denke ich hab in der write funktion nen Fehler gefunden wenn Eintrag 0 255 ist, dann geht er gar nicht erst in die Schleife erhöht also auch gar nicht i, also versucht er dann in eintrag -1 bzw da es ein unsigned int is in eintrag 65000 oder so zu schreiben.
Hallo, arbeite grade am loswerden der ganzen floats, habe allerdings das Problem, dass ich keine Idee habe wie ich den float bei der Zeit loswerden kann, denn angenommen bei der Multiplikation kommt was kleiner 1 raus, dann hab ich da auf einmal 0 stehen und durch 0 teilen ist ungesung, auch kann ich denn nicht mehr zwischen 1 und 1.9 unterscheiden. Ideen wie ich das Lösen kann? Florian
Gast
#2774533
Festkommazahlen in C zusammenbasteln. Z.B nimmst du von einer 16 Bit int 8 Bit für Vorkomma und 8 Bit für Nachkomma. Musst dann bei jeder Zuweisung und jeder Rechenoperation aufpassen. Jedes mal nachdenken, ob du um 8 Bit verschieben musst.
Ich denke ich habs jetzt, allerdings zeigt das Display einen gefühlten Faktor 5 zu wenig an, ich möchte einfach nicht glauben, dass wenn die Anlage 6kW bringt nur 1kW eingespeist werden obwohl nur mein PC als großer Verbraucher läuft ;) Änderungen sind, alle floats sind unsigned long gewichen Das hier
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
ist dem hier gewichen
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
die Verarbeitung sieht jetzt anstelle so
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
so aus
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
hierbei sind sowohl der time Multiplikator also auch die 3600 um den Faktor 10 zu groß, so erschummel ich mir eine größere genauigkeit bei der Zeit. Die todisplay Funktion wurde auf die unsigned longs angepasst. unsigned longs entsprechen 32 bit Variablen, sollte also Werte bis 4 Milliarden halten können. Ich seh grad nicht wo dieser Faktor 5 Verloren gehen soll. Florian
i++; kaufen+=(log[i]-48)*1000000000; Teste mal log[i] auf >=48 && <=57 und eventuell haste noch ein paar Testausgaben :) um mal einen Simulator damit zu füttern.
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.