PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Rechenfehler, Messfehler oder ? ?



oberallgeier
13.11.2018, 14:17
Hallo alle,
ich rechne mich grad krumm mit einer ADC-Frequenz im free running Modus.

Target: nanoclone mit mega328p@20MHz. Ich habe die Platine selbst umgequarzt, bisher ist mir kein Timingfehler aufgefallen (Blinkfrequenz Heartbeat ist 0,500/sec, UART läuft bei 115k2 gut).

Nun programmiere ich den ADC3, free running, Prescaler clk/128. Heraus kommt - Mist. Das DMM (billig, PeakTech 2010) zeigt 6,00 kHz, das Oszilloskop (Gould 1602) zeigt von fallender zu fallender Flanke 0,1670 ms, das ginge ja noch (5,988 kHz). ABER meine Rechnung verwirrt mich total: aus 20 MHz errechne ich mit clk/128 => 156 250 Interrupts pro Sekunde; mit ner getoggelten LED also 78 kHz. Gemessen - siehe oben, Oskar-Flanken mit 5,988 kHz.

Wo bitte mache ich den Fehler ?


// ================================================== =========================== =
// === Initialisierung fuer ADC mega328 MIT Interrupt
// >>>> ATmega328-P_Atmel-42735B_Complete-11-2016; Siehe Seite 308
// .. input clock frequency between 50kHz and 200kHz to get maximum resolution ..
// === ADC3/PC3 auf 10 Bit, Interrupt ausgelöst <=> free running
void ADC3_10_init_irupt(void) //
{
ADMUX |= (1<<MUX1)|(1<<MUX0); // Wandlung mit ADC3 317
ADCSRA |= (1<<ADATE); // Auto Triggering Enable doc S 307 + 319
ADMUX |= (1<<REFS0); // Referenzspannung ist AVcc 317
// AVCC with external capacitor at AREF pin
ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // Prescaler = clock/128 320
// Prescaler NUR für system clck ==> 156 250/sec (78,125 kHz) =>
// Messung ???
ADCSRA |= (1<<ADIE); // ADC Interrupt Enable 319
ADCSRA |= (1<<ADEN); // ADC Enable 319
ADCSRA |= (1<<ADSC); // Free Rung .. to start the first conversion 319
//
adc3_cnt = 0; // ADC-Wert wird x-fach aufaddiert
adc3tcnt = 1; //
adc3_tmp = 0; // ADC-x-fach-Speicher
// mrgl12 = 0b00000000; // Motorregelung 12 ausschalten
// mrgl34 = 0b00000000; // Motorregelung 34 ausschalten
}
// ================================================== ============================ =


// ================================================== ============================ =
// === Nicht unterbrechbare ISR für ADC3 auf Portpin PC3/mega328 ============== =
// Routine übernimmt ADC-Wert und quittiert mit 170 ins Statusbyte.
//
ISR(ADC_vect) // _VECTOR(21)
{ //
// PORTB ^= (1<<PB4); // Zeit/Interruptfrequ: rtLED/PIN PB4 toggeln
adc3tcnt = adc3tcnt + 1;
if (adc3tcnt < 11) return; // Es wird NUR jeder zwölfte ISR-Aufruf gewertet
// - - - - - - - - - - - - - - - -
// ##>> Ab hier ist adc3tcnt >11, hier also 12
adc3tcnt = 1; // adctcnt zurücksetzen auf 1
// - - - - - - - - - - - - - - - -
adc3_tmp = ADC; // Hole Wert
adcs = adc3_tmp; // aktuell ausgelesener Wert wird hier gesichert

Danke für die Aufklärung .

Kann es sein, dass hier noch die eigentliche Wandlungszeit dazu kommt, sodass die nächste Wandlung erst immer gestartet wird, wenn die laufende abgelaufen ist? Sozusagen der Satz in der Dokumentation ".. A normal conversion takes 13 ADC clock cycles. .." ? ? ? Denn damit käme ich auf 156 250/13 - also 12 019 und wäre bei der Blinkfrequenz von 6 kHz :-/

Ceos
13.11.2018, 14:34
Kann es sein, dass hier noch die eigentliche Wandlungszeit dazu kommt, sodass die nächste Wandlung erst immer gestartet wird, wenn die laufende abgelaufen ist? Sozusagen der Satz in der Dokumentation ".. A normal conversion takes 13 ADC clock cycles. .." ? ? ? Denn damit käme ich auf 156 250/13 - also 12 019 und wäre bei der Blinkfrequenz von 6 kHz :-/

ja :)

interrupts gibt es nur wenn ein neuer wert da ist

Moppi
13.11.2018, 18:50
So weit ich zähle, wird aber jeder zehnte und nicht jeder zwölfte ISR-Aufruf gewertet.

adc3tcnt = 1;

adc3tcnt + 1 ; 1. Aufruf (adc3tcnt = 2 )
adc3tcnt + 1 ; 2. Aufruf (adc3tcnt = 3 )
adc3tcnt + 1 ; 3. Aufruf (adc3tcnt = 4 )
adc3tcnt + 1 ; 4. Aufruf (adc3tcnt = 5 )
adc3tcnt + 1 ; 5. Aufruf (adc3tcnt = 6 )
adc3tcnt + 1 ; 6. Aufruf (adc3tcnt = 7 )
adc3tcnt + 1 ; 7. Aufruf (adc3tcnt = 8 )
adc3tcnt + 1 ; 8. Aufruf (adc3tcnt = 9 )
adc3tcnt + 1 ; 9. Aufruf (adc3tcnt = 10 )
adc3tcnt + 1 ; 10. Aufruf (adc3tcnt = 11 )

adc3tcnt = 1;

usw.....



adc3tcnt = adc3tcnt + 1;
if (adc3tcnt < 11) return; // Es wird NUR jeder zwölfte ISR-Aufruf gewertet
// - - - - - - - - - - - - - - - -
// ##>> Ab hier ist adc3tcnt >11, hier also 12
adc3tcnt = 1; // adctcnt zurücksetzen auf 1



MfG
Moppi

Ceos
14.11.2018, 07:59
Für eine in die Zukunft gerichtete Herangehensweise würde ich dazu raten im Code immer von 0 aus zu zählen (und auch so zu rechnen), das fällt einem sonst irgendwann auf die Füße ständig zwischen dem gelernten 1-10 und dem 0-9 das man in der Controllerwelt überall hat umzudenken :)

oberallgeier
14.11.2018, 09:06
Für eine in die Zukunft gerichtete Herangehensweise würde ich dazu raten im Code immer von 0 aus zu zählen (und auch so zu rechnen) ..Danke Ceos, Du hast natürlich voll und ganz Recht. Allerdings ist bei mir die Zukunft schon (fast) angebrochen: der jahrealte Code stammt vom gegenwärtigen Projekt, dem MiniD0 (https://www.roboternetz.de/community/threads/36121-Autonom-in-kleinen-Dosen-R2_D03-Nachfolger-R3D01?p=495507&viewfull=1#post495507) ein bauähnliches Pendant zur Seite zu stellen. Das MiniDöschen (0,15 l Inhalt) hatte ich ja als Variante meines Dotties (https://www.roboternetz.de/community/threads/36121-Autonom-in-kleinen-Dosen-R2_D03-Nachfolger-R3D01?p=343382&viewfull=1#post343382) gebaut (0,33 l - die "normale" Getränkedose), das schon zehn Jahre auf dem Buckel hat. Das MiniD0 ist auch schon sieben Lenze alt und war damals entstanden als Fortführung über mehrere Stufen (https://www.roboternetz.de/community/threads/36121-Autonom-in-kleinen-Dosen-R2_D03-Nachfolger-R3D01?p=366429&viewfull=1#post366429), einem Balance-Dingelchen (https://www.roboternetz.de/community/threads/36121-Autonom-in-kleinen-Dosen-R2_D03-Nachfolger-R3D01?p=411236&viewfull=1#post411236) und so mit nem Ausflug in einen Geräteträger (https://www.roboternetz.de/community/threads/36121-Autonom-in-kleinen-Dosen-R2_D03-Nachfolger-R3D01?p=369014&viewfull=1#post369014) zum Geschwindigkeitstest der Halb-Rundum-Sensorik (https://www.roboternetz.de/community/threads/36121-Autonom-in-kleinen-Dosen-R2_D03-Nachfolger-R3D01?p=382774&viewfull=1#post382774) entstanden.

Mittlerweile ist am MiniD0 fast alles veraltet und soll überarbeitet, nee, modernisiert werden. Inclusive der alten Programmierung in C(ähhh). Und da tun sich tiefe (Wissens-) Stufen auf. Ich arbeite daran.