www.mikrocontroller.net

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


Autor: Holgie (Gast)
Datum:

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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

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

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Siehe Interrupt.

Autor: Holgie (Gast)
Datum:

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


}

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.