Forum: Mikrocontroller und Digitale Elektronik MAX31855 Fehler bei heißem Sensor


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Fabian (Gast)


Lesenswert?

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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Fabian schrieb:
> Ich hoffe ihr könnt mir helfen :)
Sind irgendwelche Fehlerbits gesetzt?

von Volker B. (Firma: L-E-A) (vobs)


Lesenswert?

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

von Fabian (Gast)


Lesenswert?

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.

von Volker B. (Firma: L-E-A) (vobs)


Lesenswert?

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
von Fabian (Gast)


Lesenswert?

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)

von Volker B. (Firma: L-E-A) (vobs)


Lesenswert?

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
von Fabian (Gast)


Lesenswert?

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

von Volker B. (Firma: L-E-A) (vobs)


Lesenswert?

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
von Magnus M. (magnetus) Benutzerseite


Lesenswert?

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
Noch kein Account? Hier anmelden.