Das Elektor-Forum schließt seine Pforten (siehe auch http://www.elektormagazine.de/forum). Ab Freitag, den 01. März, ist es nicht mehr möglich, sich im Forum einzuloggen. Alle Inhalte des Forums bleiben jedoch bis Ende März noch sichtbar. Am 01. April wird das Forum schließlich komplett geschlossen.

main() funktioniert nicht richtig (mit Timer C)

Postby mr. teflon » Mon Feb 28, 2011 12:00 am

Hallo,

ich habe 3 Versionen von ein und dem gleichen Programm. Wovon nur eines funktioniert, aber auch nicht exakt so wie gewünscht.

Version a):
funktioniert zwar, aber die Abfrage der MX6675 in der Timer C Interruptschleife erfolgen nur aller eingestellten 5sec., worauf hin die Alarm LED in der Hauptschleife verzögert reagiert.

Version b):
hier erfolgt das einlesen aller 3 Sensoren in der Hauptschleife und die LCD Ausgabe in der Interruptfunktion. Das sollte so sein, ist aber nicht so. Die MAX6675 werden nur einmalig nach Reset eingelesen und dann nie wieder. Warum? Kann ich mir nicht erklären. Der AD-Wandler wird immer eingelesen.

Version c):
hier werden die 3 Sensoren immer am Anfang der Timer C Interruptschleife abgefragt. Funktioniert genauso wenig wie bei Version b). Die MAX6675 werden nicht abgefragt. Warum? Kann ich mir wieder nicht erklären. Der AD-Wandler wird auch hier immer eingelesen.

Die Idee für c) war, dass vielleicht der Interrupt dummerweise immer das einlesen der MX6675 stört. Der Interrupt wird aller 104ms aufgerufen, wegen Teiler f32. Jetzt steht das einlesen am Schelifenanfang und funktioniert wieder nicht.

Kann mir jemand sagen was ich übersehe?
Oder hat der Compiler eine Macke?
Ideen?

Edit:
das der Interrupt "Timer C" sehr viel Rechenzeit beansprucht merke ich auch daran, dass ich die Alarm LED Blinkschleife im Hauptprogramm nur bis 10 zählen lassen darf statt bis 50.000, damit diese wieder mit ca. 2Hz vor sich hin blinkt. Im Fall von Version b oder c nach einem Reset und vorher Finger an dem Thermofühler.

Es hilft mir auch nicht, wenn ich das Programm aus der Timer-C Interrupt Schleife herausnehme und wieder in der Hauptschleife abarbeiten lasse und nur noch die 3 Zaehler im Interrupt hochzählen lasse. Die MAX6675 werden trotzdem nicht ausgelesen. Nur einmalig nach Reset.

Tschau
Mr. Teflon
Attachments
a-BikeTemp-v4-funktioniert-naja.c
(39.83 KiB) Downloaded 37 times
b-BikeTemp-v4-funktioniert-nicht.c
(39.83 KiB) Downloaded 42 times
c-BikeTemp-v4-funktioniert-nicht.c
(39.83 KiB) Downloaded 35 times
mr. teflon
 
Posts: 146
Joined: Fri Jan 03, 2014 1:48 pm

Postby herch » Mon Feb 28, 2011 12:00 am

Hallo Mr. Teflon,

ich habe Dein Projekt geflasht und es hat eine Größe von 10.5 k. Das "gefährliche" ist, dass Du mit "float" Datentypen arbeitest. Ich hatte ein Projekt mit ähnlicher Größe, wenn ich dort die Berechnung mit float verwendete, benötigte dieses ca. 8 k (nur für float) an Speicher im R8C13. Bei meinem Programm wurden Variablen-Werte, in Prozeduren die damit nichts zu tun hatten, einfach überschrieben.
Wenn Du mit dem Debugger arbeitest, kannst Du evtl. dieses Phänomen beobachten.

Du solltest generell auf float verzichten. Ich lasse z.B. in den Funktionen die Werte multipliziert mit dem Faktor 10 zurückgeben. In der Ausgabe-Prozedur werden die Werte dann richtig mit Komma dargestellt.

Warum verwendest Du Timer C und nicht Timer x?
   fCPU           prex     tx          fout     Tout  20 MHz * 1/32 * 1/250 * 1/250 =       10 Hz   0.1 s
herch
 
Posts: 52
Joined: Fri Jan 03, 2014 1:48 pm

Postby mr. teflon » Tue Mar 01, 2011 12:00 am

Hallo,

ich finde es sehr nett das Du Dich meinem Problem annimmst. Alleine komme ich hier nicht weiter.

f_BikeTemp_v4.rar
Ich habe den Code weiter aufgeräumt. Es blieben nur noch 2 float Variabeln übrig. Der Code schrumpfte auf ca. 8kB. Am Problem des nicht einlesens beider MAX6675 änderte sich nichts. Dann habe ich die float Variablen auf unsigned int geändert. Upps. Der Code schrumpfte auf ca. 4kB. Jetzt wird zwar erstmal auf dem LCD Müll angezeigt, erstmal egal, reagieren müsste es trotzdem. Macht es aber nicht. Problem des nicht einlesens bleibt bestehen. Demnach kann es nicht an den Speicher fressenden float Variabeln liegen.

Das nicht verwenden von float spart doch eine Menge Speicher.

Jedoch müßte doch der Compiler Adresskonflikte abfangen, falls sonst Variablen überschrieben würden. Sonst wäre der Compiler fehlerhaft.

g_BikeTemp.rar
Das Problem fing schon vor der Nutzung vom Timer C an. Als ich noch eine zusätzliche If Schleife eingebauen wollte. Nehm ich die wieder raus, funtionierte wieder alles. Alles ohne irgendeinen Timer Interrupt. "d_e_BikeTemp.rar Ziel war es Rechenzeit freizbekommen und die feste Wartezeit "wait_ms(500)" zu umgehen und trotzdem die LCD Anzeige gegen flimmern langsamer zu machen. Das Bsp. "g_BikeTemp.rar" mit den "wait_ms(500) funktioniert noch. Das Bsp. "f_BikeTemp" schon nicht mehr, weil ich dort die 500ms gegen eine zusätzliche If ersetzt habe. Ich kann den Code gedanklich so oft durchgehen wie ich möchte - muß funktionieren.

sepp2gl kam auf die Idee ich sollte den Timer C verwenden. Das ist ein reiner Timer, wäre besser wie die anderen dafür geeignet. für die LCD Anzeigezeiten brauche ich keine exakten 100ms als Basis. Die 104ms sind für die Zwecke ausreichend. Den Timer X hatte ich später auch noch probiert. Das Problem des nicht einlesens blieb aber auch damit bestehen.


wegen dem Debugger, noch eine neue Baustelle. Danke für die sehr hilfreiche Anleitung.
ganz unten: http://www.elektor.de/forum/foren-ubersicht/foren-zu-elektor-projekten/das-r8c-projekt/fehlermeldung-des-kd30.170886.lynkx
Das Ding will nicht mehr richtig funktionieren. Mit dem nur ca. 4kB großen Code kann ich erstmal starten und es läuft. Sobald ich einen Button wie Stop drücke reagiert er sehr träge und stürtzt danach doch noch ab. Der Debugger hat aber schon mit dem Projekt funktioniert.
Nachdem der Debugger abgestürzt ist, habe ich massive Problem den µC überhaupt wieder normal flashen zu können. Die Schnittstelle ist immer noch blockiert. Nach langen hin und her geht es dann wieder.
Attachments
d-e-BikeTemp.rar
(18.99 KiB) Downloaded 38 times
f-BikeTemp-v4.rar
(119.52 KiB) Downloaded 35 times
g-BikeTemp.rar
(218.13 KiB) Downloaded 39 times
mr. teflon
 
Posts: 146
Joined: Fri Jan 03, 2014 1:48 pm

Postby mr. teflon » Tue Mar 01, 2011 12:00 am

Hallo,

ich nochmal. Habe jetzt den gesamten Code restlos bis auf das notwendigste abgespeckt. Jetzt sollte jeder der helfen möchte einen Überblick bekommen.
Ist nur noch 2kB groß
DATA 0000276(00114H) Byte(s)
ROMDATA 0000280(00118H) Byte(s)
CODE 0001303(00517H) Byte(s)

Habe auch ein neues Projekt erstellt und nur den reinen Code reinkopiert. Der Compiler zeigt beim übersetzen immer alles fehler frei an. Laut meinem Verständnis müßten jetzt die MAX6675 ständig ausgelesen und ohne jede Verzögerung ans LCD ausgegeben werden, sodass das LCD flimmert. Und sobald man an einen Fühler fasst sollte die LED blinken und zwar so schnell, dass man kein blinken wahrnimmt. Machts aber alles nachwievor nicht. Nur nach einem Rest wird einmal eingelesen und je nachdem blinkt dann die LED unendlich oder nicht. Und das auch sichtbar langsam statt optisch sehr schnell.

Edit:
Momentan funktioniert der Debugger. Auch im Freilauf ohne Break. Ich sehe darin das sich die Variablen TempP32 und TempP33 nicht ändern, obwohl sie es müßten. Wie gehe ich jetzt am Besten mittels Debugger vor um den Fehler zu finden?

Bin echt ratlos. Würde mich über jede Unterstützung freuen.

Tschau
Mr. Teflon
Attachments
de_BikeTemp-v6-MAX6675-only.1.rar
(84.11 KiB) Downloaded 38 times
mr. teflon
 
Posts: 146
Joined: Fri Jan 03, 2014 1:48 pm

Postby herch » Tue Mar 01, 2011 12:00 am

Hallo Mr. Teflon,

ich kann zwar keine *.rar Dateien und somit Deine aktuelle Version öffnen, aber ich habe eine alte Version angeschaut.
Es wird dort 50000 mal eine Funktion aufgerufen, dann wird der Zustand einer LED geändert. Besser geht es so:

main() { ...  while (1) {    if ((TempP32 > 30) || (TempP33 > 30)) {       p1_0 ^= 1;      wait_ms(125);    }    else      p1_0 = 0;  } // while...

Du kannst auch " p1_0 ^= 1; wait_ms(125);" in die Alarm Prozedur schreiben. Mit dem Wert in der Verzögerung stellt man die Blinkfrequenz ein.

sollte die LED blinken und zwar so schnell, dass man kein blinken wahrnimmt.

Soll die LED blinken oder leuchten?

Wenn Du noch mit Timer C arbeitest, in der Interrupt Prozedur:
TempP32 = (read_MAX6675_P32()+2)/4; TempP33 = (read_MAX6675_P33()+2)/4; MAX6675_P32_on_LCD (TempP32);MAX6675_P33_on_LCD (TempP33);zaehler3 = 0;

setzt Du zuerst einen Breakpoint in "zaehler3 = 0" und läßt den Debugger laufen. Er wird dann immer dort anhalten. Dann kontrollierst Du die Werte von TempP33. Sind sie nicht plausibel löscht Du den Breakpoint und setzt einen in "TempP32 = (read_MAX6675_P32()+2)/4;" und gehst mit "Step" in die Funktion hinein und schaust ob dort alles richtig funktioniert.

Vielleicht hast Du auch nur kalte Finger senke die Temperatur fuer Alarm auf etwas über Raumtemperaur

schönen Abend noch
herch
 
Posts: 52
Joined: Fri Jan 03, 2014 1:48 pm

Postby mr. teflon » Wed Mar 02, 2011 12:00 am

Hallo,

okay und Danke für die Debuggerhilfe. Den muß man auch erstmal nutzen lernen. Wegen der Alarm LED gibts viele Möglichkeiten, den Blinkintervall wollte ich später auch noch mittels Timer C einstellen. Habe ich dann erstmal abgebrochen, weil das eigentliche Programm ja nicht mehr funktioniert.

Meine Vermutung liegt in einem Fehler der Variablenübergabe zwischen den Funktionsaufrufen.

Tschau
Mr. Teflon

Edit:
Datei gelöscht, weil überholt
mr. teflon
 
Posts: 146
Joined: Fri Jan 03, 2014 1:48 pm

Postby mr. teflon » Wed Mar 02, 2011 12:00 am

Hallo,

Erfolgsmeldung

Hirn siegt über Debugger, obwohl der mich auf paar Ideen brachte, aber leider nicht auf die entscheidende ... obwohl man auch sagen könnte, dass den Fehler der Debugger eigentlich nicht sehen kann.

Nachdem ich mehrfach stutzig wurde warum das Programm mit Debugger und einem gesetzten Breakpoint funktioniert und ohne Breakpoint nicht, habe ich dann noch etliche Codevarianten probiert. Am Ende kristalisierte sich die benötigte wait_ms(...) am Ende der Anzeige heraus. Die künstiche Wartezeit hilft aber nicht der LCD Anzeige sondern dem MAX6675. Der benötigt mindestens 50ms Pause nach dem auslesen vorm erneuten auslesen. Dieser Effekt erklärt im nachhinein so manchen seltsamen Effekt bei verschiedenen Code Variationen.

Und weil ich bei Nutzung vom Timer ständig ausgelesen aber nur aller paar ms zur Anzeige gebracht habe, kam der MAX6675 nicht mehr hinterher. Nun werde ich das auslesen auch noch mittels Timer erledigen, sonst habe ich wieder 50ms künstliche Wartezeit eingebaut die ich ja nicht möchte.
Der µC will ja was zu tun haben.

Nebenbei habe ich viele globale Variablen entfernt und durch lokale ersetzen können.

Ein paar Fragen bleiben übrig.

Warum wurde im Debugger die Variable "zaehler1" auf größer 5 durch den Timer hochgezählt, wenn sie doch beim Schleifendurchlauf IF Bedingung >=5 am Ende genullt wird. Kann nur Werte zwischen 0 ... 5 annehmen.

Und vielleicht kannst Du mir erklären was das Semikolon (hier sogar zwei) am Ende der Funktion für eine Bedeutung hat?


// 8 Bits eines Bytes hintereinander an das LCD senden (SPI)void send_byte_to_lcd(char byte){int i;for (i = 0; i < 8; i++)   // Schleife für alle 8 Bits{ CLK = 0;// Taktleitung auf LOW setzen SI = ((byte&128) != 0);   // wenn ja SI = 1, sonst SI = 0 byte <<= 1;// nach links schieben CLK = 1; // Taktleitung auf HIGH wait_us(30);};};


Eine Erklärung dazu finde ich in meinem Anfänger C Programmierbuch nicht.

Und wird die Variable byte im Paramenter im Funktionsaufruf schon als lokale Variable bezeichnet?

Danke.

Tschau
Mr. Teflon
Attachments
d-BikeTemp-funktioniert-abgespeckt-mit-Timer-C-COM1.c
(21.48 KiB) Downloaded 42 times
BikeTemp-v6-MAX6675-only.zip
(115.5 KiB) Downloaded 36 times
mr. teflon
 
Posts: 146
Joined: Fri Jan 03, 2014 1:48 pm


Return to Das R8C-Projekt

Who is online

Users browsing this forum: No registered users and 1 guest