mikrocontroller.net

Forum: Compiler & IDEs Warum funktioniert das nicht? Mittelwert, AD_wandler


Autor: Dirk S. (fusebit)
Datum:

Bewertung
0 lesenswert
nicht 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...
//TLC4545 Ansteuerung
int adc(void)
{
  unsigned int abfrage;
  //unsigned long int summe;
  
  //for(int k=0;k<64;k++)
  //{
    CLRBIT(PORTD,5);            //CS auf 0
    
    for(int i=0;i<16;i++)
    {
      SETBIT(PORTD,7);          //CLK auf 1
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      CLRBIT(PORTD,7);          //CLK auf 0
      abfrage=(abfrage<<1);
      asm volatile ("nop");
      if (bit_is_set(PIND,6)) abfrage|=1;  //DATA abfragen
    }
    SETBIT(PORTD,5);            //CS auf 1
    //summe = summe + (unsigned long int) abfrage;
    //abfrage=0;
  //}
  //abfrage = (unsigned int) (summe/64);
  
  //summe=0;
  return(abfrage);
}


So funktioniert es, wenn ich das rauskommentierte aktiviere ergibt es 
Blödsinn :-(

Autor: Magnus Müller (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: pumpkin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

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

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

pumpkin

Autor: Magnus Müller (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh shit... hab mich da im Code vertan... Du summierst ja 64 
"abfrage"-Werte a 16Bit... mein Fehler ;)

Autor: Dirk S. (fusebit)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schreib doch mal Deine gemessenen Werte in ein Array und sieh Dir den 
Inhalt dieses Arrays an - vielleicht erkennst Du dann, woran es bei der 
Mittelwertbildung scheitert.

Autor: pumpkin (Gast)
Datum:

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

// ...

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

Autor: Magnus Müller (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)
//TLC4545 Ansteuerung
int adc(void)
{

Gruß,
Magnetus

Autor: Dirk S. (fusebit)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Das ist ein TLC4545, 200 kSPS.

Der AVR läuft mit 8 MHz, wie bekomme ich denn raus wie lange der AVR für 
das aufsummieren benötigt? Das muss ich wohl mal das genaue Timing 
zwischen den Wandlungen berechnen...

Autor: pumpkin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Magnus Müller (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du solltest dir das Datenblatt nochmal genauer ansehen. Speziell ab 
Seite 12 "Principles of Operation". Siehe Anhang.
sampling

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

conversion

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

For all devices, the SDO data presented during a cycle is the result of
the conversion of the sample taken during the previous cycle. The
output data format is shown in the following table.

Autor: pumpkin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gibt's eigentlich einen Grund, warum du nicht die SPI-Hardware
benutzt?

Je nach Taktfrequenz kann 3 µs lang genug sein, als dass es sich lohnt,
das nächste Auslesen mit einem Timer anzustoßen.

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Initialisierung
  summe = 0;
sollte am Anfang der Routine stehen, nicht am Ende. Dort ist sie 
unwirksam.

Autor: pumpkin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Dirk S. (fusebit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank erstmal! Ich werde mal ein paar nops einfügen und sehen ob 
es klappt.

Leider muss ich wohl erstmal den SMD-Mega auslöten und ersetzen, er wird 
plötzlich nicht mehr erkannt und das obwohl ich nichts an den Fuses 
gemacht habe. So ein Mist...

Autor: Frank Jonischkies (frajo)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Dirk S. (fusebit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kurze Rückmeldung:

Manchmal hilft halt Däumchendrehen. Ein paar Nopse eingefügt und schon 
stimmt der Wert.

Die 32 addiere ich jetzt auch noch hinzu.


Vielen Dank an Alle...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.