Hallo, ich verwende einen Arduino in Kombination mit einem MAX31855 (fertiges Board von AdaFruit), um die Temperatur eines Thermo-Elements Typ K auszulesen. Das Thermo-Element misst die Temperatur eines Ofens, im Bereich 20-1000°C. Es ist mit ca. 1m geschirmter Leitung per Klemme mit dem MAX31855 verbunden. Habe alles mal einen Tag laufen lassen im gesamten Temperaturbereich und es klappt ganz gut. Der Messwert entspricht der Wirklichkeit, ist schön stabil und schwankt nicht. Mein Problem ist Folgendes: Wenn der Ofen bspw. 200°C hat und ich schalte alles aus und danach wieder ein, wird immer eine Temperatur von 0° ausgelesen. Der MAX31855 gibt auch keine Fehlermeldung, sondern immer nur 0°. Als ob der IC nicht reagieren würde. Sinkt die Temperatur nun unter 30°, wird auch die korrekte Temperatur ausgelesen. Wenn jetzt geheizt wird, funktioniert alles wie gehabt. Beim Hochlauf des ICs muss das Thermo-Element anscheinend inetwa Raumtemperatur haben. Vorher reagiert er nicht. Liegt das vielleicht an der Kaltstellenkompensation des Chips? Kann man dieses Verhalten irgendwie ändern? Ich hoffe ihr könnt mir helfen :) Grüße
Fabian schrieb: > Liegt das vielleicht an > der Kaltstellenkompensation des Chips? Kann man dieses Verhalten > irgendwie ändern? Ich hoffe ihr könnt mir helfen :) Das verstehe ich nicht. Der MAX31855 führt selber doch keine Kaltstellenkompensation durch, sondern überträgt lediglich die Messerwerte von Thermoelement und internem Temperatursensor. Die Kompensation sollte Deine Software durchführen. Ob sie das richtig macht, solltest Du den Programmierer fragen, also Dich selbst. > (...) Der Messwert > entspricht der Wirklichkeit, ist schön stabil und schwankt nicht. Kann es sein, dass Deine Software die Messwerte glättet bzw. filtert? Dann würde ich den Fehler dort vermuten. Grüßle, Volker
Lothar M. schrieb: > Sind irgendwelche Fehlerbits gesetzt? Keins gesetzt, die sind alle drei auf 0. Das meinte ich mit "keine Fehlermeldung". Volker B. schrieb: > Der MAX31855 führt selber doch keine Kaltstellenkompensation durch Also laut Datenblatt macht er das: "The MAX31855 performs cold-junction compensation and digitizes the signal from a K-, J-, N-, T-, S-, R-, or E-type thermocouple." Was er nicht macht ist den Messwert zu linearisieren. Die Widerstandskurve ist ja nicht ganz linear, aber in meinem Messbereich ist der Fehler klein genug. Ich brenne ja nur Keramik ;) Volker B. schrieb: > Kann es sein, dass Deine Software die Messwerte glättet bzw. filtert? Ich lese alle 2s per Interrupt 5 Messwerte ein, frage die Fehlerbits ab und nehme den Mittelwert. Das Seltsame ist, dass das Messen der Temperatur grundsätzlich funktioniert (auch stundenlang), aber beim Einschalten muss das Thermo-Element kalt sein. Wenn es warm oder heiß ist, dann gibt's nur 0°C.
Fabian schrieb: > Also laut Datenblatt macht er das: "The MAX31855 performs cold-junction > compensation > and digitizes the signal from a K-, J-, N-, T-, S-, R-, or > E-type thermocouple." OK, Du verwendest also einen MAX31855K. Das depperte Datenblatt hätte ja auch darauf hinweisen können, dass jeder Thermoelement-Typ eine spezielle Version des MAX31855x benötigt... > Ich lese alle 2s per Interrupt 5 Messwerte ein, frage die Fehlerbits ab > und nehme den Mittelwert. ...und da läuft auch nichts über? ...und der Datenaustausch zwischen main() und Irpt-Handler erfolgt über eine volatile-Variable? > Das Seltsame ist, dass das Messen der Temperatur grundsätzlich > funktioniert (auch stundenlang), aber beim Einschalten muss das > Thermo-Element kalt sein. Wenn es warm oder heiß ist, dann gibt's nur > 0°C. Ich würde behaupten, dass der MAX genau das macht was er soll und der Fehler mal wieder in dem Teil liegt, der nicht gezeigt wird -- wie so oft in diesem Forum. Grüßle, Volker
:
Bearbeitet durch User
Dann rück' ich mal ein paar mehr Info's raus. Ich hatte gehofft, dass jemand schonmal genau das Gleiche gehabt hat. Ich verwende die Adafruit_MAX31855 Library. Die ist von Tausenden getestet und da steht auch nicht besonders viel drin. Ich würde den Fehler eher bei mir vermuten. Hier ist das Initialisieren:
1 | void setup() |
2 | {
|
3 | delay(500); |
4 | if (!furnace::thermocouple.begin()) |
5 | {
|
6 | furnace::_onerror("MAX31855"); |
7 | for(;;); |
8 | }
|
9 | |
10 | cli(); |
11 | TCCR1A = 0; |
12 | TCCR1B = 0; |
13 | OCR1A = 31250; // Alle 2s |
14 | TCCR1B = (1<<CS10) | (1<<CS12) | (1<<WGM12); |
15 | TIMSK1 = (1<<OCIE1A); |
16 | sei(); |
17 | }
|
und der Interrupt:
1 | ISR(TIMER1_COMPA_vect) |
2 | {
|
3 | furnace::control(); |
4 | }
|
5 | ...
|
6 | Adafruit_MAX31855 furnace::thermocouple(SPI_SYSTEM_CLOCK, SPI_CHIP_SELECT, SPI_MISO); |
7 | |
8 | double furnace::_read_temp_avg() |
9 | {
|
10 | double temps = 0; |
11 | for(int i = 0; i < sample_count; ++i) |
12 | {
|
13 | double probeTemperature = thermocouple.readCelsius(); |
14 | uint8_t faultCode = thermocouple.readError(); |
15 | if(faultCode & MAX31855_FAULT_OPEN) |
16 | _onerror("Nicht verbunden"); |
17 | else if(faultCode & MAX31855_FAULT_SHORT_GND) |
18 | _onerror("Masseschluss"); |
19 | else if(faultCode & MAX31855_FAULT_SHORT_VCC) |
20 | _onerror("Kurzschluss"); |
21 | else if(isnan(probeTemperature)) |
22 | _onerror("T/C Problem"); |
23 | temps += probeTemperature; |
24 | delay(100); |
25 | }
|
26 | return temps / static_cast<double>(sample_count) + temp_offset; |
27 | }
|
28 | |
29 | int32_t error_count = 0; |
30 | void furnace::control() |
31 | {
|
32 | auto t = _read_temp_avg(); |
33 | if (abs(actual_temp - t) > 30) // Temparatur innerhalb von 2s mehr als 30° gestiegen -> ignorieren |
34 | error_count++; |
35 | else
|
36 | actual_temp = t; |
37 | if (error_count > 30) |
38 | _onerror("Deltatemparatur"); |
39 | |
40 | bool old_state = is_heater_on; |
41 | if (actual_temp <= (set_temp - hysteresis)) |
42 | is_heater_on = true; |
43 | else if (actual_temp >= (set_temp + hysteresis)) |
44 | is_heater_on = false; |
45 | |
46 | if(old_state != is_heater_on) |
47 | digitalWrite(out_heat_element, is_heater_on ? HIGH : LOW); |
48 | }
|
sample_count ist uint8_t = 5 und temp_offset ist double = 0. Ich könnte am Wochenende ggf. ein Testprojekt fertig machen in dem nur das Nötigste steht um den Fehler zu reproduzieren. Die Variablen sind im Übrigen nicht als volatile gekennzeichnet -> wird geändert. Aber wie gesagt: Es funktioniert ja grundsätzlich. Ich habe letzten Freitag erfolgreich ein 14h Brennprogramm abgefahren. Der Fehler kommt nur in dieser Situation: Gerät ein >> Ofen aufheizen >> Gerät aus >> Gerät ein >> 0° (Funktion weg) >> Ofen etwas abkühlen lassen >> 30° >> 29° >> 28°... (Funktion wieder da)
Fabian schrieb: > Dann rück' ich mal ein paar mehr Info's raus. und hier tauchen merkwürdigerweise genau die magischen 30°C auf: > if (abs(actual_temp - t) > 30) // Temparatur innerhalb von 2s mehr als > 30° gestiegen -> ignorieren > error_count++; > else ...aber Schuld ist natürlich der IC :-) Grüßle, Volker
:
Bearbeitet durch User
Fabian schrieb: > Ich würde den Fehler eher bei mir vermuten. ;) Verdammt. Ich hab so lange drauf geguckt - Ich hab's einfach nicht gesehen. Grrr. So ein blöder Fehler. Vielen Dank Volker! Grüße
Fabian schrieb: > Verdammt. Ich hab so lange drauf geguckt - Ich hab's einfach nicht > gesehen. Das kenne ich nur zu gut! Bei umfangreichen Programmen drucke ich mir gern' das Listing aus und verziehe mich an einen Ort, wo es keine Ablenkung gibt und die einzige (sinnvolle) Beschäftigung das Lesen des Listings ist. Du glaubst nicht, wie viele logische Fehler ich dabei jedes Mal in meinem Code gefunden habe... Manchmal reicht es auch, eine Runde auf dem Fahrrad zu drehen, möglichst auf ruhigen Feld- und Waldwegen. Oft kommt mir dann eine "Eingebung" wo der logische Fehler zu suchen ist. Grüßle, Volker
:
Bearbeitet durch User
Volker B. schrieb: > Fabian schrieb: >> Dann rück' ich mal ein paar mehr Info's raus. > > und hier tauchen merkwürdigerweise genau die magischen 30°C auf: Volker B. schrieb: > Fabian schrieb: >> Verdammt. Ich hab so lange drauf geguckt - Ich hab's einfach nicht >> gesehen. > > Das kenne ich nur zu gut! Das ist die berühmt-berüchtigte "Betriebsblindheit" und auch nur allzu menschlich :)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.