Ich hätte es anders aufgezogen.
Denn: da gehören immer ein paar Dinge zusammen.
Kanalnummer, die Samples selber und die Stelle an die der nächste Sample
zu schreiben ist bilden eine logische Einheit. Diese 3 Informationen
gehören zusammen, so wie bei einem Geburtstag der Tag, Monat und Jahr
zusammengehören. Die Einheit aus Tag, Monat und Jahr nennt man ein
Datum. Hier in deinem Fall gibt es keine übliche Bezeichnung dafür, was
dich aber nicht daran hindern soll dir eine zu definieren. Nennen wie
sie einfach mal eine "Messung".
Also definiere ich mir eine derartige Struktur
1 | struct messung_
|
2 | {
|
3 | uint8_t ADKanal;
|
4 | uint8_t nextSample;
|
5 | uint816_t ADSamples[NR_SAMPLES];
|
6 | };
|
Gut.
Von diesen 'Messungen' hast du 6 Stück
1 | struct messung_ Messungen[NR_MEASUREMENTS];
|
und bei jedem Aufruf der ADC Routine übergibst du einen Pointer auf die
jeweils aktuelle 'Messung' die fortgeführt werden soll.
1 | uint16_t AD_read( struct messung_* pMessung )
|
2 | {
|
3 | uint16_t value;
|
4 | uint16_t middle;
|
5 | uint8_t i;
|
6 |
|
7 | // welcher AD Kanal?
|
8 | ADMUX = ADMUX + pMessung->ADKanal;
|
9 | ADCSRA |= (1<<ADSC);
|
10 | while (ADCSRA & (1<<ADSC) )
|
11 | {}
|
12 |
|
13 | value = ADCW;
|
14 |
|
15 | // Kanal wieder rausnehmen, damit ADMUX 'sauber' bleibt
|
16 | ADMUX = ADMUX - pMessung->ADKanal;
|
17 |
|
18 |
|
19 | // Messung in die Samples einpflegen
|
20 | pMessung->nextSample++;
|
21 | if( pMessung->nextSample == NR_SAMPLES )
|
22 | pMessung->nextSample = 0;
|
23 |
|
24 | pMessung->ADSamples[ pMessung->nextSample ] = value;
|
25 |
|
26 |
|
27 | // Mittelwert ausrechnen
|
28 | middle = 0;
|
29 | for( i = 0; i < NR_SAMPLES; i++ )
|
30 | {
|
31 | middle += pMessung->ADSamples[i];
|
32 | }
|
33 | middle /= NR_SAMPLES;
|
34 |
|
35 | return middle;
|
36 | }
|
(benutz lokale Variablen, wenn es nicht viele sind und sie tatsächlich
nur lokale Bedeutung haben!)
und in main gibst du dann von deinen 6 'Messkanälen', die du korrekt
Initialisiert hast, zb auf die ADC Kanäle 0, 1, 3, 4, 5 und 7
1 | struct messung_ Messungen[NR_MEASUREMENTS] =
|
2 | { { 0, 0, { 0 } },
|
3 | { 1, 0, { 0 } },
|
4 | { 3, 0, { 0 } },
|
5 | { 4, 0, { 0 } },
|
6 | { 5, 0, { 0 } },
|
7 | { 7, 0, { 0 } }
|
8 | };
|
einen nach dem anderen auf die ADC Routine
1 | int main()
|
2 | {
|
3 |
|
4 | ...
|
5 |
|
6 | nrMeasurement = 0;
|
7 |
|
8 | while( 1 )
|
9 | {
|
10 |
|
11 | nrMeasurement++;
|
12 | if( nrMeasurement == NR_MEASUREMENTS )
|
13 | nrMeasurement = 0;
|
14 |
|
15 | value = AD_read( &Messungen[nrMeasurement] );
|
16 |
|
17 | ...
|
18 | }
|
19 | }
|
die Funktion AD_read findet in der übergebenen Struktur (die Struktur
wird in Form eines Pointers drauf übergeben) alles vor, was sie benötigt
um die Messung durchzuführen und das Ergebnis korrekt einzuordnen.
Und wenn du auf unterschiedlichen ADC-Kanälen unterschiedliche Anzahl an
Samples zum Mittelwert zusammenfassen willst, dann ist auch das einfach
möglich. Du erweiterst einfach die Struktur, so dass auch diese
Information enthalten ist
1 | struct messung_
|
2 | {
|
3 | uint8_t ADKanal;
|
4 | uint8_t nextSample;
|
5 | uint8_t nrSamples;
|
6 | uint816_t ADSamples[NR_SAMPLES];
|
7 | };
|
erweiterst die Funktion, so dass sie diese INformation benutzt, anstelle
der Konstanten
1 | uint16_t AD_read( struct messung_* pMessung )
|
2 | {
|
3 | uint16_t value;
|
4 | uint16_t middle;
|
5 | uint8_t i;
|
6 |
|
7 | // welcher AD Kanal?
|
8 | ADMUX = ADMUX + pMessung->ADKanal;
|
9 | ADCSRA |= (1<<ADSC);
|
10 | while (ADCSRA & (1<<ADSC) )
|
11 | {}
|
12 |
|
13 | value = ADCW;
|
14 |
|
15 | // Kanal wieder rausnehmen, damit ADMUX 'sauber' bleibt
|
16 | ADMUX = ADMUX - pMessung->ADKanal;
|
17 |
|
18 |
|
19 | // Messung in die Samples einpflegen
|
20 | pMessung->nextSample++;
|
21 | if( pMessung->nextSample == pMessung->nrSamples )
|
22 | pMessung->nextSample = 0;
|
23 |
|
24 | pMessung->ADSamples[ pMessung->nextSample ] = value;
|
25 |
|
26 |
|
27 | // Mittelwert ausrechnen
|
28 | middle = 0;
|
29 | for( i = 0; i < pMessung->nrSamples; i++ )
|
30 | {
|
31 | middle += pMessung->ADSamples[i];
|
32 | }
|
33 | middle /= pMessung->nrSamples;
|
34 |
|
35 | return middle;
|
36 | }
|
und erweiterst die Messungen selber, so dass du angibst, wieviele
Samples zu nehmen sind.
1 | struct messung_ Messungen[NR_MEASUREMENTS] =
|
2 | { { 0, 10, 0, { 0 } },
|
3 | { 1, 15, 0, { 0 } },
|
4 | { 3, 3, { 0 } },
|
5 | { 4, 19, { 0 } },
|
6 | { 5, 20, { 0 } },
|
7 | { 7, 8, { 0 } }
|
8 | };
|
Im Moment gibt es noch eine Einschränkung, dass du keine größere Zahl an
Samples angibst als das Array groß ist. Aber auch dieses 'Problem'
könnte man noch lösen.
Codeorganisation und Datenstrukturen sind kein Selbstzweck, sondern
bringen dir sauberen Code, der auch flexibel sind. Aber dazu muss man
sein C kennen. Arrays sind gut, aber sie sind bei weitem nicht die
einzige Möglichkeit um Struktur in Daten reinzubringen. Ganz im
Gegenteil.