Hallo,
nachdem ich endlich meine Platine für die Steuerung meines Reflow Ofens
fertig gemacht habe, musste auch ein Programm her....
Ich habe daraufhin das angehängte Programm geschrieben,
aber als es dann im µC war......
....NICHTS
Kann mir einer sagen, was ich mal wieder übersehen habe???
Und was kann ich sonst noch besser machen??
Mit ausprobieren ist ja leider nicht....
Mit freundlichen Grüßen
Modellbauer
> ....NICHTS
Was heißt Nichts?
Wenn wirklich gar nix passiert, dann könnte die Taktquelle ein Problem
haben. Also Fusebits falsch gesetzt und/oder Quarz o.ä. nicht korrekt
angeschlossen.
Dazu solltest du natürlich die Betriebsspannung usw. prüfen.
Wenn nur der UART nicht geht, dann ist er höchstwahrscheinlich falsch
konfiguriert (z.B. Baudrate falsch oder TxD nicht aktiviert).
Zudem:
Versuche, wenn irgendwie möglich, Gleitkomma-Rechnungen zu vermeiden,
und insbesondere Funktionen wie die "dtostrf".
Das kostet Unmengen an Flash und Rechenzeit.
In ca. 90% aller Fälle kommt man mit einer normalen itoa oder ltoa auch
zum Ziel, wenn man nachher in den String bei der Ausgabe an gewünschter
Stelle ein Komma einfügt.
Mal als Anregung: So habe ich das mal gelöst, um Integers mit Vorzeichen
und 0...4 Nachkommastellen auszugeben (ich garantiere natürlich nicht
dafür, dass es funktioniert...): 1 | void lcd_show_format_int(int inval, uint8_t DigAfterDecimal) {
| 2 | uint8_t stlen;
| 3 | unsigned int compval;
| 4 | if(inval < 0) {
| 5 | inval = -inval;
| 6 | lcd_data('-');
| 7 | }
| 8 | itoa(inval,outval,10);
| 9 | stlen = strlen(outval);
| 10 | if(DigAfterDecimal > 0) {
| 11 | compval = 1;
| 12 | for(uint8_t i=0;i<DigAfterDecimal;i++) {
| 13 | compval *= 10;
| 14 | }
| 15 | if(inval < compval) lcd_data('0');
| 16 | if(compval > 10) {
| 17 | if(inval < (compval / 10)) {
| 18 | lcd_data(',');
| 19 | lcd_data('0');
| 20 | }
| 21 | }
| 22 | }
| 23 | for(uint8_t i=0;i<stlen;i++) {
| 24 | if(i == (stlen - DigAfterDecimal)) lcd_data(',');
| 25 | lcd_data(outval[i]);
| 26 | }
| 27 | }
|
Also ich empfange weder was an rs232 noch regt sich irgendeine der LEDs.
Wenn ich allerdings ein anderes Programm daraufschiebe, funktioniert
alles. Also einzeln funktionieren sowohl RS232 als auch die LEDs.
Mit dem geposteten Programm funktioniert aber garnichts. Also muss es
irgendwie daran und nicht an den Fuses etc liegen.
Das mit den floats war auch eigentlich nur so übergangsweise...
Das wird noch geändert, weil ich da sowiso ein paar Warnings hatte...
Aber trozdem sollte das der allgemeinen Funktion keinen Abbruch tun.
Vielen Dank für die Mühe sich da rein zu denken
Modellbauer
Mal ehrlich, das Programm hast DU geschrieben?
Ganz schön cryptisch. Leider zu cryptisch für mich.
Meine Domäne ist die Hardware. Ich hätte mehr Kommentar
geschrieben, damit man den Programmfluss leichter nachvollziehen
kann.
Mit deinen 1k-Widerständen von den LEDs wirste kaum ein
Erfolgserlebnis haben. 150 OHM sind da üblich.
Der 220 Ohm für den Optotriac müsste eigentlich gehen
kann es aber nicht garantieren.
Wegen dem nicht-laufen kann ich nichts sagen. Hast du versucht den
Fehler einzugrenzen? Also Funktionen aus der Main auskommentieren bis es
funktioniert? Oder nen Debugger / Simulator drübergejagt? Bei so einem
einfachen Programm sollte AvrStudio reichen um alle Programmteile
durchtesten zu können (gibt ja nicht so viele Eingänge ;) ).
Hier mal einige Überlegungen. Ist dein ADC ist blockierend? Hast du
get_adc() getestet, dass er ohne dem umliegenden Code Funktioniert? Dies
wären die Punkte, wo ich ansetzten würde (leider kann man ohne weiterem
Code nicht viel sagen und meine Glaskugel macht schon Feierabend ;) )
Aber mir ist etwas grundlegend anderes aufgefallen. Wenn du error()
aufrufst, stellst du nicht sicher, dass dein SS-Relay nicht gerade
eingeschaltet ist.
Fall:
1. Durchlauf: ist < soll --> Relay ein
2. Durchlauf: ist < 90 --> error --> unendlichschleife mit relay an
Dito LED-cool, du setzt die solltemperatur auf 0, aber die for(;;)
schleife verhindert, dass deine Regel-Funktion wieder aufgerufen wird.
lg
Mobius
Max M. schrieb:
> Mit deinen 1k-Widerständen von den LEDs wirste kaum ein
> Erfolgserlebnis haben. 150 OHM sind da üblich.
Jaa, ich weiß im Schaltplan sind die falsch drinne...
Eigentlich habe ich da 330 Ohm Widerstände verwendet. Und ich habe ja
auch schon geschrieben, dass die im eigenen Programm funktionieren...
Laszlo H. schrieb:
> Wegen dem nicht-laufen kann ich nichts sagen. Hast du versucht den
> Fehler einzugrenzen? Also Funktionen aus der Main auskommentieren bis es
> funktioniert? Oder nen Debugger / Simulator drübergejagt? Bei so einem
> einfachen Programm sollte AvrStudio reichen um alle Programmteile
> durchtesten zu können (gibt ja nicht so viele Eingänge ;) ).
Also im Simulator hat es wie immer nur bis zur while-Schleife
funktioniert...
Das ist bei mir aber schon immer so gewesen und die Programme haben
trozdem funktioniert.
Laszlo H. schrieb:
> Hier mal einige Überlegungen. Ist dein ADC ist blockierend? Hast du
> get_adc() getestet, dass er ohne dem umliegenden Code Funktioniert? Dies
> wären die Punkte, wo ich ansetzten würde (leider kann man ohne weiterem
> Code nicht viel sagen und meine Glaskugel macht schon Feierabend ;) )
Nee habe ich noch nicht ausprobieren können. Habe in den letzten Paar
Tagen auch leider keine Zeit gehabt... Kommende Woche werde ich mich da
aber nochmal dran setzen. Dann kann ich auch die einzelnen Teile testen
und so weiter...
Ich habe mal die adc.c und uart.c in den Anhang gepackt...
Laszlo H. schrieb:
> Aber mir ist etwas grundlegend anderes aufgefallen. Wenn du error()
> aufrufst, stellst du nicht sicher, dass dein SS-Relay nicht gerade
> eingeschaltet ist.
>
> Fall:
> 1. Durchlauf: ist < soll --> Relay ein
> 2. Durchlauf: ist < 90 --> error --> unendlichschleife mit relay an
>
> Dito LED-cool, du setzt die solltemperatur auf 0, aber die for(;;)
> schleife verhindert, dass deine Regel-Funktion wieder aufgerufen wird.
Das ist mir noch garnicht aufgefallen und wäre es glaube ich auch nicht.
Deshalb größten Dank an dieser Stelle für den Hinweis... Werde ich dann
beheben, wenn ich nächste Woche mehr Zeit habe.
Damit wäre es aber schonmal geklärt, dass ich nicht irgendeinen total
blöden Fehler bis hierhin gemacht habe, der dafür verantwortlich ist.
Vielen Dank
Modellbauer
Ich hab mir das Programm gerade durchgelesen und hätte noch einen
sicherheitstechnischen Tip:
Wenn
error();
aufgerufen wird, bzw. in dieser Funktion sollte die Heizung abgeschaltet
werden, weil sie eventuell im Ein-Zustand steht, wenn der Fehler
auftritt.
Das könnte zu warm werden.
Grüße,
Peter
Soo,
peinlich peinlich, was mir da alles so im alten Programm für Fehler
unterlaufen sind:
-> Damit die LEDs leuchten sollen, ist es sinnvoll die entsprechenden
Ports als Ausgänge zu konfigurieren....
-> Die Schleife von der uart_putchar(), in der auch der Simulator vom
AVR Studio hängen geblieben ist, war tatsächlich falsch ( ()
vergessen)....
Wenn man dann also den Kopf mal einschaltet, ist alles auch gleich viel
einfacher...
Habe jetzt einfach mal den aktuellen Code angehangen. Der ist aber in
keiner Form vernünftig dokumentiert. Mache ich vielleicht nochmal, damit
man da etwas besser durchsteigt.
Getestet ist alles, aber ohne Ofen. Neben zahlreichen "trocken" Tests
nur kurz mit einer Glühbirne ausprobiert. Hat auch prima funktioniert.
Viele Grüße
Modellbauer
ISt das beim Posten passiert, oder hast du wirklich nach jeder Zeile
eine Leerzeile drinnen?
Wenn du dich dazu entschliessen könntest, anstelle von
1 | uart_putstring("ABKUEHLEN");
| 2 |
| 3 | uart_putchar(0x0D);
| 4 |
| 5 | uart_putchar(0x0A);
|
ganz einfach 1 | uart_putstring("ABKUEHLEN\r\n");
|
zu schreiben, würde schon mal 30% deines Codes wegfallen, was der
Übersicht extrem zugute kommen würde.
Die Funktion control() dampft sich so von einer Bildschirmseite auf
1 | void control(void) //einfache Temperaturreglung
| 2 | {
| 3 | uart_putstring("Solid State Relais: ");
| 4 |
| 5 | if(t_soll > t_ist)
| 6 | {
| 7 | SSR_Port |= (1<<SSR_Pin); //Solid State Relais ein
| 8 | uart_putstring("EIN\r\n");
| 9 | }
| 10 | else
| 11 | {
| 12 | SSR_Port &=~(1<<SSR_Pin); //Solid State Relais aus
| 13 | uart_putstring("AUS\r\n");
| 14 | }
| 15 | }
|
15 Zeilen ein.
BIst du dir da ganz sicher?
1 | volatile uint8_t t_soll = 0; //Variable für Soll-Temperatur
| 2 | volatile int16_t t_ist = 0; //Variable für Ist-Temperatur
|
unterschiedliche Datentypen für eigentlich immer das selbe - eine
Temperatur?
Wenn du die vereinheitlichst, könntest du dir eine Funktion schreiben,
die einen uint16_t ausgibt, in Analogie zu uart_printstring, wodurch
sich wieder einige Funktionen extrem verkürzen.
Vergleich deine update_soll mit dieser hier
1 | void update_soll(void) //Berechnung der Soll-Temperatur
| 2 | {
| 3 | if( time <= 52 )
| 4 | {
| 5 | t_soll = ((2.5 * time)+20) ;
| 6 | LED_Port &=~((1<<LED_Preheat) | (1<<LED_FluxActivation) | (1<<LED_Reflow));
| 7 | LED_Port |= (1<<LED_Preheat);
| 8 |
| 9 | uart_putstring("VORHEIZEN\r\n");
| 10 | }
| 11 |
| 12 | else if( time <= 120 )
| 13 | {
| 14 | t_soll = ((0.5 * time) + 120);
| 15 |
| 16 | LED_Port &=~((1<<LED_Preheat) | (1<<LED_FluxActivation) | (1<<LED_Reflow));
| 17 | LED_Port |= (1<<LED_FluxActivation);
| 18 |
| 19 | uart_putstring("FLUSSMITTELAKTIVIERUNG\r\n");
| 20 | }
| 21 |
| 22 | else if( time <= 180 )
| 23 | {
| 24 | t_soll = (((2 * time)/(3)) + 100);
| 25 |
| 26 | LED_Port &=~((1<<LED_Preheat) | (1<<LED_FluxActivation) | (1<<LED_Reflow));
| 27 | LED_Port |= (1<<LED_Reflow);
| 28 |
| 29 | uart_putstring("REFLOW\r\n");
| 30 | }
| 31 |
| 32 | uart_putuint16("Soll-Temperatur: ", t_soll);
| 33 | uart_putuint16("Ist-Temperatur: ", t_ist);
| 34 | uart_putuint16("Sekunden: ", time);
| 35 |
| 36 | if( time > 180 )
| 37 | {
| 38 | cool_down();
| 39 | }
| 40 | }
|
Nicht schlecht. 3 Bildschirmseiten auf 40 Zeilen eingedampft.
Die Kunst beim Programmieren besteht nicht darin, alles irgendwie zum
Laufen zu bekommen, sondern sein Programm so zu gestalten, dass man auch
nach einem halben Jahr noch schnell erfassen kann, was an einer Stelle
passiert. Funktionen die sinnlos über mehrere Bildschirmseiten laufen,
fördern das nicht unbedingt.
Hallo,
danke erstmal für die Hinweise.
Also zu den Carriage Return + Line Feed folgendes:
Ich habe das irgendwie auch mit /r und /n ausprobiert, hat bei mir aber
nicht geklappt. Hatte glaube ich beides in einer eigenen Zeile als
uart_putchar('/r') oder irgendwie so. Auf jeden Fall hat das nicht
funktioniert. Deshalb habe ich einfach auf die verwendeten Dinge
zurückgegriffen, weil ich wusste, dass es so auf jeden Fall geht.
Wenn man sich das so vor Augen führt, ist das schon extrem, was da alles
eingespart werden kann. Wie gesagt habe ich mir aber auch noch keine
Gedanken über "schön" gemacht. Ich war einfach nur froh, dass es lief...
=)
Da ich jetzt aber leider keine Zeit mehr habe, werde ich es dann morgen
nochmal etwas verschönern und vor allem verkürzen.
Danke schön
Modellbauer
Fabio W. schrieb:
> Hallo,
>
> danke erstmal für die Hinweise.
>
> Also zu den Carriage Return + Line Feed folgendes:
>
> Ich habe das irgendwie auch mit /r und /n ausprobiert,
Nicht /n
Sondern \n
Das ist ein Backslash (AltGr + ß), kein Slash
> Wie gesagt habe ich mir aber auch noch keine
> Gedanken über "schön" gemacht.
Das ist ein Fehler. Du kannst dir viel Arbeit sparen, wenn du von vorne
herein auf einen einigermassen vernünftigen Programmaufbau achtest.
Im abschliessenden 'pretty' Durchgang sind es dann nur mehr
Kleinigkeiten, die man optisch aufbereitet. Aber es entwickelt sich ja
viel besser, wenn man nicht sofort den Überblick verliert (Siehe deine
'dummen' Fehler)
Jaa, okay.... Das wäre dann wohl auch der Grund dafür, dass es bei mir
so nicht funktioniert hat. Wer lesen kann ist da wohl klar im Vorteil.
Zum "pretty" Durchgang kann ich nur sagen, dass mir das jetzt
hoffentlich eine Lehre gewesen ist und ich es Zukunft anders mache.
Vielen Dank
Modellbauer
Hallo,
habe heute alles nochmal verschönert.
Im Anhang ist dann die verbesserte Version.
Ich hoffe hier kann man sich besser zurecht finden.
Habe es gerade probiert, leider funktioniert es nur einmal.
Es scheint so, dass der an der 1000ms Pause hängen bleibt, denn wenn ich
die herausnehme, klappt es.
Morgen mal schaun woran das liegt.
Viele Grüße
Modellbauer
EDIT: Keine Ahnung warum die Kommentare so bescheuert sind. Beim AVR
Studio waren die alle schön gleich.
Hallo,
wollte jetzt nochmal meine endgültige Version hier posten, falls jemand
interessiert sein sollte.
Das ist jetzt so in Benutzung. Habe keine Lust das weiter anzupassen,
weil es reicht eigentlich von der Funktion her, auch wenn die Kurve
nicht so optimal verläuft.
Grüße
Modellbauer
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|