PT1000 an RP2040-pico-Board

OP #7012197
Lesenswert?

Für einen ATmega328 gibt es schon einen Beitrag zur Auswertung eines 
PT1000: Beitrag "PT1000, einfache Auswertung mit AVR (ATmega328)"
Dort wird ein 10 Bit ADC verwendet, welcher bei höheren Temperaturen 
eine nicht so hohe Auflösung liefert. Der RP2040 hat nun einen 12 Bit 
ADC, zu dem es allerdings keine genauen Daten gibt, weshalb auch keine 
genauere Bestimmung des Messfehlers möglich ist.

Für eigene Versuche/Spielereien hier ein angepasstes Programm für 
Arduino-IDE und eine beispielhafte .log-Datei, die Temperaturen im 
Bereich -54 °C bis +385 °C mit 1 K Auflösung aufgezeichnet hat.

Da sich beim RP2040 Ein- und Ausgangssignale durch Setzen eines 
CTRL-Bits invertieren lassen, sind hier beim UART1 die Signale 
invertiert. Das TxD1-Signal an GP0 kann somit direkt an einen 
RS232-USB-Wandler angeschlossen werden. Sollte auch RxD1 an GP1 
verwendet werden, ist auf jeden Fall ein serieller Schutzwiderstand (3k3 
- 10k) vor dem Eingang notwendig.
Je nach Anwendung könnte es vorteilhaft sein, anstatt den PT1000 mit 
langem Kabel anzuschließen, den PT1000 direkt am pico-Board zu betreiben 
und das TxD-Signal mit +5 V und GND über eine längere Leitung zu führen.
Angehängte Dateien:
Gast #7012220
Lesenswert?

Mi N. schrieb:
> Für einen ATmega328 gibt es schon einen Beitrag zur Auswertung eines
> PT1000: Beitrag "PT1000, einfache Auswertung mit AVR (ATmega328)"

Ja.

Du hättest den dortigen thread auch lesen durfen.

Oder noch schlimmer, du bis.N. bzw. m.n. selbst unter erneut neuem 
Namen.

Die Schaltung ist Scheisse.

Man betreibt Pt1000 nicht mit einer Spannung über dem Pt1000 von 2.5V, 
1.65V, 1.25V, 0.55V, das führt zu hohem Messfehler durch Eigenerwärmung, 
und man belastet Referenzspannungsausgänge nicht mit vielen Milliampere.

Beim RP2040 hast du zudem die Schaltung verschwiegen, der hat auf den 
üblichen Platinen eine RC gefilterte Referenzspannung von 3.3V, es wird 
aber vielleicht von dir ratiometrisch zur ungefilterten Betriebsspannung 
(Versorgung Output Pin) gemessen, was dann keineswegs mehr ratiometrisch 
ist, sondern nur noch verrauscht.

Statt immer wieder zielgenau die schlechteste aller Lösungen 
anzustreben, sollte man einfach mal lesen, wie man es richtig macht.

https://dse-faq.elektronik-kompendium.de/dse-faq.htm#F.32
OP #7013895
Lesenswert?

Im Programm steht neben der Funktionsbeschreibung auch wie die beiden 
Widerstände angeschlossen werden müssen.
Hier noch einmal das Schaltbild dazu.
Der serielle Ausgang ist GP0: Pin 1 des pico-Boards.

Wenn man den ser. Monitor in der Arduino-IDE nutzen möchte, müssen die 
Serial1.xxx() Aufrufe nach Serial.xxx() geändert werden.
Angehängte Dateien:
Gast #7013937
Lesenswert?

Mi N. schrieb:
> Hier noch einmal das Schaltbild dazu

Ja, schlimm, hier sieht man, wie ARef vom RP2040 aussieht

https://proto-pic.co.uk/wp-content/uploads/2021/03/RPI-PICO-R3-PUBLIC-SCHEMATIC.pdf

Also 200 Ohm Ausgangswiderstand und er belastet mit 2k, da bricht die 
Spannung schon mal um 10% auf 3V ein, und es kommen satte 1.5V mit 1.5mA 
an den Pt1000, statt der üblichen 0.1V und maximalen 0.33V.

Was er da noch ausser Hausnummern messen will, bleibt schleierhaft.
OP #7014640
Lesenswert?

Εrnst B. schrieb:
> Lustigerweise ohne klare Definition, ob der Pin anschließend hart LOW
> oder HIGH ist.

Blind aber gut gelaut. Schön!
Als Programmieranfänger muß man lernen, daß es explizite und implizite 
Funktionen gibt. Nur weil Du etwas nicht siehst, bedeutet das ja nicht, 
daß es nicht existiert.
Statt Götzenanbeterei hätte Du auch fragen können. Aber es ging Dir wohl 
garnicht um einen konstruktiven Beitrag.
#7015051
Lesenswert?

Mi N. schrieb:
> Als Programmieranfänger(*) muß man lernen,

Gut erkannt. Hier eine kleine Übungsaufgabe für dich, so zum Start:

Was muss passieren, dass diese Funktion hier ein "gpio_put" ausführt, 
wenn sie mit Parametern "PT_IN_0, OUTPUT" aufgerufen wird?

1
extern "C" void pinMode(pin_size_t ulPin, PinMode ulMode) {
2
    switch (ulMode) {
3
    case INPUT:
4
        gpio_init(ulPin);
5
        gpio_set_dir(ulPin, false);
6
        gpio_disable_pulls(ulPin);
7
        break;
8
    case INPUT_PULLUP:
9
        gpio_init(ulPin);
10
        gpio_set_dir(ulPin, false);
11
        gpio_pull_up(ulPin);
12
        gpio_put(ulPin, 0);
13
        break;
14
    case INPUT_PULLDOWN:
15
        gpio_init(ulPin);
16
        gpio_set_dir(ulPin, false);
17
        gpio_pull_down(ulPin);
18
        gpio_put(ulPin, 1);
19
        break;
20
    case OUTPUT:
21
        gpio_init(ulPin);
22
        gpio_set_dir(ulPin, true);
23
        break;
24
    default:
25
        DEBUGCORE("ERROR: Illegal pinMode mode (%d)\n", ulMode);
26
        // Error
27
        return;
28
    }
29

30
    if (ulPin > 29) {
31
        DEBUGCORE("ERROR: Illegal pin in pinMode (%d)\n", ulPin);
32
        return;
33
    }
34
    _pm[ulPin] = ulMode;
35
}

Falls du diese schwere Aufgabe gemeisterst hast, nächste Frage, diesmal 
mehr in die "Lesen und verstehen"-Richtung:

Wer definiert den Zustand des Pins bei Programmstart, wenn dein Programm 
es nicht explizit vorgibt?

A) Das Arduino-Framework. Wenn ja: Wo dokumentiert, wo definiert?
B) Die Registerinhalte des RP2040 bei Reset.

Bonusfrage: Unter welchen Umständen kann ein Programm ohne vorherigen 
Hardware-Reset ausgeführt werden? Oder ist das kategorisch 
ausgeschlossen?


Und als Finale:

Welche schlimmen Folgen hätte es gehabt, einfach in der setup() mit 
einem digitalWrite für klare Verhältnisse zu sorgen?



*) Falls du dich fragst, was dich als blutigen Anfänger geoutet hat:
Es war hauptsächlich die Überflüssige "do {} while (1);" - Schleife in 
deiner loop().
Die verhindert nämlich u.A. dass "yield()" aufgerufen wird, und macht 
damit die TinyUSB-Funktionalität kaputt.
OP #7015522
Lesenswert?

Ist ja alles ganz nett, aber interessiert nicht die Bohne. Hier geht es 
um einen PT1000 und nicht um TinyUSB.

Der Controller setzt per Hardware-Reset seine Peripherie in einen 
definierten Zustand. Sofern die IDE anschließend nicht unerlaubter Weise 
daran herumdreht, steht das Ausgangsdatenregister von GPIO26 / ADC0 auf 
'0'.
So ist es im hier vorliegenden Programm der Fall!

Den ADC0-Pin im Programm wiederholt auf seinen Ausgangswert zu bringen, 
ist dann ein "Angstkondensator" in Software. Zur Sicherheit natürlich 
nicht in setup() sondern in loop(). Gut, es schadet nicht. Aber dann 
bitte auch die RxD und TxD Pins noch einmal "richtig" auf Eingang bzw. 
Ausgang setzen - man weiß ja nie.
OP #7526702
Lesenswert?

Andreas M. schrieb:

Der ADC im RP2040 schafft leider keine 12 Bit.

Das ist alles bekannt. Sieh Dir bitte die .txt-Datei an und zeige mir die Stelle, an der das passieren müßte. Ich habe sie nicht gefunden; vielleicht gelingt es Dir. Der ADC-Wert 2560 abzüglich des Offsets von 16 ergibt 2544. Dazu werden 170 °C errechnet wie auch zu 2543, da keine Nachkommstelle angezeigt wird.

Die "Ausraster" könnte man kompensieren, indem man an den kritischen Stellen einen kleinen Offset zuschaltet (Pullup/Pulldown) oder seinen Messbereich zwischen zwei "Fehlerstellen" verschiebt. Auch damit bleiben der Aufwand gering und der gesamte Messbereich sehr hoch.

#7526751
Lesenswert?

Mi N. schrieb:

Das ist alles bekannt. Sieh Dir bitte die .txt-Datei an und zeige mir die Stelle, an der das passieren müßte. Ich habe sie nicht gefunden; vielleicht gelingt es Dir.

Deine Messung bringt so nix. Du nimmst einen ADC Wert, berechnest daraus eine Temperatur und versuchst darin dann was zu sehen. Die berechnete Temperatur ist aber einfach nur eine andere Darstellung des ADC Werts, sie ist eine davon abhängige Größe.

Was du machen müsstest wäre die berechnete Temperatur mit der Temperaturmessung eines zweiten, unabhängigen Messgerätes zu vergleichen. Dann wirst Du einen schönen Sprung sehen, so etwa bei 178 °C ( Nach Deiner Formel ) Allerdings nutzt Du ja gerade mal ca 25% des Messbereichs des ADCs

Nimm ein Poti, Klemme das an den ADC und an ein Multimeter. Dann machst Du eine Messreihe in mV Schritten, notiere ADC Werte und Spannung auf dem Multimeter. Es reichen die Regionen um die ADC Zählwerte 512, 1536, 2560, und 3584.

Mi N. schrieb:

Die "Ausraster" könnte man kompensieren, indem man an den kritischen Stellen einen kleinen Offset zuschaltet (Pullup/Pulldown) oder seinen

Nicht wirklich, der Fehler ist auch an den nicht kritischen Stellen noch sehr groß. Schau dir das INL Diagramm in http://pico-adc.markomo.me/INL-DNL/#why-does-the-dnl-spike an. Aus Softwaresicht besteht das Problem, das ein ADC Zählwert mehrere Spannungen bedeuten kann. Du kannst also vom Zählwert nicht ableiten, in welche Richtung du korrigieren musst.

OP #7526792
Lesenswert?

Andreas M. schrieb:

Die berechnete Temperatur ist aber einfach nur eine andere Darstellung des ADC Werts, sie ist eine davon abhängige Größe.

Genau darum geht es, wenn man einen PT1000 auswertet ;-)

Andreas M. schrieb:

Nicht wirklich, der Fehler ist ...

daß Du mich nicht verstanden hast. Im Datenblatt sind die Fehlstellen benannt. Folglich kann man an den Stellen, die diesen Werten entsprechen, einen Offset hinzufügen/abziehen, um den ADC in einen unkritischen Bereich zu bringen. Ein paar Millivolt sollten reichen. Anschließend muß der neue ADC-Wert um den Offset korrigiert werden. Dazu braucht es noch ein wenig Gehirnschmalz, um den Offset automatisch zu erfassen. Für die doppelte Messung ergibt sich eine kleine Verzögerung (< 1 ms) des Ergebnisses, was nicht stören dürfte. Die Auflösung bleibt hoch und die erreichbare Genauigkeit hängt von ADC und den verwendeten Bauteilen ab. Wer +/- 1 mK erwartet, ist hier falsch!

#7527175
Lesenswert?

Mi N. schrieb:

Gut, und was ist Deine Lösung? Einen diskreten ADC verwenden oder doch nur einen billigen Widerstand?

Ich nutze nur 8 Bit, das reicht zum Glück für meine Zwecke aus. Wenn ich mehr brauche dann würde ich ne externen nehmen oder nen Sigma Delta in Software implementieren wenn es sich um eine langsame Größe (wie z.B. Temperatur handels). Da reicht ein GPIO Pin. müsste über die PIO eigentlich gehen:

https://www.microchip.com/en-us/application-notes/an700 https://elmicro.com/files/elmicro/due9810_sigdelta.pdf

Mi N. schrieb:

Vieleicht sind die neueren RP2040 auch schon verbessert.

Nein, aktuell ist da kein Silicon Fix geplant. (Wäre auch garn icht ohne weiteres möglich weil da ganze Flächen umorganisiert werden müssen)

OP #7527186
Lesenswert?

Andreas M. schrieb:

Gut, und was ist Deine Lösung? Einen diskreten ADC verwenden oder doch nur einen billigen Widerstand?

Ich nutze nur 8 Bit, das reicht zum Glück für meine Zwecke aus.

Vielleicht berücksichtige ich die Kompensation noch in der Schaltung und im Programm. Im Grunde reicht es, einen 100 k Widerstand zum 1 k parallel zu schalten - einfach 3,3 V per GPIO über diesen Widerstand an den ADC-Eingang - und sonst "fliegend" zu lassen. Alternativ nimmt man einen etwas größeren Wert als 1 k, um mit dem ADC-Wert im Bereich 1536 - 2560 zu liegen. -50 -> +200 °C sollten dann unkorrigiert messbar sein.

OP #7528944
Lesenswert?

Andreas M. schrieb:

Nicht wirklich, der Fehler ist auch an den nicht kritischen Stellen noch sehr groß. Schau dir das INL Diagramm in http://pico-adc.markomo.me/INL-DNL/#why-does-the-dnl-spike an. Aus Softwaresicht besteht das Problem, das ein ADC Zählwert mehrere Spannungen bedeuten kann. Du kannst also vom Zählwert nicht ableiten, in welche Richtung du korrigieren musst.

Die Sache habe ich mir noch einmal näher angeschaut und ein paar Versuche durchgeführt. Danke für Deinen Einwand. Eine (Bereichs-)Umschaltung vorzunehmen, um aus den kritischen Bereichen herauszukommen, ist nicht so sinnvoll, es sei denn, man könnte bei Stückzahlen dadurch richtig viel sparen.

Beschränkt man sich beim ADC auf den Wertebereich von 1536 - 2559 (INL_INDEX = 2 bzw. 3. Segment der INL-Kurve) und erhöht zudem R1 auf 1,200 kOhm, erhält man einen Messbereich von rund -70 bis +250 °C.

Im neuen Programm ist eine Korrektur der INL laut Datenblatt vorhanden, um den ADC-Fehler zu reduzieren. Weitere und dominante Fehlerquellen sind jedoch die Güteklasse des PT1000 selbst, der genaue Wert von R1, der 0-Offset des ADCs und der recht grobe Skalierungsfaktor von 0,0385. Hier wäre es angesagt, über Tabellenwerte zu interpolieren. Beispiele dazu gibt es an anderer Stelle. Hier wollte ich das Demo-Programm übersichtlich und durch Debug-Ausgaben die Funktion nachvollziehbar halten. Getestet habe ich die Funktion mit Drehpoti und USB-Ausgabe, wodurch der Aufbau recht einfach war. Vielleicht nutzt es.

Angehängte Dateien:
#7529184
Lesenswert?

Mi N. schrieb:

Die Sache habe ich mir noch einmal näher angeschaut

Ich halte es für eine sehr schlechte Idee, den V_Ref zu belasten.

Wenn Dein µC seine Betriebsspannung als Referenz nutzt, kommt der Spannungsteiler samt PTC direkt an diese. Wenn diese sich ändert, macht das garnichts, weil ja das Verhältnis gemessen wird. Auf µC-net beliebig oft durchgekaut, "Ratiometrische Messung".

#7529228
Lesenswert?

Ich bin nicht sicher, ob das hier schon genannt wurde, aber die Referenzspannung auf dem Pico-Board ist ziemlich unsauber. Man kann aber einfach am Vref-Pin einen Referenz-Shunt (LM4040 mit 3V bietet sich an) nach Masse schalten. Der R7 auf dem Pico-Board dient dann schon als Vorwiderstand für die Referenz.

Im Anhang der Ausschnitt aus dem Datenblatt des Pico-Boards.

PS: Die Referenz sollte man natürlich nicht belasten. :)

Angehängte Dateien:
OP #7529398
Lesenswert?

Jonny O. schrieb:

Ich bin nicht sicher, ob das hier schon genannt wurde, aber die Referenzspannung auf dem Pico-Board ist ziemlich unsauber. Man kann aber einfach am Vref-Pin einen Referenz-Shunt (LM4040 mit 3V bietet sich an) nach Masse schalten. Der R7 auf dem Pico-Board dient dann schon als Vorwiderstand für die Referenz.

Dann mache es! Meine Schaltungen/Programme sind nicht in Stein gemeißelt und konstruktive Erfahrungsberichte sind willkommen.

Was erwartest Du von einer absolut stabilen Referenz? Mehr Auflösung, höhere Genauigkeit? Ich habe da meine Zweifel. R9 in der Schaltung mit 1R ist eher eine Lötbrücke. V_REF und V_ADC sind (fast) identisch und daher werden hier ratiometrische Messungen gemacht. R7 mit 200R und C13 mit 2µ2 filtern die restlichen 1 MHz Spitzen vom Schaltregler locker weg. Das Kurzschließen des PT1000 läßt die Spannung V_REF leicht wackeln, was bei einer ratiometrischen Messung aber nicht stört.

Bei einigen Schaltungen schalte ich den lokalen Schaltregler des Pico-Boards ab und verwende einen extenern 3,3 V LDO für das gesamte Board. Das halte ich hier für nicht notwendig.

Den NOS-Wert (number of samples) hatte ich testweise von 1 auf 100 gesetzt, um beim fliegenden (Poti-)Aufbau Störungen zu vermeiden. Aktuell habe ich dann wieder mit einer Einzelmessung und 1000 Ohm für R1 gemessen: die Ergebnisse sind gleich. Selbst die dummy-Messung vor der Erfassung des Messwertes kann entfallen, wenn die Zuleitung keine zu große Kapazität aufweist.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren