Forum: Compiler & IDEs analoge Messwerte einlesen und speichern, Anfängerproblem


von Holgie (Gast)


Lesenswert?

Hallo zusammen,
Ich habe ein Problem beim Abspeichern von Messwerten. Ich habe ein Array 
definiert und möchte in einer ForNext Schleife die Werte des 
Analog/Digitalwandlers einlesen und in dem Array speichern
if (c[1] == 50)
{
PORTD |= (1<<PD3);
for (j=0;j<250;j++)
{
c[j] = ADCH;
}
}
Wenn ich die Werte dann auslese sind alle 250 Messwerte gleich (51) 
obwohl sich die Spannung beim Messen geändert hat. Aufgrund der 
If-Anweisung fange ich erst ab Wert50 an zu speichern. Funktioniert das 
Einlesen mittels For Next Schleife nicht? Untenstehend noch das 
komplette Programm.
Danke für Eure HIlfe.
Gruß
Holger

#define  PROZESSORTAKT  3680000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include "rs232.h"



/* ==== INTERRUPT HANDLER: ADC Conversion Complete === */
SIGNAL (ADC_vect)
{
//  unsigned char c;
unsigned char c[250];
  char temp[5];
  int j,i;
PORTD |= (1<<PD2); //Pull up von PD2 einschalten
DDRD &= ~ (1<<PD2); // PD2 als Eingang
DDRD = (1<<PD3)| (1<<PD4); // Pin D3 und D4 als Ausgang

  // ADC Resultat einlesen =======================

  c[1] = ADCH; /* Nur ADCH lesen, weil 8-Bit Modus */

if (c[1] == 50)
{
PORTD |= (1<<PD3);
for (j=0;j<250;j++)
{
c[j] = ADCH;
}
}
  // ADC Resultat auf RS232 ausgeben ============/

if (!(PIND & (1<<PIND2)))
{
PORTD |= (1<<PD4);
for (i=0;i<250;i++)
{

    itoa(c[i], temp, 10); /* In einen String konvertieren ... */

  uart_putchar('\n');
    uart_putstring(temp);

  }
  }
}




int main(void)
{
  /* RS232 einschalten ...*/
  setup_uart();
  uart_putline("[ EasyADC -- www.avrbuch.de ]");

  // Alle Interrupts erlauben
  sei();

  // ADC, 8-Bit im Free Running Mode mit Interrupt
  // Referenzspannung: VCC
  // Takt: Systemtakt / 2 (4 MHz bei 8Mhz Quarz)
  ADMUX = (1<<REFS0) | (1<<ADLAR);
  ADCSRA = (1<<ADEN) | (1<<ADFR) | (1<<ADIE);

  // ADC starten!
  ADCSRA |= (1<<ADSC);

  // Endlosschleife
  while (1) ;

  return 0;
}

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Was willst du wirklich machen? Sicher nicht das komplette Programm im 
SIGNAL (ADC_vect) laufen lassen...

Ich könnte mir vorstellen:

250 ADC Werte sollen so schnell wie möglich in einen Puffer eingelesen 
werden. Wenn der Puffer voll ist, sollen die Werte mit RS232 ausgegeben 
werden. In der Ausgabezeit werden keine neuen Messwerte ermittelt. Nach 
der Ausgabe werden die nächsten 250 Werte genommen.

von Karl H. (kbuchegg)


Lesenswert?

Holgie schrieb:
> Hallo zusammen,
> Ich habe ein Problem beim Abspeichern von Messwerten. Ich habe ein Array
> definiert und möchte in einer ForNext Schleife die Werte des
> Analog/Digitalwandlers einlesen und in dem Array speichern
> if (c[1] == 50)
> {
> PORTD |= (1<<PD3);
> for (j=0;j<250;j++)
> {
> c[j] = ADCH;
> }
> }
> Wenn ich die Werte dann auslese sind alle 250 Messwerte gleich (51)

Yep.
Genau das hast du programmiert.

> obwohl sich die Spannung beim Messen geändert hat.

Das ist aber dem ADCH egal.
Einmal ADC starten -> ein Messwert
Willst du den nächsten Messwert, musst du den ADC erbeut sampeln lassen.
Insbesondere solltest du beachten, dass du hier mitten in einer ISR 
steckst. Damit teilt dir der ADC mit, dass er den nächsten Messwert 
fertig hat. Und in deiner Schleife speicherst du diesen einen Messwert 
quer über dein Array. Logisch haben dann alle Elemente im Array 
denselben Wert.

Ehe du dich da mit dem ISR verfranst: Wie wäre es, wenn du erst mal ganz 
einfach die ADC Routine aus dem Tutorial verwendest? Damit bist du ein 
klein wenig näher an deiner for-Schleifen Denkweise.

In einer ISR muss man nämlich anders vorgehen. Das ist ungefähr so, wie 
wenn du in einem Raum sitzt und ab und an schaut dein Kumpel bei der Tür 
rein und ruft dir eine Zahl zu (den ADC Messwert) und du musst auf diese 
eine Zahl reagieren. (Dein Code macht das Äquivalent zu: Du schreibst 
diese Zahl 250 mal auf, erklärst das zum Ergebnis und wunderst dich, 
dass alle 250 Ergebnisse gleich sind)
In dieser Situation würdest du anders vorgehen. Wenn dein Kumpel dir 
eine Zahl zuruft und wieder verschwindet, dann schreibst du diese eine 
Zahl am Ende einer Tabelle dazu. Du zählst mit, wieviele Zahlen dir dein 
Kumpel bisher genannt hat und wenn es 250 waren, dann erklärst du die 
Tabelle für vollständig und verlautbarst das Ergebnis.

von Falk B. (falk)


Lesenswert?

Siehe Interrupt.

von Holgie (Gast)


Lesenswert?

Schönen guten Abend zusammen,
ich wollte mich noch für die tollen Antworten besonders von Hr. 
Buchegger bedanken. Damit hab ich es nun geschafft und gerade mein 
großes Erfolgserlebniss gehabt. So macht die Sache echt Spass.
Viele Grüße und macht weiter so!!
Gruß
HOlger

Untenstehend noch das auf dem Atmega 8 funktionierende Programm.


define  PROZESSORTAKT  3680000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include "rs232.h"

   unsigned char c[500];
   char temp[5];
   int j,i;


/* ==== INTERRUPT HANDLER: ADC Conversion Complete === */
    //    SIGNAL (ADC_vect)
      // {
      //  }
  // ADC Resultat einlesen =======================
ISR(ADC_vect)
{
    // user code here


        c[j] = ADCH; /* Nur ADCH lesen, weil 8-Bit Modus */

           if (j<500)
           {
           j++;
           }

        }






int main(void)
   {

   PORTD |= (1<<PD2); //Pull up von PD2 einschalten
   DDRD &= ~ (1<<PD2); // PD2 als Eingang
   DDRD = (1<<PD3)| (1<<PD4); // Pin D3 und D4 als Ausgang


      /* RS232 einschalten ...*/
      setup_uart();
      uart_putline("[ EasyADC -- www.avrbuch.de ]");

      // Alle Interrupts erlauben
      sei();

      // ADC, 8-Bit im Free Running Mode mit Interrupt       // 
Referenzspannung: VCC

      // Takt: Systemtakt / 2 (4 MHz bei 8Mhz Quarz)
      ADMUX = (1<<REFS0) | (1<<ADLAR);
      ADCSRA = (1<<ADEN) | (1<<ADFR) | (1<<ADIE) | (1<<ADPS2)| 
(1<<ADPS1)| (1<<ADPS0);

      // ADC starten!
      ADCSRA |= (1<<ADSC);

          // Endlosschleife
          while (1)

          // ADC Resultat auf RS232 ausgeben ============/

          if (!(PIND & (1<<PIND2)))

             {
             PORTD |= (1<<PD4);
                for (i=0;i<500;i++)
                {

                itoa(c[i], temp, 10); /* In einen String konvertieren 
... */

                uart_putchar('\n');
        uart_putchar ('\r');
                uart_putstring(temp);

                }
        j = 0;
             }


}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.