Hallo, ich kämpfe seit Tagen damit,Temperaturwerte aus einem ADC vom STM32 auszulesen. Ich habe DMA und polling versucht und jedes mal sind die Werte total unplausibel. Wenn ich mit einem multimeter Messe sehen die Werte aber plausibel aus. Hat jemand das schonmal gemacht und den Beispielcode für mich?
Patrick E. schrieb: > Hat jemand das schonmal gemacht und den Beispielcode für mich? https://github.com/STMicroelectronics/STM32CubeF0/tree/master/Projects/STM32F042K6-Nucleo/Examples/ADC/ADC_DMA_Transfer Dürfte sich bereits auf deinem PC befinden als Teil des STM32CubeF0.
Patrick E. schrieb: > Ich habe DMA und polling versucht Dann zeig Mal den Code dazu. Ohne kann hier niemand weiter helfen. Patrick E. schrieb: > und jedes mal sind die Werte total unplausibel. Wie äußert sich das? Wie sehen die Werte aus und was erwartest du? Patrick E. schrieb: > Wenn ich mit einem multimeter Messe sehen die Werte aber plausibel aus. Wieso, was misst du damit? Patrick E. schrieb: > Hat jemand das schonmal gemacht und den Beispielcode für mich? Etwas unspezifisch. Zum einen gibt es von ST selbst einige Beispiele. Zum anderen ist das mit Arduino eine Zeile. Also was genau willst du?
Patrick E. schrieb: > ich kämpfe seit Tagen damit,Temperaturwerte aus einem ADC vom STM32 > auszulesen. Ich würde eher sagen du kämpfst damit hier klar darzustellen was du überhaupt machst bzw. machen willst. Also zuerst mal: Aus einem ADC kann man keine Temperaturwerte auslesen.
Patrick E. schrieb: > Hat jemand das schonmal gemacht und den Beispielcode für mich?
1 | #!/python
|
2 | # -*- coding: UTF-8 -*-
|
3 | # vim: fileencoding=utf-8: ts=4: sw=4: expandtab:
|
4 | from machine import Pin,ADC |
5 | |
6 | ADC_PIN_NUM = xxx |
7 | |
8 | adc_pin = Pin(ADC_PIN_NUM, Pin.IN, None) |
9 | adc_channel = ADC(adc_pin) |
10 | value = adc_channel.read_u16() >> 4 |
Ich habe alles soweit schon ausprobiert, im Moment sieht es so aus: https://dpaste.org/7m6zr https://dpaste.org/DymS9 Wenn ich das richtig verstehe, kann man bei den kleinen STM32 die "Scan conversation mode" nicht ausschalten und muss daher immer alle konfigurierten ADC Sensoren in einem rutsch pollen. Deshalb sollte man lieber DMA benutzen, man sieht auch noch schnippsel von dem DMA code in dem source code, diese werden zur Zeit nicht benutzt. Die Beispiele kenne ich auch, die rufen da aber nur einen ADC ab, wenn ich micht nicht täusche. Ich habe auch meine clock config mal angehängt.
:
Bearbeitet durch User
Die Eingangsimpedanz der ADC schwankt stark mit der Einlesegeschwindigkeit. So hochohmig wie deine Messchaltung ist, solltest du so langsam wie sinnvoll messen...
Roland E. schrieb: > Die Eingangsimpedanz der ADC schwankt stark mit der > Einlesegeschwindigkeit. So hochohmig wie deine Messchaltung ist, > solltest du so langsam wie sinnvoll messen... Also du meinst ich sollte den Spannungsteiler lieber auf 1k / 100R reduzieren? Kann ich mit meinen 10k NTCs kann überhaupt was anfangen?...
Patrick E. schrieb: > Also du meinst ich sollte den Spannungsteiler lieber auf 1k / 100R > reduzieren? Kann ich mit meinen 10k NTCs kann überhaupt was anfangen?... Die Impedanz des Spannungsteilers entspricht der Parallelschaltung beider Widerstände. 1k / 100R ergäben 91 Ohm 10k / 10k ergeben 5k Ohm Bis 10k bin ich sicher, dass das ohne Probleme funktionieren kann. Denn niemand zwingt dich dazu, eine besonders kurze Sampling-Zeit einzustellen. Siehe file:///home/stefan/Downloads/an2834-how-to-optimize-the-adc-accuracy-in -the-stm32-mcus-stmicroelectronics.pdf Kapitel 3.2.7 und 4.2.6
Monk schrieb: > file:///home/stefan/Downloads/an2834-how-to-optimize-the-adc-accuracy-in > -the-stm32-mcus-stmicroelectronics.pdf Schon wieder jemand, der lokale Files verlinkt. Da kann keiner von uns drauf zugreifen.
Oliver R. schrieb: > Schon wieder jemand, der lokale Files verlinkt. Oh, das hatte ich per Google gefunden und aus der URL Zeile kopiert, ohne genau hin zu schauen. https://www.st.com/resource/en/application_note/an2834-how-to-optimize-the-adc-accuracy-in-the-stm32-mcus-stmicroelectronics.pdf Noch eine Ergänzung: Man kann mit einem Oszilloskop am Eingang des ADC messen, wie stark er den Spannungsteiler belastet. Man kann ggf. diese Spannung mit externen Kondensatoren (zwischen Signal und GND) stabilisieren. Wenn der externe Kondensator relativ groß ist (z.B. 100nF) und zwischen den Messungen reichlich Zeit zum Aufladen bekommt, dann ergibt sich eine schön stabile Spannung. Ganz egal wie hochohmig der Spannungsteiler ist.
Monk schrieb: > ... > > Man kann ggf. diese Spannung mit externen Kondensatoren (zwischen Signal > und GND) stabilisieren. Wenn der externe Kondensator relativ groß ist > (z.B. 100nF) und zwischen den Messungen reichlich Zeit zum Aufladen > bekommt, dann ergibt sich eine schön stabile Spannung. Ganz egal wie > hochohmig der Spannungsteiler ist. Jepp. 100n vor den Pin auf dem geteilten Signal sollte auch gehen. Eine Akkuspannung muss man ja nicht 1000x pro Sekunde einlesen. Da kann man auch 1x in der Sekunden den ADC einmal messen lassen. Auf der Seite 107 in https://www.st.com/resource/en/datasheet/stm32f401re.pdf ist die berechnung für die Eingangsimpedanz der ADC. Ich habe mir aus den Erfahrungen gemerkt, dass alles über 5k Quellimpedanz extrem ungenau wird. Die in den electrical Spec angegbenen 50k (max) sind reines Wunschdenken am theoretischen Rand des ADC...
:
Bearbeitet durch User
Ich habe jetzt mal 100 nF vom signal zu Masse gelötet. Sampling rate ist auf Maximum trotzdem springen die Werte zwischen 0 und 4095. Gemessen habe ich am spannungsteiler 0,2xxx Volt also sollte ich doch ca 248 am ADC auslesen... Ungefähr .
Patrick E. schrieb: > Sampling rate ist auf Maximum trotzdem springen die Werte zwischen 0 und > 4095. Gemessen habe ich am spannungsteiler 0,2xxx Volt also sollte ich > doch ca 248 am ADC auslesen. Also wahrscheinlich ein Softwareproblem.
Monk schrieb: > Patrick E. schrieb: >> Sampling rate ist auf Maximum trotzdem springen die Werte zwischen 0 und >> 4095. Gemessen habe ich am spannungsteiler 0,2xxx Volt also sollte ich >> doch ca 248 am ADC auslesen. > > Also wahrscheinlich ein Softwareproblem. Mit dma kommt auch nur 0 zurück. Sollte ich mal von HAL auf LL umschalten in cubemx? Ich habe jetzt so ziemlich alle Kombinationen durch und weiß auch nicht mehr weiter wie ich da sinnvolle werte raus bekommen soll.
Patrick E. schrieb: > Sollte ich mal von HAL auf LL umschalten in cubemx? Ich bin kein Fan von der HAL, aber ich bin sicher, dass die Problemursache woanders liegt. Lerne lieber, sie richtig zu benutzen. Dazu reicht die Doku der HAL alleine nicht aus. Man muss auch das Reference Manual und das Datasheet dazu lesen. Vielleicht erst mal mit einem STM32F0 oder L0 anfangen, denn die sind weniger komplex.
:
Bearbeitet durch User
Patrick E. schrieb: > Wenn ich das richtig verstehe, kann man bei den kleinen STM32 die "Scan > conversation mode" nicht ausschalten und muss daher immer alle > konfigurierten ADC Sensoren in einem rutsch pollen. Nein, hast du nicht. STM32F0x Reference Manual: Analog input channels: – 16 external analog inputs – 1 channel for internal temperature sensor (V SENSE ) – 1 channel for internal reference voltage (V REFINT ) – 1 channel for monitoring external V BAT power supply pin Start-of-conversion can be initiated: – By software – By hardware triggers with configurable polarity (timer events) Conversion modes: – Can convert a single channel or can scan a sequence of channels. – Single mode converts selected inputs once per trigger – Continuous mode converts selected inputs continuously – Discontinuous mode
Patrick E. schrieb: > Die Beispiele kenne ich auch, die rufen da aber nur einen ADC ab, wenn > ich micht nicht täusche. Dann fang doch erstmal damit an. Wenn das Beispiel einen Kanal korrekt abfragt kannst du es erweitern. Man kann bei solchen Themen so viel falsch machen, da ist es absolut sinnvoll mit einem funktionierenden(!) Beispiel anzufangen anstatt Ewigkeiten an einem vermurksten Code herumzudoktorn. Und wenn es doch ein Hardware-Problem ist, kannst du lange an der Software herumpfuschen.
Patrick E. schrieb: > Die Beispiele kenne ich auch, die rufen da aber nur einen ADC ab, wenn > ich micht nicht täusche. Der STM32F04xx hat nur einen einzigen ADC. Der jeweilige Messkanal wird durch einen Multiplexer auf dessen Eingang gelegt (Neudeutsch "geroutet"). Per DMA kann man eine vorher festgelegte Reihenfolge der Messkabnäle festlegen, die ziemlich wahlfrei ist (ich kene das Reference Manual des F04 nicht [auswendig]). Mit STCubeMX kann man das alles fertig konfigurieren,
Patrick E. schrieb: > Sampling rate ist auf Maximum trotzdem springen die Werte zwischen 0 und > 4095. Das weckt den Verdacht, dass du das ADC-Register zum falschen Zeitpunkt ausliest. Wo in deinem hier gezeigten Quellcode wird denn sichergestellt, dass in dem Register im Moment des Auslesens ein gültiger Wert steht?
:
Bearbeitet durch User
Niklas G. schrieb: >> uint32_t AD_RES_BUF[ADC_BUF_SIZE]; > > Liefert der ADC nicht 16bit-Werte?! 12Bit. Ist aber unkritisch, das 16Bit-Register in einen 32Bit uint zu packen. RAM ist bei den Cortex billig, da muss man nicht wegen drei oder vier Byte rumgeizen. Rechnen tut der schließlich auch mit 32Bit...
Roland E. schrieb: > Rechnen tut der schließlich auch mit 32Bit... Das DMA speichert aber wahrscheinlich einzelne 16bit-Werte in diesen Puffer. Wenn man diese in C als 32bit ausliest passiert Murks.
Niklas G. schrieb: > Das DMA speichert aber wahrscheinlich einzelne 16bit-Werte in diesen > Puffer. Wenn man diese in C als 32bit ausliest passiert Murks. Guter Punkt. Ob das wohl die Problemursache ist?
Niklas G. schrieb: > Das DMA speichert aber wahrscheinlich einzelne 16bit-Werte in diesen > Puffer. Wenn man diese in C als 32bit ausliest passiert Murks. Kann sein. Ich habe das nicht mehr so im Gedächtnis. Wegen solcher Hinweise sollte man sich das Kapitel "ADC" und/oder "DMA" im Reference Manual angucken.
Niklas G. schrieb: > Das DMA speichert aber wahrscheinlich einzelne 16bit-Werte in diesen > Puffer. Wenn man diese in C als 32bit ausliest passiert Murks. Patrick E. schrieb: > trotzdem springen die Werte zwischen 0 und 4095. Lässt sich jedoch nicht mit falscher DMA Übertragungsgröße (WORD/HALFWORD) erklären.
Patrick E. schrieb: > Mit dma kommt auch nur 0 zurück. Sollte ich mal von HAL auf LL > umschalten in cubemx? Ich habe jetzt so ziemlich alle Kombinationen > durch und weiß auch nicht mehr weiter wie ich da sinnvolle werte raus > bekommen soll. Da würd' ich doch glatt mal alle ADC- und DMA-Register "zu Fuß" auslesen und kontrollieren, ob da wirklich das Gewünschte drin steht ...
Norbert schrieb: > Niklas G. schrieb: >> Das DMA speichert aber wahrscheinlich einzelne 16bit-Werte in diesen >> Puffer. Wenn man diese in C als 32bit ausliest passiert Murks. > > Patrick E. schrieb: >> trotzdem springen die Werte zwischen 0 und 4095. > > Lässt sich jedoch nicht mit falscher DMA Übertragungsgröße > (WORD/HALFWORD) erklären. Ich hatte HALFWORD/HALFWORD konfiguriert... Was aber natürlich Murks ist. Ich habe jetzt, weil RAM hab ich ja, auf WORD/WORD umgestellt und siehe da. Es klappt... plausible Werte.. Wirklich vielen vielen Dank! Und ich werde mir für die nächste Schaltung merken, dass ich die ADC Eingangswiderstände überprüfe und die Eingänge puffer.
Patrick E. schrieb: > Ich hatte HALFWORD/HALFWORD konfiguriert... Was aber natürlich Murks > ist. Ich habe jetzt, weil RAM hab ich ja, auf WORD/WORD umgestellt und > siehe da. Es klappt... plausible Werte.. WORD sind in dieser Architektur 32bit und somit gänzlich unnötig bei ADC. HALFWORD sind 16 bit und das ist korrekt, wenn man damit ein uint16 array füllt. Oftmals kann man sogar (bei verminderter Auflösung) den ADC auf 8bit setzen (autoshift >> 4) und mit DMA BYTE Transfers ein uint8 array füllen.
Norbert schrieb: > Patrick E. schrieb: >> Ich hatte HALFWORD/HALFWORD konfiguriert... Was aber natürlich Murks >> ist. Ich habe jetzt, weil RAM hab ich ja, auf WORD/WORD umgestellt und >> siehe da. Es klappt... plausible Werte.. > > WORD sind in dieser Architektur 32bit und somit gänzlich unnötig bei > ADC. > HALFWORD sind 16 bit und das ist korrekt, wenn man damit ein uint16 > array füllt. > Oftmals kann man sogar (bei verminderter Auflösung) den ADC auf 8bit > setzen (autoshift >> 4) und mit DMA BYTE Transfers ein uint8 array > füllen. Richtig wäre dann ja trotzdem WORD -> HALFWORD ... Ich hatte nicht verstanden das es hier um peripherie Breite --> Memory Breite ging.
Patrick E. schrieb: > Richtig wäre dann ja trotzdem WORD -> HALFWORD Ne, HALFWORD Peripherie (ADC, 12Bit) zu HALFWORD Memory (uint16_t). Dein eigentlicher Fehler war also deinen Buffer uint32_t zu deklarieren.
Patrick E. schrieb: > Richtig wäre dann ja trotzdem WORD -> HALFWORD ... Ich hatte nicht > verstanden das es hier um peripherie Breite --> Memory Breite ging. Ähm, nein. Datenblatt STM32F0: 13.11.9 ADC data register (ADC_DR) Address offset: 0x40 Reset value: 0x0000 0000 Bits 15:0 DATA[15:0]: Converted data Also DMA read: HALFWORD (nimmt automagisch den unteren 16bit Teil) DMA write: HALFWORD Edit: N.M. war schneller
:
Bearbeitet durch User
Außer dass es unnötig Speicher frisst nützt dir das Array als uint32 ja nichts. P.S. Das Log() in deiner Konvertierung würde ich auch lieber durch eine Tabelle ersetzen.
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.