ADC-Kanäle sukzessive abfragen

#7890194
Lesenswert?

StefanK schrieb:

Veit D. schrieb:

StefanK schrieb:

@Veit D.

Ein bool Datentyp hat immer die kleinste Byte Größe. Beim 8Bit AVR 1 Byte. Lasse dir auf deiner Zielplattform von allen Datentypen die Größe mittels sizeof() ausgeben. bool kann nur Werte von true/false annehmen. Das ist die Eigenschaft des Datentyps.

Dann bedeutet das, dass mehrere bools in so einer Struct nicht in ein Byte gepackt werden?

Nein.

D.h. man muß sich ein Byte anlegen, dieses als Bit-Basis verwenden und auf seine bits einzeln zugreifen, wenn man nicht für jedes bool ein ganzes Byte spendieren will.

Du kannst bei Bedarf mit Bitfelder rumspielen. https://en.cppreference.com/w/cpp/language/bit_field.html

OP #7890212
Lesenswert?

Dergute W. schrieb:

Moin,

StefanK schrieb:

was hätten denn mehr Details zu Anfang Ihrer Meinung nach daran geändert, die Methode zu finden, wie man am schnellsten ohne im Hauptprogramm zu warten mehrere ADC-Kanäle mißt?

Dann waere z.b. mir voellig klar gewesen, dass das mit dem "am schnellsten" natuerlich Quatsch ist.

Ja, das wäre wohl so gekommen und wir hätten Ihre Ideen verloren, wenn Sie sich aus der Diskussion verabschiedet hätten. Das finde ich eben schade.

@Rainer W. (rawi)

Möchtest du die Flügelschläge einzelner überfliegender Insekten ausregeln oder warum so schnell?

Das vielleicht nicht gerade, es gibt ja auch immer weniger Insekten ;-) Es gibt von Microchip eine interessante Application Note dazu. Sie verwenden natürlich einen PIC. Der mißt 4 Kanäle * 4 Messungen und Mittelwert mit 1000Hz (wir schaffen immerhin 600Hz mit Atmega328/ATtiny bei 16MHz Systemtakt). Die 1000 Datensätze pro Sekunde gehen in einen PI-Regler, der den MPP 40 mal pro Sekunde anpasst. Bei allen MPP-Suchalgorithmen von P&O, Hill-Climbing über Incremental Condutance bis hin zu Fire Flies etc. steigt der MPP-Wirkungsgrad, also den richtigen Punkt zu finden und zu halten mit der Frequenz. Daher ist es gut schnell zu sein.

#7890222
Lesenswert?

Moin,

StefanK schrieb:

Ja, das wäre wohl so gekommen und wir hätten Ihre Ideen verloren, wenn Sie sich aus der Diskussion verabschiedet hätten. Das finde ich eben schade.

Bullshit. Wenn du gleich am Anfang auch noch erwaehnt haettest, dass du ja auch noch einen UART brauchst, den aber mangels Vorhandensein in HW unbedingt in SW machen musst, dann waere ziemlich sicher nicht nur bei mir die Idee aufgekommen, eben den zeitkritischen Teil des UARTs im Timerinterrupt zu machen und dann eher so "nebenbei" den ollen ADC zu triggern und dessen Eingang umzuschalten. Und nich ewig rumzukaspern ob der ADC jetzt 13.5 oder 14.3 Takte braucht... Und wenn du dann auch noch erwaehnt haettest, dass dein Wissen von seriellen Protokollen in C auch noch durchaus Potential nach oben hat... Naja, waere sicherlich schneller gegangen, da was wirklich halbwegs durchdachtes fuer's Gesamtproblem vorzuschlagen, kann mir ja aber eher auch wurscht sein :-)

Gruss WK

OP #8058068
Lesenswert?

Nachtrag: 10 Jahre vor diesem Beitrag hatte Sebastian Foerster die gleiche Projektidee. Er löste die Messung von 4 Spannungen mit dem ADC im Freerunning Modus so:

1
ISR(ADC_vect) 
2
{
3
  switch(ADMUX)
4
  {
5
    case ADCMUX_CELL_VOLTAGE:
6
      //ADCSRB = 0; //change conversation to free running;
7
      cell_voltage = ADCW;
8
      ADMUX = ADCMUX_CELL_CURRENT;
9
    break;
10
    
11
    case ADCMUX_CELL_CURRENT:
12
      cell_current = ADCW;
13
      ADMUX = ADCMUX_ACCU_VOLTAGE;
14
    break;
15
    
16
    case ADCMUX_ACCU_VOLTAGE:
17
      accu_voltage = ADCW;
18
      ADMUX = ADCMUX_CELL_VOLTAGE;
19
      adc_ready = true;
20
      //ADCSRB = (1<<ADTS2); //trigger adc read with timer in sync
21
    break;
22
  }
23
}

https://sebastianfoerster86.wordpress.com/2016/01/02/attiny13-solar-cell-charger-hardware/

: Bearbeitet durch User
(Firma: Gast) #8058144
Lesenswert?

StefanK schrieb:

Er löste die Messung von 4 Spannungen mit dem ADC im Freerunning Modus so:

Bedenklicher Ansatz!

Die Kanalumschaltung in der ISR kommt zu einem undefiniertem Zeitpukt. Also weiß man nicht sicher zu welchem Kanal die nächste Messung gehört. Will man das unterbinden, muss man jede 2te Messung verwerfen. Und damit ist der freerunning Mode nicht mehr die schnellste Variante.

: Bearbeitet durch User
#8058275
Lesenswert?

Die Umschaltung passiert erst nach der Konvertierung. So ist das Ergebnis in der nächsten Isr noch von dem vorher ausgewähltem Kanal / der Konvertierung die lief als die Mux geändert wurde. Unzuverlässig kann das nur werden wenn man einen Int verpasst. Aber dazu müssten andere Isr viel zu lang sein. Oder in der ADC-Isr zu viel passieren bevor der Wert ausgelesen wird ;-)

(Firma: Gast) #8058317
Lesenswert?

Achim H. schrieb:

Die Umschaltung passiert erst nach der Konvertierung. So ist das Ergebnis in der nächsten Isr noch von dem vorher ausgewähltem Kanal / der Konvertierung die lief als die Mux geändert wurde.

Davon ist im dem gezeigten Code nichts zu sehen.

Im Gegenteil! Der Code geht davon aus, dass die Mux Umstellung VOR der S&H Phase, und damit auch vor der Wandlung, stattfindet.

#8058330
Lesenswert?

Arduino F. schrieb:

Im Gegenteil! Der Code geht davon aus, dass die Mux Umstellung VOR der S&H Phase, und damit auch vor der Wandlung, stattfindet.

Das tut es ja auch. Lies mal das Datenblatt.

Beitrag "Re: ADC-Kanäle sukzessive abfragen" Beitrag "Re: ADC-Kanäle sukzessive abfragen"

Ok, ich sehe das Problem, denn ich hatte es auch. Die Zuordnung der Kanäle ist falsch. Denn wenn man in der ISR ADMUX ausliest ist das die aktuell laufende Wandlung aber NICHT das Ergebnis in ADCW. Das ist von der vorhergehenden Wandlung!

#8058345
Lesenswert?

Das einzige was man weiß wenn man in der ISR aufschlägt, ist dass ein IRQ stattgefunden hat. Nach dem Eintreten des IRQ hat man 1,5 ADC Takte Zeit um den MUX für die nächste Messung umzustellen. Ob und wo man sich in diesem schmalen Zeitfenster aufhält weiß man nicht.

Also muss man eine Laufzeit/Reaktionszeit Analyse des kompletten Systems durchführen. Wenn nichts anderes einen IRQ erzeugen kann UND man auch sonst sicher ist, dass kein IRQ temporär /disabled/ wird, ist man bei hohen CPU Taktraten (ADC DIV 64 od. 128) auf der sicheren Seite. Sonst heißt es Zyklen zählen und worst case Szenarien rechnen.

Sobald man auch nur einmal den MUX (unwissentlich) etwas zu spät umschaltet, ist die nächste Messung versaut. Das aber garantiert. ;-)

#8058348
Lesenswert?

Norbert schrieb:

Das einzige was man weiß wenn man in der ISR aufschlägt, ist dass ein IRQ stattgefunden hat. Nach dem Eintreten des IRQ hat man 1,5 ADC Takte Zeit um den MUX für die nächste Messung umzustellen.

Nein! Das ist längst passiert! Das macht der ADC im free run mode selber! Und wenn man den Single shot mode nutzt, ist es egal, denn dann steht der ADC.

Also muss man eine Laufzeit/Reaktionszeit Analyse des kompletten Systems durchführen.

Nö, das wäre ziemlich doof. Ist aber gar nicht nötig.

#8058352
Lesenswert?

Norbert schrieb:

Das macht der ADC im free run mode selber!

Der schaltet selbstständig auf den nächsten Kanal?

Ja.

In welcher Reihenfolge?

Den, der in ADMUX steht. Dahinter liegt ein 2. aus Softwaresicht unsichtbares Register, das beim Start der AD-Wandlung gespeichert wird.

Welche Kanäle? Wo konfigurierbar?

Den nächsten Kanal kann man per ADMUX festlegen, mehr nicht. Siehe mein Link oben, da gibt es vollständige, getestete Software.

OP #8058372
Lesenswert?

Arduino F. schrieb:

Falk B. schrieb:

Die Zuordnung der Kanäle ist falsch.

Richtig!

Das sollte schon klappen. Wenn die ISR kommt, liefert sie den ADC-Wert aus der vorletzten ADMUX Beauftragung. Liest man in dieser ISR ADMUX, erhält man den Kanal der bereits jetzt auto-getriggerten Messung. Wenn man jetzt ADMUX um eins erhöht, passt es. Dann geht ADMUX ggü dem in dieser ISR gelieferten ADC-Wert um genau +2 vor.

In der Main.c muss das schon so vorbereitet werden, wenn der ADC mit Kanal 0 gestartet wird. Dann ADMUX++. Ist verzwickt, aber geht.

: Bearbeitet durch User
OP #8058465
Lesenswert?

Arduino F. schrieb im Beitrag

Genau das ist in deinem zuletzt gezeigten Code falsch. Damit ist der Code kaputt und das Tutorial dramatisch irreführend.

Der Code ist weder kaputt noch irreführend, er funktioniert.

Falk B. schrieb:

Nö, es ist falsch, denn die defines sind dann irreführend!

Selber nö. Seit wann lässt Du Dich so leicht in die Irre führen? Das passt schon, hast Du doch selbst in Deinen Code gezeigt.

Also ich finde die Methode von Sebastian Foerster gut. Sie erzeugt zwar etwas mehr Code, ist aber flexibel und intuitiv. Das hätte ich gern schon vor einem Jahr gewusst. Hätte mir ne Menge Nerven gespart. Übrigens Schreck Gpt beatwortet die Frage nach Freerunning inzwischen mit genau dieser Methode... Mein 👍 hoch für Sebastian.

Angehängte Dateien:
: Bearbeitet durch User
(Firma: 1984now) #8058492
Lesenswert?

StefanK schrieb:

Ob S. schrieb:

Ist ein deutlicher Hinweis, dass KI eigentlich bedeutet: konkurrenzlos inkompentent.

Dem widerspreche ich jetzt mal nicht, bin aber trotzdem gespannt auf Deine Methode. Zeig her!

Wieso, alles was es dazu zu sagen gab ist doch bereits in den einschlägigen Threads gesagt worden. Die korrekte Umsetzung kannst du ja der KI überlassen.

Ähemm... Blöderweise ist die auf Wichsvorlage angewiesen, weil ihr jegliches Verständnis für die Inhalte fehlt. Tja, dumm gelaufen...

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