mikrocontroller.net

Forum: Compiler & IDEs ADC Messung beim ATTiny13 Problem


Autor: Christof Kauba (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, ich will mit einem Tiny13 per ADC eine Spannung messen, die ich 
dann proportional als Blinkfrequenz eines LEDs ausgeben möchte.
Dazu habe ich folgenden Code geschrieben:
#define F_CPU 1200000UL     // Quarz mit 1,2 Mhz (interner Oszillator)

#include <avr/io.h>        // Library für Hardwaredefinitionen etc.
#include <avr/interrupt.h>    // Definitionen für Interruptroutinen
#include <avr/signal.h>      // Interruptroutinen 2
#include <stdint.h>        // Integer Datentypen
#include <util/delay.h>      // Verzögerungsschleifen



// Funktionen:

uint16_t Messung(void);    //ADC Messung


// Variablen:

uint16_t rfsignal = 0;
uint8_t counter = 0;
uint8_t compare = 0;


// Hauptprogramm:

int main (void)
{
  
  // Timer initialisieren:

  TIMSK0 &= ~((1<<TOIE0)|(1<<OCIE0A)|(1<<OCIE0B));       //Interrupts für Timer 0 deaktivieren
  
  TCCR0A = 0x00;
  TCCR0B |= (1<<CS01) | (1<<CS00);              //Takt = CPU-Takt/64
  TCNT0 = 0x00;
  
  TIMSK0 |= (1<<TOIE0);       //set 8-bit Timer/Counter0 Overflow Interrupt Enable
  
  sei();            // set the Global Interrupt Enable Bit
  
  set_sleep_mode(SLEEP_MODE_IDLE);
  
  
  // Initialisierung Ports:

  DDRB |= (1<<PB0);
  

  PORTB |= (1<<PB0);
  
  while(1)
  {
    rfsignal = Messung();
    
    compare = (rfsignal * (-2517L))/10000L + 125;
      
    if (counter >= compare)
    {    
      PORTB ^= (1<<PB0);      //Port B, Pin 0 toggeln (LED blinkt)
      counter = 0;
    }
    
    sleep_mode();
  }
}



SIGNAL(SIG_OVERFLOW0)      //overflow interrupt vector
{
  counter++;
}


// ADC Funktion:
  
uint16_t Messung (void)     //Methode zum Messen mittels ADC und errechnen des Messwertes
{            

  uint16_t result = 0;    //Messergebnis
  
  ADCSRA |= (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);    //Initialiserung ADC, Frequenzteiler: 8
  ADMUX = 0x03;                    //Zu verwendender Pin, ADC3
  
                            //Versorgungsspg. als Referenz

  
  //Dummy-Messung zwecks ADC Initialisierung bzw. nach Referenzspannungswechsel
  
  ADCSRA |= (1<<ADSC);           // eine ADC-Wandlung
  while(!(ADCSRA & (1<<ADIF)));       // auf Abschluss der Konvertierung warten (ADIF-bit)
  ADCSRA |= (1<<ADIF);           // ADIF löschen
  
  // Eigentliche Messung
 
  ADCSRA |= (1<<ADSC);         // eine Wandlung "single conversion"
  while(!(ADCSRA & (1<<ADIF)));     // auf Abschluss der Konvertierung warten (ADIF-bit)
  result = ADCW;             // Wandlungsergebnis
  ADCSRA |= (1<<ADIF);         // ADIF löschen
  
  ADCSRA &= ~(1<<ADEN);           // ADC deaktivieren (2)
  ADMUX = 0x00;              // ADMUX löschen
  
  return result;              // Rückgabewert der Funktion = Messwert
}

Mein Problem ist, dass egal wie groß das Eingangssignal ist (liegt 
zwischen 1 und 2,5V), die LED immer gleich schnell blinkt, und zwar so 
schnell, als wäre der Wert rfsignal = 0 (als meiner Meinung nach, obwohl 
ich die Blinkfrequenz nicht genau nachgemessen habe).

Es muss fast an der ADC Funktion liegen (diese habe ich aus dem AVR GCC 
Tutorial), da ich bereits probiert habe in meine Formel statt der 
Variable rfsignal Werte einzusetzen und da hat alles wunderbar geklappt.

Mache ich bei der Messung irgendetwas falsch?
Zur Info, ich verwende den Pin ADC3 als Eingang und die LED hängt an 
PB0.

Ich habe auch schon probiert, den sleep Modus wegzulassen, dies ändert 
aber nichts.

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

Bewertung
0 lesenswert
nicht lesenswert
Christof Kauba wrote:
>
>   ADCSRA |= (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);    //Initialiserung
> ADC, Frequenzteiler: 8
>   ADMUX = 0x03;                    //Zu verwendender Pin, ADC3
>
>                             //Versorgungsspg. als Referenz

Denke mal, dass das beim Tiny ähnlich ist. Bei den Megas
ist es so, dass kein REF Bit gesetzt externe Referenz bedeutet.
Wenn du also an ARef nichts angeschlossen hast, dann ist deine
Referenz auf 0.

Schau aber zur Sicherheit noch mal ins Datenblatt des Tiny.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Tiny13 kann keine externe Referenz. REFS = 0 ist VREF = VCC. Müsste 
also zumindest was Sinnvolles rauskommen.

@Christof:
Was soll denn die Multiplikation mit -2517 bewirken? Ist mir grad etwas 
schleierhaft...

Und counter ist nicht volatile deklariert, wird aber in ISR und 
Hauptprogramm verwendet. Außerdem sollte SIGNAL (und auch die signal.h) 
nicht mehr verwendet werden. Ist veraltet.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Was soll denn die Multiplikation mit -2517 bewirken?

compare = 125 - 0.2517*rfsignal
Ich schätze mal, je größer die Spannung umso kleiner die compare-Zeit, 
damit das Blinken schneller wird ?!

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan wrote:
>>Was soll denn die Multiplikation mit -2517 bewirken?
>
> compare = 125 - 0.2517*rfsignal
Autsch, ja klar, jetzt läutet es...

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Autsch, ja klar, jetzt läutet es...
ja, ich hör's ;-)

Autor: Jan R. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Christof,

Problem noch aktuell?

Zufällig hab ich was mit 'nem ATtiny13 gemacht und konnte es mal eben 
hier ausprobieren. Und bei mir funktioniert dein Programm einwandfrei.

Lass mich raten: Du machst das alles mit einem STK500. Und um dort einen 
ATtiny13 zu programmieren muss man 2. "Drähte verlegen".
Und der eine geht von  XT1 auf PB3. XT1 gibt ständig das Clocksignal 
raus.
Zieh die Verbindung mal ab so das auch nur deine zu messende Spannung an 
PB3 anliegt. Sollte dann funktionieren.

Gruß, Jan

Autor: Christof Kauba (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ja das Problem ist noch aktuell.
Nein ich verwende kein STK500, sondern eine selbstgeabute Schaltung.
Ja laut Datenblatt des ATTiny13 kann er nur die interne Referenzspannung 
von 1,1V oder die Versorgungsspannung als Referenz verwenden.

Das Programmieren funktioniert einwandfrei (ich verwende PonyProg).

Autor: Christof Kauba (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Außerdem ist mir gerade aufgefallen, dass eigentlich statt
#include <avr/signal.h>      // Interruptroutinen 2
#include <avr/sleep.h>      // Library für Sleep-Modes

stehen sollte. Muss mir wohl ein Fehler beim Kopieren unterlaufen sein.

Muss ich die variable counter unbedingt als volatile deklarieren?
Denn wie gesagt, wenn ich statt rfsignal einen fixen Wert verwende, 
funktioniert das Ganze.

Autor: Jan R. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Das Programmieren funktioniert einwandfrei (ich verwende PonyProg).

ne, ja, nein, doch - ich hab mich vielleicht falsch ausgedrückt. ALLES 
funktioniert bei mir. also die LED blinkt hier proportional zur spannung 
mit genau dem oben gepasteten programm!

am programm liegt es ja dann wohl nicht. dann zeig bitte mal den 
schaltplan.

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

Bewertung
0 lesenswert
nicht lesenswert
Christof Kauba wrote:

> Muss ich die variable counter unbedingt als volatile deklarieren?

Schaden kann es auf keinen Fall.

> Denn wie gesagt, wenn ich statt rfsignal einen fixen Wert verwende,
> funktioniert das Ganze.

Ich würde mal folgenden Versuch machen.
Nur den ADC auslesen und das Ergebnis auf ein paar Leds ausgeben
(je mehr desto besser). Dann ein Poti an den ADC und schauen ob
sich an den LED was tut. Damit möchte ich feststellen, ob vom
ADC überhaupt irgendein Wert daherkommt, der ADC also grundsätzlich
funktioniert, oder ob der Wert erst danach irgendwo versickert.

Offensichtlichen Fehler seh ich sonst keinen im Programm und
Jan hat auch gepostet, dass es bei ihm funktionieren würde.

Vielleicht ist es ja auch was ganz Banales wie: den falschen Pin
am Tiny erwischt.

Autor: Christof Kauba (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schaltplan hab ich jetzt so nicht explizit gezeichnet.
Wie schon erwähnt ist die Spannung (Ausgang eines Funkempfängers) auf 
dem ADC3 Pin angschlossen, und die LED an PB0 und über einen 470 Ohm 
Widerstand zu GND.
Ansonsten ist eigentlich nichts angschlossen, außer ein 100 nF 
Kondensator zwischen Vcc und GND.

Ich messe am ADC Eingang eine Spannung von 2V, wenn ich ein Signal 
empfange, und wenn ich keines empfange, bzw eigentlich wenn ich keines 
sende messe ich immer noch 1,3V auf Grund von Störsignalen, die das 
Modul empfängt.
Aber die Blinkfrequenz ändert sich nicht.

Hast du genau die gleichen Pins verwendet?

Autor: Christof Kauba (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, ich glaube ich habe den Fehler gefunden.
Mein Tiny13 dürfte hardwaremäßig nicht in Ordnung sein, ich habe es 
jetzt mit einem anderen Tiny13 getestet und da funktioniert alles 
einwandfrei.

Autor: Jan R. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmmmm...

Da ich hier grad ein STK500, einen Tiny13, ein JTAG ICE MKII und eine 
LED liegen hatte dachte ich mir ich schau mal nach.

- Tiny13 in STK500
- JTAG ICE MKII dran
- Dein Programm über GNU Plug-In, Copy-Paste in AVR Studio
- LED und externe DC Spannungsquelle an GENAU DIE SELBEN Pins
- Programm rein, JTAG loslaufen gelassen und an der Spannung gedreht.
- Mit steigender Spannung wächst die Blinkfrequenz

(wie gesagt, außer das es zuerst nicht ging weil XT1 noch an PB3 hing)

Vielleicht ist die Ausgangsfrequenz deines Funkempfängers ja die gleiche 
wie die Abtastung deines ADC ;-)

Ne, bin jetzt grad auch ratlos...

Autor: Jan R. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> OK, ich glaube ich habe den Fehler gefunden.

also doch was banales. wahrscheinlich ADC3 geschrottet. kann unter 
umständen mal eine Spannung > 5V aus deinem Funkempfänger kommen? Dann 
würde ich mal eine Schutzbeschaltung davorhängen.

gruß, jan

Autor: Christof Kauba (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also laut Datenblatt des Funkempfänger ist die maximale Spannung an 
diesem Ausgang 2,53V.
Ich habe auch um sicherzugehen mal beim Einschalten nachgemessen, ob 
nicht vielleicht Spannungsspitzen auftreten, habe da aber auch keine 
Spannung größer 2,5V gemessen.

Autor: bitschieber (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
trotz alter Beitrag die lösung:
schau dir mal den Source Code der AppNote 442 an
AVR442: PC Fan Control using ATtiny13

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.