Forum: Projekte & Code PT1000 an RP2040-pico-Board


You were forwarded to this site from EmbDev.net. Back to EmbDev.net
von Mi N. (msx)


Angehängte Dateien:

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.

: Bearbeitet durch User
von MaWin (Gast)


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

von Mi N. (msx)


Angehängte Dateien:

Lesenswert?

Anbei noch die von der Arduino-IDE exportierte .uf2-Datei, die man 
direkt auf das pico-Boards kopieren kann.

von ossi (Gast)


Lesenswert?

Wie sieht die Schaltung aus?

von Mi N. (msx)


Angehängte Dateien:

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.

von MaWin (Gast)


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.

von Εrnst B. (ernst)


Lesenswert?

MaWin schrieb:
> und er belastet mit 2k

MaWin schrieb:
> satte 1.5V mit 1.5mA
> an den Pt1000

dazu kommt noch diese schicke Codezeile:
1
 pinMode(PT_IN_0, OUTPUT);             // PT1000 wieder kurzschließen
Lustigerweise ohne klare Definition, ob der Pin anschließend hart LOW 
oder HIGH ist.

d.H. entweder wird Aref meistens mit 1k belastet, oder der PT1000 mit 
3.3mA

von Mi N. (msx)


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.

von Εrnst B. (ernst)


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.

von Mi N. (msx)


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.

von Andreas M. (amesser)


Lesenswert?

Der ADC im RP2040 schafft leider keine 12 Bit. Es gibt einen 
Silicon-Bug, einer der Referenzkondensatoren ist falsch dimensioniert. 
Deswegen steht im Datenblatt ja auch eine ENOB von 8.7, gibt diverse 
Abhandlungen im Netz dazu. Effektiv ist der ADC nur bis 8 Bit zu 
gebrauchen.

von Mi N. (msx)


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.

von Andreas M. (amesser)


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.

von Mi N. (msx)


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!

von Andreas M. (amesser)


Lesenswert?

Mi N. schrieb:
> Genau darum geht es, wenn man einen PT1000 auswertet ;-)

Du hast nicht verstanden was ich geschrieben habe.

von Mi N. (msx)


Lesenswert?

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

Vieleicht sind die neueren RP2040 auch schon verbessert.

von Andreas M. (amesser)


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)

von Mi N. (msx)


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.

von Mi N. (msx)


Angehängte Dateien:

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.

: Bearbeitet durch User
von Manfred P. (pruckelfred)


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

von Jonny O. (-geo-)


Angehängte Dateien:

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. :)

: Bearbeitet durch User
von Mi N. (msx)


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.

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.