Forum: Mikrocontroller und Digitale Elektronik Reflow Ofen Steuerung


von Fabio W. (modellbauer)


Angehängte Dateien:

Lesenswert?

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

von Markus F. (5volt) Benutzerseite


Lesenswert?

> ....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
}

von Fabio W. (modellbauer)


Lesenswert?

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

von Max M. (xxl)


Lesenswert?

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.

von Laszlo H. (mobius)


Lesenswert?

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

von Fabio W. (modellbauer)


Angehängte Dateien:

Lesenswert?

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

von Peter D. (pdiener) Benutzerseite


Lesenswert?

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

von Fabio W. (modellbauer)


Angehängte Dateien:

Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Fabio W. (modellbauer)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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)

von Fabio W. (modellbauer)


Lesenswert?

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

von Fabio W. (modellbauer)


Angehängte Dateien:

Lesenswert?

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.

von Fabio W. (modellbauer)


Angehängte Dateien:

Lesenswert?

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.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.