Moin! Ich möchte die Spannung einer Sinus-Wechselspannung bestimmen. - Spannungsfrequenz: Variabel 1-1000 Hz - Spannungsbereich: 1-15 V - Genauigkeit der Messung ca. 50 mV - Häufigkeit: 1 - 10 Messungen / Sekunde (je nach Frequenz) Hauptprozessor wird ein ESP32 sein. Mein aktueller Ansatz ist grob der folgende: Sinus o | .-. | | | | '-' | -----+---------oADC | | | | .-. | - | | --- /\ | | --- | '-' | | | | GND GND GND Der Gedanke ist, dass der ESP32 direkt die Wechselspannung durch einen passenden Spannungsteiler heruntergeteilt auf seinen ADC bekommt. Eine Diode verhindert negative Spannungen am ADC-Eingang, ein kleiner Kondensator senkt den Innenwiderstand der Schaltung für den ADC. Durch einen (nicht eingezeichneten) Trigger, weiß der ESP, wann das Maximum der Spannung erreicht ist und startet die Konvertierung passend zum Maximum (oder kurz davor). Ich habe den Aufbau bereits ausprobiert und grundsätzlich funktioniert es auch, dass Problem ist, dass der gemessene Spannungswert frequenzabhängig ist. Ich gehe davon aus, dass es damit zu tun hat, dass die Messung gut 300us lang dauert und die Spannung bei hohen Frequenzen dann bereits nennenswert abgefallen ist. Eigentlich wäre ich davon ausgegangen, dass der ADC die Spannung zum Messstart "einfriert", dem scheint aber nicht so? Nun verwendet der ESP32 einen SAR-ADC. Ist das Verhalten bei einem Delta-Sigma-ADC wie dem AD1115 vergleichbar? Oder brauche ich noch andere ADCs? Hintergrundgedanke bei der Art der Messung ist dessen Einfachheit. Natürlich könnte ich auch eine Spitzenwertgleichrichtung vollziehen, dass ganze filtern und dann wandeln, allerdings scheitert es in der Regel an der variablen Frequenz und einer sinnvollen Filterung, die über den gesamten Frequenzbereich sinnvoll funktioniert. Aus diesem Grund hoffe ich auf eine einfache Lösung, wie die oben beschriebene.
Du hast einen Tiefpass gebaut - natürlich ist der gemessene Spannungswert frequenzabhängig.
meh schrieb: > Du hast einen Tiefpass gebaut - natürlich ist der gemessene > Spannungswert frequenzabhängig. Danke für den Hinweis. Allerdings habe ich den Tiefpass so ausgelegt, dass dessen Grenzfrequenz deutlich oberhalb von 1000 Hz liegt. Und selbst ohne Kondensator misst der ADC eine deutlich geringere Spannung. Darüber hinaus habe ich die Spannung am ADC mit einem Oszilloskop gemessen. Das Oszi hat bei allen Frequenzen ca. 1V am ADC gemessen. Hingegen hat der ADC Werte im Bereich von 1000 (von 4095) bei 100 Hz und 300 (von 4095) bei 1 kHz.
Wie viel Zeit vergeht zwischen Triggerung und Start der Wandlung?
Julian N. schrieb: > Moin! > Ich möchte die Spannung einer Sinus-Wechselspannung bestimmen. Was meinst du damit GENAU? Willst den Spitzen oder Effektivwert bestimmen? > Der Gedanke ist, dass der ESP32 direkt die Wechselspannung durch einen > passenden Spannungsteiler heruntergeteilt auf seinen ADC bekommt. OK. > Eine > Diode verhindert negative Spannungen am ADC-Eingang, Weniger OK. > ein kleiner > Kondensator senkt den Innenwiderstand der Schaltung für den ADC. Jain, er liefert die Ladung für die kurzen Meßpulse des ADC. > Durch > einen (nicht eingezeichneten) Trigger, weiß der ESP, wann das Maximum > der Spannung erreicht ist und startet die Konvertierung passend zum > Maximum (oder kurz davor). OK. Also willst du den Spitzenwert messen. > Ich habe den Aufbau bereits ausprobiert und grundsätzlich funktioniert > es auch, dass Problem ist, dass der gemessene Spannungswert > frequenzabhängig ist. Ich gehe davon aus, dass es damit zu tun hat, dass > die Messung gut 300us lang dauert 300us? Ist das die MESSUNG oder die Abtastung. Eigentlich ist die Abtastung sehr schnell, wenige Mikrosekunden. Die anschließende AD-Wandlung kann deutlich länger dauern, das ist aber egal, weil der Meßwert durch die Sample & Hold Stufe eingefroren wurde. >und die Spannung bei hohen Frequenzen > dann bereits nennenswert abgefallen ist. Eigentlich wäre ich davon > ausgegangen, dass der ADC die Spannung zum Messstart "einfriert", dem Tut er auch. > Nun verwendet der ESP32 einen SAR-ADC. Ist das Verhalten bei einem > Delta-Sigma-ADC wie dem AD1115 vergleichbar? Jain. > Oder brauche ich noch > andere ADCs? Nö. > den gesamten Frequenzbereich sinnvoll funktioniert. Aus diesem Grund > hoffe ich auf eine einfache Lösung, wie die oben beschriebene. Ich tippe auf ein Softwareproblem. Deine CPU verpennt den Trigger und mißt zu spät. Dein Trigger müßte einen hochpriorisierten Interrupt auslösen, der ohne Firlefanz die Messung startet. Das sollte ein 32 Bit COntroller mit vielen MHz in kaum mehr als 1-2us hinkriegen. Das mußt du prüfen. Setze ein IO-Signal auf HIGH, wenn der Meßvorgang beginnt. Miß die Verzögerung zwischen Trigger und Testsignal mit dem Oszilloskop.
Georg G. schrieb: > Wie viel Zeit vergeht zwischen Triggerung und Start der Wandlung? Ich habe einen Operationsverstärker mit + auf dem Sinus-Signal, Minus an einem Spannungsteiler, der Ausgang an einem ESP32-Pin als Interrupt. Immer wenn die Sinus-Spannung eine Spannung x übersteigt, geht dessen Ausgang auf High und ein Interrupt wird im ESP ausgelöst. Sinkt die Spannung, unter x, geht der OPV-Ausgang auf Low und ein zweiter Interrupt wird ausgelöst. Der ESP32 speichert die Mikrosekunden beider Triggerungen ab, berechnet dessen Differenz sowie die sich über mehrere Rise-Interrupts ergebene Frequenz. In einer Endlosschleife wird dann überprüft, ob sie sich zeitlich gerade im Bereich um +-5us um den berechneten nächsten Mittelpunkt befindet und startet dann die Messung mittels adc1_get_raw. Während der ADC-Messung wird ein Pin auf High gesetzt, was ich mit dem Oszilloskop auch sehen kann und das bestätigt, dass die Messung ca. 5-10 us nach dem Hochpunkt gestartet wird und ca. 170 us dauert. Zu diesem Zeitpunkt ist die Spannung dann um ca. 50 % abgefallen (1000 Hz). Hier der Code const uint16_t Pin_Interrupt = 33; const uint16_t Pin_Measuring = 27; volatile uint32_t t_start; volatile uint32_t t_duration; volatile uint32_t frequency_measured; volatile bool adc_now = false; void ADC(void* pvParameters) { bool next_measure = true; adc1_config_width(ADC_WIDTH_BIT_12); adc1_config_channel_atten(ADC1_CHANNEL_4, ADC_ATTEN_11db); while (1) { if (next_measure && digitalRead(Pin_Interrupt) && micros() > t_start + t_duration / 2 - 10 && micros() < t_start + t_duration / 2 + 0) { last_time = micros(); digitalWrite(Pin_Measuring, HIGH); last_value = adc1_get_raw(ADC1_CHANNEL_4); digitalWrite(Pin_Measuring, LOW); next_measure = false; } else if (next_measure && micros() > t_start + t_duration / 2 + 10) { next_measure = false; } if (!digitalRead(Pin_Interrupt)) next_measure = true; vTaskDelay(1 / portTICK_PERIOD_MS); } } void IRAM_ATTR ISR_Int() { const uint32_t t_start_new = micros(); if (digitalRead(Pin_Interrupt)) { frequency_measured = 1000000 / (t_start_new - t_start); t_start = t_start_new ; adc_now = true; } else { t_duration = t_start_new - t_start; adc_now = false; } } void setup(void) { [...] xTaskCreatePinnedToCore(ADC, "ADC", 10000, NULL, 1, &DAC, 1); pinMode(Pin_Interrupt, INPUT); attachInterrupt(digitalPinToInterrupt(Pin_Interrupt), ISR_Int, CHANGE); }
Falk B. schrieb: > Julian N. schrieb: >> Moin! >> Ich möchte die Spannung einer Sinus-Wechselspannung bestimmen. > > Was meinst du damit GENAU? > Willst den Spitzen oder Effektivwert bestimmen? An sich wäre es mir gleich, weil beides ineinander überführbar ist. In diesem konkreten Fall möchte ich die Spitzenspannung bestimmen. >> Eine >> Diode verhindert negative Spannungen am ADC-Eingang, > > Weniger OK. Weil? Theoretisch verzehrt sie mir aufgrund des Stromes bei positivem Signal minimal meine gemessene Spannung, allerdings ist der Effekt aufgrund des geringen Stromes insgesamt zu vernachlässigen. >> ein kleiner >> Kondensator senkt den Innenwiderstand der Schaltung für den ADC. > > Jain, er liefert die Ladung für die kurzen Meßpulse des ADC. Ist das nicht letztlich gleichbedeutend? > 300us? Ist das die MESSUNG oder die Abtastung. Eigentlich ist die > Abtastung sehr schnell, wenige Mikrosekunden. Die anschließende > AD-Wandlung kann deutlich länger dauern, das ist aber egal, weil der > Meßwert durch die Sample & Hold Stufe eingefroren wurde. Okay, schon Mal vielen Dank für diese Info! > Ich tippe auf ein Softwareproblem. Deine CPU verpennt den Trigger und > mißt zu spät. Dein Trigger müßte einen hochpriorisierten Interrupt > auslösen, der ohne Firlefanz die Messung startet. Das sollte ein 32 Bit > COntroller mit vielen MHz in kaum mehr als 1-2us hinkriegen. Das mußt du > prüfen. Setze ein IO-Signal auf HIGH, wenn der Meßvorgang beginnt. Miß > die Verzögerung zwischen Trigger und Testsignal mit dem Oszilloskop. Siehe meinen letzten Post, in dem ich nun auch das Programm geteilt habe. Eine weitere Überlegung meinerseits ist die Nichtlinearität des ESP-ADCs. Aus diesem Grund habe ich bewusst Spannungen im "mittleren" Messbereich gewählt. Laut der Seite https://docs.espressif.com/projects/esp-idf/en/v3.3/api-reference/peripherals/adc.html bei ADC_ATTEN_11db zwischen 150 und 2450mV. Konkret ein paar Messwerte: | Frequenz | Gemessene Spannung | Gemessener | | | (Oszi) in V | ADC-Wert | | -------- | ------------------ | ---------- | | 0 | 1.335 | 1174 | | 100 | 1.230 | 1067 | | 1000 | 1.255 | 585 | | 0 | 0.722 | 572 | | 100 | 0.668 | 515 | | 1000 | 0.678 | 260 | Die mit dem Oszilloskop gemessene Spannung ist jeweils zum Zeitpunkt der steigenden Flanke meines ADC-Start-Signals (Pin_Measuring) gemessen.
:
Bearbeitet durch User
Um auf den Pufferkondensator noch einmal einzugehen. Ich habe hinter den Spannungsteiler einen weiteren Operationsverstärker als Spannungsfolger geschaltet. Dahinter ein 120 Ohm Widerstand mit einem 100 nF Kondensator in Reihe gegen Masse. Zwischen Widerstand und Kondensator liegt der ADC. Die Grenzfrequenz müsste nach meinem Verständnis bei 13 kHz liegen und somit weit über meine zu messenden 1 kHz. Die gemessenen ADC-Werte stabilisieren sich so auch minimal und steigen etwas, sind allerdings weiterhin ca. 40 % niedriger als erwartet.
Hallo, musste mal ein Druckgeber retative genau Auswerten. Hab das driften (über Zeit) und Abweicheungen (verglichen mit Oszi) beim ESP32-ADC auch nicht im griff bekommen. Hab mir dann ein ADS1115 besogt und mit bisschen digital Filtern klappte es dann sehr gut :) Gruß Michael
Falk B. schrieb: > Ich tippe auf ein Softwareproblem. Deine CPU verpennt den Trigger und > mißt zu spät. Dein Trigger müßte einen hochpriorisierten Interrupt > auslösen, der ohne Firlefanz die Messung startet. Das sollte ein 32 Bit > COntroller mit vielen MHz in kaum mehr als 1-2us hinkriegen. Das mußt du > prüfen. Setze ein IO-Signal auf HIGH, wenn der Meßvorgang beginnt. Miß > die Verzögerung zwischen Trigger und Testsignal mit dem Oszilloskop. Damit liegst du wohl tatsächlich richtig! Ich habe das Skript noch ein wenig überarbeitet, sodass der geplante Messzeitpunkt relativ zum Triggermittelpunkt verschoben werden kann. Hierbei stellte sich heraus, dass wenn ich 150 us vor dem Mittelpunkt ein 10 us/(Frequenz/1Hz) langes Fenster eröffne, um zu messen, dann werden die Werte bei 1000 Hz genauso hoch gemessen, wie bei 1 Hz!
Julian schrieb: > Hierbei stellte sich heraus Also hast du anfangs nicht das Maximum erwischt sondern warst schon auf der fallenden Flanke. Wie wäre es mit einem anderen Ansatz: Am vermuteten Maximum messen. Nächste Messung etwas früher. Messwert ist höher: Wir sind nach dem Maximum. Weiter in diese Richtung. Messwert ist niedriger: Wir sind noch vor dem Maximum. Etwas später messen. Das Ganze so lange, bis der Unterschied zwischen zwei Messungen kleiner als xxx ist. Eventuell die Messzeitpunkte über der Frequenz merken. Dann geht es beim nächsten Versuch schneller. Die Frequenz misst du ja ohnehin.
Georg G. schrieb: > Wie wäre es mit einem anderen Ansatz: Am vermuteten Maximum messen. > Nächste Messung etwas früher. Messwert ist höher: Wir sind nach dem > Maximum. Weiter in diese Richtung. Messwert ist niedriger: Wir sind noch > vor dem Maximum. Etwas später messen. Das Ganze so lange, bis der > Unterschied zwischen zwei Messungen kleiner als xxx ist. > > Eventuell die Messzeitpunkte über der Frequenz merken. Dann geht es beim > nächsten Versuch schneller. Die Frequenz misst du ja ohnehin. Gefällt mir! In die Richtung wird es auf jeden Fall gehen! Aktuell muss ich nur erst den Schaltungsaufbau fertig bekommen, sodass bestellt werden kann und dann ist genug Zeit zum Programmieren :D Wenn ich dran denke, werde ich das Ergebnis hier auch nochmal teilen :)
Julian schrieb: > Georg G. schrieb: >> Wie viel Zeit vergeht zwischen Triggerung und Start der Wandlung? > > Ich habe einen Operationsverstärker mit + auf dem Sinus-Signal, Minus an > einem Spannungsteiler, der Ausgang an einem ESP32-Pin als Interrupt. Was soll diese Lyrik? Zeig uns einen gescheiten Schaltplan! > Immer wenn die Sinus-Spannung eine Spannung x übersteigt, geht dessen > Ausgang auf High und ein Interrupt wird im ESP ausgelöst. Sinkt die > Spannung, unter x, geht der OPV-Ausgang auf Low und ein zweiter > Interrupt wird ausgelöst. Nennt sich Komparator. > Der ESP32 speichert die Mikrosekunden beider > Triggerungen ab, berechnet dessen Differenz sowie die sich über mehrere > Rise-Interrupts ergebene Frequenz. In einer Endlosschleife wird dann > überprüft, ob sie sich zeitlich gerade im Bereich um +-5us um den > berechneten nächsten Mittelpunkt befindet und startet dann die Messung > mittels adc1_get_raw. Ganz falsch. Die ADC-Messung muss in der ISR erfolgen. Alles anders ist deutlich schlechter zeitlich definiert. > Während der ADC-Messung wird ein Pin auf High > gesetzt, was ich mit dem Oszilloskop auch sehen kann und das bestätigt, > dass die Messung ca. 5-10 us nach dem Hochpunkt gestartet wird und ca. > 170 us dauert. Zu diesem Zeitpunkt ist die Spannung dann um ca. 50 % > abgefallen (1000 Hz). 1kHz sind 1ms Periodendauer, die Halbwelle nur 500us. Wenn man die Spitze auf deine 50mV genau treffen will, kann man sich grob geschätzt kaum 5us Fehler leisten. > > Hier der Code Entweder als Anhang oder in Klammern, damit das besser formatiert wird. > while (1) { > if (next_measure && digitalRead(Pin_Interrupt) && micros() > > t_start + t_duration / 2 - 10 && micros() < t_start + t_duration / 2 + > 0) { Viel zu kompliziert. Wenn schon, dann muss EINE Bedingung in einer Variable definiert werden, welche dann hier ein GO gibt. > last_time = micros(); > digitalWrite(Pin_Measuring, HIGH); > last_value = adc1_get_raw(ADC1_CHANNEL_4); Wie bereits gesagt, ist das hier falsch. Die ADC-Messung gehört in den Interrupt. Allein die sehr schnelle CPU mit vielen MHz rettet dich hier, gibt dir aber die falsche Sicherheit, ein gutes Konzept zu haben.
Julian schrieb: >> Eventuell die Messzeitpunkte über der Frequenz merken. Dann geht es beim >> nächsten Versuch schneller. Die Frequenz misst du ja ohnehin. > > Gefällt mir! In die Richtung wird es auf jeden Fall gehen! Aktuell muss > ich nur erst den Schaltungsaufbau fertig bekommen, sodass bestellt > werden kann und dann ist genug Zeit zum Programmieren Falsch! Du glaubt, das alles mal schnell-schnell neben zu lösen und dann einfach nur bissel Programmieren zu müssen. Ein verbreiteter Irrtum. Du mußt dein Konzept sowie deine Schaltung auf den Prüfstand stellen und vermutlich deutlich verbessern. Allein schon dein Komparator zur Generierung des Triggers für die Maximummessung ist so nicht gut. > :D Wenn ich dran > denke, werde ich das Ergebnis hier auch nochmal teilen :) Jaja . . .
Wenn man es richtig machen möchte... https://www.analog.com/media/en/technical-documentation/data-sheets/AD8436.pdf https://www.analog.com/media/en/technical-documentation/data-sheets/1968f.pdf Es gibt noch mehr solcher Bausteine. fchk
Frank K. schrieb: > Wenn man es richtig machen möchte... Einfach mal lesen. Er will den Spitzenwert messen, nicht RMS. Es ist anscheinend auch ein reiner Sinus, da brauch es keinen High Tec RMS-DC Wandler.
Falk B. schrieb: >> Der ESP32 speichert die Mikrosekunden beider >> Triggerungen ab, berechnet dessen Differenz sowie die sich über mehrere >> Rise-Interrupts ergebene Frequenz. In einer Endlosschleife wird dann >> überprüft, ob sie sich zeitlich gerade im Bereich um +-5us um den >> berechneten nächsten Mittelpunkt befindet und startet dann die Messung >> mittels adc1_get_raw. > > Ganz falsch. Die ADC-Messung muss in der ISR erfolgen. Alles anders ist > deutlich schlechter zeitlich definiert. Also mein Wissen über ISRs besagt, dass diese möglichst KURZ sein sollten. Eine 300 us lange dauernde Messung zähle ich sicherlich nicht dazu. Mal davon abgesehen, dass ich überhaupt kein Interrupt zum Zeitpunkt der maximalen Spannung habe, sondern einen vor dem Maximum und einem nach dem Maximum. Das Maximum befindet sich in der Mitte der beiden und ist sehr wohl ausreichend präzise "zeitlich definiert". Wie kommst du darauf, das dem nicht so wäre? Meine Oszilloskop-Messung (von der ich oben sprach) bestätigt diese These ja eindeutig! Zudem habe ich den Vorteil, den Zeitpunkt der Messung beliebig um das Maximum herum zu verschieben. Also "Ganz falsch" sicherlich nicht... > 1kHz sind 1ms Periodendauer, die Halbwelle nur 500us. Wenn man die > Spitze auf deine 50mV genau treffen will, kann man sich grob geschätzt > kaum 5us Fehler leisten. Bei 1 V und 1 kHz habe ich einen Spannungsbfall von 50 mV nach über 50 us. (cos(2*PI*1000Hz*50us)=0.95) Entsprechend habe ich praktisch sogar ein Zeitfenster von +-50 us um das Maximum. Eine Abweichung von 5 us ist somit völlig unproblematisch. > Entweder als Anhang oder in Klammern, damit das besser formatiert wird. Mache ich nächstes Mal besser. >> while (1) { >> if (next_measure && digitalRead(Pin_Interrupt) && micros() > >> t_start + t_duration / 2 - 10 && micros() < t_start + t_duration / 2 + >> 0) { > > Viel zu kompliziert. Wenn schon, dann muss EINE Bedingung in einer > Variable definiert werden, welche dann hier ein GO gibt. Weil? Hast du für diese These irgendwelche Gründe? >> last_time = micros(); >> digitalWrite(Pin_Measuring, HIGH); >> last_value = adc1_get_raw(ADC1_CHANNEL_4); > > Wie bereits gesagt, ist das hier falsch. Die ADC-Messung gehört in den > Interrupt. Allein die sehr schnelle CPU mit vielen MHz rettet dich hier, > gibt dir aber die falsche Sicherheit, ein gutes Konzept zu haben. Nein ist es nicht, wie bereits oben geschrieben. Und du irrst dich. Mit einem AtMega128 hätte ich weit weniger Probleme als mit dem ESP32. Einem AtMega mit 20 MHz könnte ich einfach endlos in einer Schleife warten lassen und würde den Zeitpunkt deutlich präziser treffen. Beim ESP32 hingegen habe ich Multitasking, sodass es passieren kann, dass die ADC-Messung überhaupt nicht aufgerufen wird, wenn der Zeitpunkt gekommen ist. Unabhängig davon ändert dies nichts an der Präzision des Messzeitpunktes. Diesen stelle ich mit der Größe meines Fensters ein, indem die Messung gestartet wird. Es kann lediglich passieren, dass ich eine Messung verpasse, dann nehme ich halt die nächste, ich brauche sowieso keine 1000 in der Sekunde (wie oben geschrieben). Ungenauer wird es dadurch aber sicherlich nicht, weder zeitlich noch werttechnisch!
Frank K. schrieb: > https://www.analog.com/media/en/technical-documentation/data-sheets/AD8436.pdf > https://www.analog.com/media/en/technical-documentation/data-sheets/1968f.pdf Danke für den Tipp, die habe ich mir auch schon angeschaut. Allerdings habe ich keine einfache und funktionierende Filterung hinbekommen, welche die 1 Hz bis 1000 Hz Ausgangssignale der Chips ausreichend geglättet bekommt. Da ist mein gewählter Ansatz m.E. einfacher und funktioniert ja genauso?
Hallo, Julian schrieb: >>> if (next_measure && digitalRead(Pin_Interrupt) && micros() > >>> t_start + t_duration / 2 - 10 && micros() < t_start + t_duration / 2 + >>> 0) { als alternative. Timer auf 1ms (jeh nach Genugigkeit) interrupt stellen -> Timer stoppen -> Timer durch interrupt starten -> Werte von mehreren Wellen ins Array schreiben -> danach kannste zwei maxima suchen array prosition entspricht dann ja zeitangabe (vergangene Zeit) --> Frequenz. Wenn du das driften und abweichung (gemessen zum oszi) im griff bekommst hast. ADC-Wert x Kurrector = Scheitelspannung. Gruß Michael
Wenn ich das richtig sehe, ist der Task eh in einer Busy-Loop und wartet (pollend) auf den passenden Zeitpunkt. Dann sample doch stattdessen ständig und bestimm den Spitzenwert in Software.
Julian schrieb: > Frank K. schrieb: >> https://www.analog.com/media/en/technical-documentation/data-sheets/AD8436.pdf >> https://www.analog.com/media/en/technical-documentation/data-sheets/1968f.pdf > Danke für den Tipp, die habe ich mir auch schon angeschaut. Allerdings > habe ich keine einfache und funktionierende Filterung hinbekommen, > welche die 1 Hz bis 1000 Hz Ausgangssignale der Chips ausreichend > geglättet bekommt. Da ist mein gewählter Ansatz m.E. einfacher und > funktioniert ja genauso? Du weißt schon, dass diese Chips Wechselspannung reinbekommen und Gleichspannung am Ausgang ausgeben? Und diese Gleichspannung kannst Du einfach mit einem ADC messen. Einfach so. Ohne Interrupt usw. fchk
Falk B. schrieb: >> Während der ADC-Messung wird ein Pin auf High gesetzt, >> was ich mit dem Oszilloskop auch sehen kann und das >> bestätigt, dass die Messung ca. 5-10 us nach dem >> Hochpunkt gestartet wird und ca. 170 us dauert. Zu >> diesem Zeitpunkt ist die Spannung dann um ca. 50 % >> abgefallen (1000 Hz). > > 1kHz sind 1ms Periodendauer, die Halbwelle nur 500us. > Wenn man die Spitze auf deine 50mV genau treffen will, > kann man sich grob geschätzt kaum 5us Fehler leisten. Die Theorie sagt, dass man die Spitze gar nicht treffen muss. Leider interessiert sich niemand für die Theorie...
Frank K. schrieb: > Du weißt schon, dass diese Chips Wechselspannung > reinbekommen und Gleichspannung am Ausgang ausgeben? Ohne Integrationskondensator und ohne Frequenzabhängigkeit? Träum' weiter... Einfach mal das Diagramm auf Seite 12 des ersten Daten- blattes angucken...
Julian schrieb: > Durch > einen (nicht eingezeichneten) Trigger, weiß der ESP, wann das Maximum > der Spannung erreicht ist und startet die Konvertierung passend zum > Maximum (oder kurz davor). Ja - das wird was hingeben... Nur gut, dass Du den (Hardware-) Trigger "nicht eingezeichnet" hast, denn genau da liegt der Hund begraben. Einfach mal drauf los programmieren, ohne dass das Konzept auch nur in die Nähe von "tragfähig" kommt - das kann nicht gut gehen. Jedenfalls könnte das noch sehr spannend werden. Soll ich schon mal popcorn holen?
Julian schrieb: >> Ganz falsch. Die ADC-Messung muss in der ISR erfolgen. Alles anders ist >> deutlich schlechter zeitlich definiert. > Also mein Wissen über ISRs besagt, dass diese möglichst KURZ sein > sollten. Eine 300 us lange dauernde Messung zähle ich sicherlich nicht > dazu. Stimmt. Aber keine Regel ohne Ausnahme. Außerdem müssen ISRs nicht extrem kurz sein, sondern nur so kurz, als daß sie andere Interrupts bzw. die Hauptschleife nicht zu viel ausbremsen. Das kann im Einzelfall auch viele Millisekunden sein. > Mal davon abgesehen, dass ich überhaupt kein Interrupt zum > Zeitpunkt der maximalen Spannung habe, sondern einen vor dem Maximum und > einem nach dem Maximum. Das Maximum befindet sich in der Mitte der > beiden und ist sehr wohl ausreichend präzise "zeitlich definiert". Wie präzise? Selbst wenn man den Nullpunkt als schaltschwelle nimmt, ist das zwar theoretisch sehr genau, aber praktisch nicht ganz so einfach wie du denkst. Schon gar nicht mit deiner naiven Arduino-Denkweise. < Wie > kommst du darauf, das dem nicht so wäre? Meine Oszilloskop-Messung (von > der ich oben sprach) bestätigt diese These ja eindeutig! Zudem habe ich > den Vorteil, den Zeitpunkt der Messung beliebig um das Maximum herum zu > verschieben. Also "Ganz falsch" sicherlich nicht... Falsch genug, als daß man da noch einiges machen muss. >> Viel zu kompliziert. Wenn schon, dann muss EINE Bedingung in einer >> Variable definiert werden, welche dann hier ein GO gibt. > Weil? Hast du für diese These irgendwelche Gründe? Weil du selber nur schlecht durchsiehst und auch die Berechnung Zeit braucht, wenn gleich daß bei deiner schnellen CPU kaum ins Gewicht fällt. >> Wie bereits gesagt, ist das hier falsch. Die ADC-Messung gehört in den >> Interrupt. Allein die sehr schnelle CPU mit vielen MHz rettet dich hier, >> gibt dir aber die falsche Sicherheit, ein gutes Konzept zu haben. > Nein ist es nicht, wie bereits oben geschrieben. Und du irrst dich. Mit > einem AtMega128 hätte ich weit weniger Probleme als mit dem ESP32. Einem > AtMega mit 20 MHz könnte ich einfach endlos in einer Schleife warten > lassen und würde den Zeitpunkt deutlich präziser treffen. Beim ESP32 > hingegen habe ich Multitasking, Hast du das? Läuft da wirklich (pääemtives) Multitasking? Das Arduino-Framework macht keins, da läuft bestenfalls ein 1ms Timer. > sodass es passieren kann, dass die > ADC-Messung überhaupt nicht aufgerufen wird, wenn der Zeitpunkt gekommen > ist. Unsinn. > sowieso keine 1000 in der Sekunde (wie oben geschrieben). Ungenauer wird > es dadurch aber sicherlich nicht, weder zeitlich noch werttechnisch! Wenn du meinst. Mach mal.
foobar schrieb: > Wenn ich das richtig sehe, ist der Task eh in einer Busy-Loop und wartet > (pollend) auf den passenden Zeitpunkt. Dann sample doch stattdessen > ständig und bestimm den Spitzenwert in Software. Damit umschipperst man ein Problem, holt Dir dafür ein neue ins Boot: Wie schnell muss man sampeln, damit innerhalb der Messzeit der Spitzenwert garantiert hinreichend genau (0.33% ?) getroffen wird. Zusatzfrage: Wer entscheidet wann über die Messzeit, also 100 ... 1000ms?
Jester schrieb: > foobar schrieb: >> Wenn ich das richtig sehe, ist der Task eh in einer Busy-Loop und wartet >> (pollend) auf den passenden Zeitpunkt. Dann sample doch stattdessen >> ständig und bestimm den Spitzenwert in Software. > > Damit umschipperst man ein Problem, holt Dir dafür ein neue ins Boot: > Wie schnell muss man sampeln, damit innerhalb der Messzeit der > Spitzenwert garantiert hinreichend genau (0.33% ?) getroffen wird. Bei maximaler Aussteuerung eines 12bit Wandlers: (90° - arcsin(4095/4096)) × 2 Das wäre dann ein Bereich von ~ 2,5° um den Scheitelwert. Aber mal ganz ehrlich, so ein ESP hat/ist doch schon ein erwachsener Prozessor. Den lässt man einfach mit maximaler Geschwindigkeit im Kreis laufen und gut iss. Selbst ein AVR braucht nur wenige Prozent Prozessorleistung wenn er 15000 Mal pro Sekunde den ADC bedient.
@fchk Wie der Grummler bereits richtig feststellte, ist leider auch bei diesen Chips ein dahintergeschalteter Filter notwendig. Falk B. schrieb: > Stimmt. Aber keine Regel ohne Ausnahme. Außerdem müssen ISRs nicht > extrem kurz sein, sondern nur so kurz, als daß sie andere Interrupts > bzw. die Hauptschleife nicht zu viel ausbremsen. Das kann im Einzelfall > auch viele Millisekunden sein. Richtig, im Einzelfall. Und wer hätte es gedacht, ich nehme einen ESP32 nicht, weil ich scheiße programmiere, sondern weil ich weitere Funktionen von ihm benötige, wie WLAN, diverse ADCs, beide DACs, SPI, I²C, etc. Da passiert im Hintergrund weit mehr als du glaubst und entsprechend werde ich mich an meinem allgemein sinnvollen Grundsatz halten, ISRs kurz zu halten! > Wie präzise? Selbst wenn man den Nullpunkt als schaltschwelle nimmt, ist > das zwar theoretisch sehr genau, aber praktisch nicht ganz so einfach > wie du denkst. Schon gar nicht mit deiner naiven Arduino-Denkweise. Offen präzise genug!? Wenn mein ADC die RICHTIGEN Werte mit MEINER Methode im Experiment bestimmt, dann ist es ganz offensichtlich präzise genug... Und was auch von der Theorie nur logisch ist! Keine Ahnung, weshalb du diese gewaltigen Ungenauigkeiten erwartest. Aber bestimmt, kommt jetzt eh wieder nur eine inhaltlose Antwort, dass ich zu dumm sei, meinen Fehler zu erkennen, ohne Mal wirklich INHALT zu schreiben. Wenn du ach so toll, intelligent und allwissend bist, dann teile uns doch dein Wissen, dass wir davon lernen können oder lass es einfach ganz bleiben. Deine leeren Phrasen bringen niemanden weiter -.- Falk B. schrieb: > Julian schrieb: >> Nein ist es nicht, wie bereits oben geschrieben. Und du irrst dich. Mit >> einem AtMega128 hätte ich weit weniger Probleme als mit dem ESP32. Einem >> AtMega mit 20 MHz könnte ich einfach endlos in einer Schleife warten >> lassen und würde den Zeitpunkt deutlich präziser treffen. Beim ESP32 >> hingegen habe ich Multitasking, > > Hast du das? Läuft da wirklich (pääemtives) Multitasking? Das > Arduino-Framework macht keins, da läuft bestenfalls ein 1ms Timer. Ja auf einem ESP32 arbeitet präemtives Multitasking. Siehe https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos.html Offenbar habe ich mit meiner "naiven Arduino" Denkweise mehr Plan von dem, was ich hier tue als du glaubst... Aber mach ruhig weiter mit deinen unbegründeten Thesen ala "ist eh alles sche*** was du machst". Das restliche Gesülze erspare ich mir zu beantworten. Falls noch konstruktive Hinweise und Ideen kommen, immer gerne her damit! Wie gesagt, ich danke dir für deinen Hinweis mit dem zeitlichen Verzug der Messung! Dessen Herkunft ist mir leider weiterhin unklar, aber letztlich problemlos lösbar. Übrigens, die oben gezeigte Software ist eine rein für das Experiment geschriebene Software, um die Machbarkeit zu beweisen. Das hat sie getan. Fehlerfrei oder gar perfekt ist sie sicherlich nicht, ist auch nicht notwendig. Das wird Aufgabe sein, wenn die Hardware steht. Übrige inhaltlose Kommentare werde ich ignorieren... Falls Langeweile besteht, tob dich (oder @Jester) gerne weiter aus.
Norbert schrieb: > Jester schrieb: >> foobar schrieb: >>> Wenn ich das richtig sehe, ist der Task eh in einer Busy-Loop und wartet >>> (pollend) auf den passenden Zeitpunkt. Dann sample doch stattdessen >>> ständig und bestimm den Spitzenwert in Software. >> >> Damit umschipperst man ein Problem, holt Dir dafür ein neue ins Boot: >> Wie schnell muss man sampeln, damit innerhalb der Messzeit der >> Spitzenwert garantiert hinreichend genau (0.33% ?) getroffen wird. > > Bei maximaler Aussteuerung eines 12bit Wandlers: > (90° - arcsin(4095/4096)) × 2 > Das wäre dann ein Bereich von ~ 2,5° um den Scheitelwert. Hut ab - Du bist der Erste, der das Problem mal mathematisch angegangen ist! Angenommen, die 2.5° würden stimmen, würde sich daraus ein Sample-Intervall (bzw. Sample-Jitter) von 2.5°/360° x 1ms = 6.8us ableiten lassen - unabhängig davon, ob die Methode nach "foobar" oder "Julian" zum Einsatz kommt. In Beitrag "Re: Direkte Messung von Wechselspannung mittels ADC" geht Julian von 50us aus, in Beitrag "Re: Direkte Messung von Wechselspannung mittels ADC" schätzt Falk B. 5us wären richtig, in Beitrag "Re: Direkte Messung von Wechselspannung mittels ADC" meint Grummeler, dass das eh alles schei*egal sei. Bei so viel „Unsicherheit“ hätte ich noch keine einzige Zeile Code generiert, ja mich noch nicht mal für einen uC entschieden. Wobei die Frage nach der Messzeit, also 100 ... 1000ms immer noch nicht entschieden ist - geschweige denn, wie die Methode "Julian" die (toleranzbehaftete) Signalfrequenz bestimmen will. Schießlich braucht er diese, um den optimalen Sample-Zeitpunkt im Voraus festzulegen.
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.