Warum funktioniert das nicht? Mittelwert, AD_wandler

OP #579126
Lesenswert?

Moin Leute,

ich komme mit meinem Code nicht auf einen grünen Zweig. Wenn die Abfrage 
des AD-Wandlers nur einmal durchläuft, dann bekomme ich einen sinnvollen 
und schwankenden Wert. Daher möchte ich einige Werte mitteln, aber das 
klappt einfach nicht. Dann bekomme ich falsche Werte...
1
//TLC4545 Ansteuerung
2
int adc(void)
3
{
4
  unsigned int abfrage;
5
  //unsigned long int summe;
6
  
7
  //for(int k=0;k<64;k++)
8
  //{
9
    CLRBIT(PORTD,5);            //CS auf 0
10
    
11
    for(int i=0;i<16;i++)
12
    {
13
      SETBIT(PORTD,7);          //CLK auf 1
14
      asm volatile ("nop");
15
      asm volatile ("nop");
16
      asm volatile ("nop");
17
      asm volatile ("nop");
18
      asm volatile ("nop");
19
      asm volatile ("nop");
20
      asm volatile ("nop");
21
      asm volatile ("nop");
22
      asm volatile ("nop");
23
      CLRBIT(PORTD,7);          //CLK auf 0
24
      abfrage=(abfrage<<1);
25
      asm volatile ("nop");
26
      if (bit_is_set(PIND,6)) abfrage|=1;  //DATA abfragen
27
    }
28
    SETBIT(PORTD,5);            //CS auf 1
29
    //summe = summe + (unsigned long int) abfrage;
30
    //abfrage=0;
31
  //}
32
  //abfrage = (unsigned int) (summe/64);
33
  
34
  //summe=0;
35
  return(abfrage);
36
}

So funktioniert es, wenn ich das rauskommentierte aktiviere ergibt es 
Blödsinn :-(
Gast #579133
Lesenswert?

Du summierst 16 "abfrage"-Werte und teilst die Summe dann durch 64? Du 
solltest mal versuchen durch 16 zu teilen.

By the way: kannst du "Blödsinn" etwas näher definieren?

Gruß,
Magnetus
Gast #579136
Lesenswert?

Hallo,

dein Rückgabetyp der Funktion adc() ist nicht unbedingt kompatibel zu 
deiner Rechnung:
1
unsigned int adc(void) { /*...*/ }

Manchmal funktioniert das, manchmal nicht. Wie äußert sich 'Blödsinn' 
denn genau?

pumpkin
OP #579138
Lesenswert?

@Magnus
Nein, weiter oben ist die 64er Schleife. Die 16er Schleife ist das 
Bitweise abfragen des ADC.

@pumpkin
Das werde ich mal ändern!

Definition Blödsinn:
Der ausgegeben Wert ist deutlich zu hoch. Es liegt von Drucksensor etwa 
4,03 V an. Mit einfacher Wandlung passt der Wert sehr gut. Mit 
Mittelwertbildung liege ich bei 4,2 V.
Gast #579144
Lesenswert?

Mmmmh, ist schwierig zu sagen. Mein Gedanke ist z.Zt., dass der Wandler 
evtl. etwas zu schnell beackert wird:
1
CLRBIT(PORTD,5);            //CS auf 0
2
    
3
for(int i=0;i<16;i++)
4
{
5

6
// ...

Du sagst 'wandle!' und holst sofort deine Daten ab. Was für einen 
Wandler nutzt du (Flash, Sigma-Delta, Approx, ...)? Deine 
Shiftregisterkonstruktion scheint ja zu funktionieren.

pumpkin
Gast #579148
Lesenswert?

> Du sagst 'wandle!' und holst sofort deine Daten ab. Was für einen
> Wandler nutzt du (Flash, Sigma-Delta, Approx, ...)? Deine
> Shiftregisterkonstruktion scheint ja zu funktionieren.

Er benutzt scheinbar einen TLC4545 (siehe Beginn des Codes)
1
//TLC4545 Ansteuerung
2
int adc(void)
3
{

Gruß,
Magnetus
Gast #579153
Lesenswert?

Ok, hab' es nicht gesehen. Das Datenblatt sagt ~17ns nach /CS und ~3µs 
conversion time. Guck dir mal das datasheet auf Seite 12 (conversion) 
an. Dort wird beschrieben wie man ungültige Ergebnisse erkennt.

pumpkin
Gast #579155
Lesenswert?

Du solltest dir das Datenblatt nochmal genauer ansehen. Speziell ab 
Seite 12 "Principles of Operation". Siehe Anhang.
1
sampling
2

3
The converter sample time is 20 SCLKs in duration, beginning on the 5th
4
SCLK received during an active signal on the CS input (or FS input for
5
the TLC4541.)
6

7
conversion
8

9
Each device completes a conversion in the following manner. The
10
conversion is started after the 24th falling SCLK edge. The CS input
11
can be released at this point or at any time during the remainder of
12
the conversion cycle. The conversion takes a maximum of 2.94 μs to
13
complete. Enough time (for conversion) should be allowed before the
14
next falling edge on the CS input (or rising edge on the FS input for
15
the TLC4541) so that no conversion is terminated prematurely. If the
16
conversion cycle is terminated early, the data presented on SDO during
17
the following cycle is FF00h. This predefined output code is helpful in
18
determining if the cycle time is not long enough to complete the
19
conversion. The same code is also used to determine if a reset cycle
20
is valid.
21

22
For all devices, the SDO data presented during a cycle is the result of
23
the conversion of the sample taken during the previous cycle. The
24
output data format is shown in the following table.
Gast #579156
Lesenswert?

>> Der AVR läuft mit 8 MHz, wie bekomme ich denn raus wie lange der AVR für
>> das aufsummieren benötigt?

Im Debug kannst du dir die clock cycles anschauen (irgendwo linkes 
Fenster, Unterpunkt CPU wenn ich mich recht entsinne). Eine 'Stoppuhr' 
ist auch eingebaut, aber die braucht das richtige #define F_CPU (auch im 
makefile?!?).

pumpkin
Gast #579177
Lesenswert?

Habe es gerade einmal durchgerechnet. Angenommen du verwendest das 
fehlerhafte Wort 0xFF00 63 mal zur Mittelwertbildung, dann rutscht dein 
Wert gegen ~4,95V (Referenz 5V). Wahrscheinlich sind nicht alle Werte 
fehlerhaft, so dass dein leicht erhöhter Wert plausibel scheint. Ist nur 
eine Möglichkeit, aber die würde ich erstmal abklopfen.

pumpkin
#579258
Lesenswert?

Wenn Du 64 Messungen aufsummierst und dann durch 64 dividierst 
vergrößerst Du den Fehler. Das nieder-niederwertigste Bit (das unter 
Bit0) könnte bei jeder Messung 0 oder 1 sein da der zu messende Wert ja 
analog vorliegt. Statistisch gesehen also 32 mal 0 und 32 mal 1. Addiere 
vor der Division durch 64 noch die Hälfte der Anzahl der Messungen (32), 
und Du gleichst diesen Fehler wieder aus.

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