Forum: Compiler & IDEs ADC Messung beim ATTiny13 Problem


von Christof Kauba (Gast)


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:
1
#define F_CPU 1200000UL     // Quarz mit 1,2 Mhz (interner Oszillator)
2
3
#include <avr/io.h>        // Library für Hardwaredefinitionen etc.
4
#include <avr/interrupt.h>    // Definitionen für Interruptroutinen
5
#include <avr/signal.h>      // Interruptroutinen 2
6
#include <stdint.h>        // Integer Datentypen
7
#include <util/delay.h>      // Verzögerungsschleifen
8
9
10
11
// Funktionen:
12
13
uint16_t Messung(void);    //ADC Messung
14
15
16
// Variablen:
17
18
uint16_t rfsignal = 0;
19
uint8_t counter = 0;
20
uint8_t compare = 0;
21
22
23
// Hauptprogramm:
24
25
int main (void)
26
{
27
  
28
  // Timer initialisieren:
29
30
  TIMSK0 &= ~((1<<TOIE0)|(1<<OCIE0A)|(1<<OCIE0B));       //Interrupts für Timer 0 deaktivieren
31
  
32
  TCCR0A = 0x00;
33
  TCCR0B |= (1<<CS01) | (1<<CS00);              //Takt = CPU-Takt/64
34
  TCNT0 = 0x00;
35
  
36
  TIMSK0 |= (1<<TOIE0);       //set 8-bit Timer/Counter0 Overflow Interrupt Enable
37
  
38
  sei();            // set the Global Interrupt Enable Bit
39
  
40
  set_sleep_mode(SLEEP_MODE_IDLE);
41
  
42
  
43
  // Initialisierung Ports:
44
45
  DDRB |= (1<<PB0);
46
  
47
48
  PORTB |= (1<<PB0);
49
  
50
  while(1)
51
  {
52
    rfsignal = Messung();
53
    
54
    compare = (rfsignal * (-2517L))/10000L + 125;
55
      
56
    if (counter >= compare)
57
    {    
58
      PORTB ^= (1<<PB0);      //Port B, Pin 0 toggeln (LED blinkt)
59
      counter = 0;
60
    }
61
    
62
    sleep_mode();
63
  }
64
}
65
66
67
68
SIGNAL(SIG_OVERFLOW0)      //overflow interrupt vector
69
{
70
  counter++;
71
}
72
73
74
// ADC Funktion:
75
  
76
uint16_t Messung (void)     //Methode zum Messen mittels ADC und errechnen des Messwertes
77
{            
78
79
  uint16_t result = 0;    //Messergebnis
80
  
81
  ADCSRA |= (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);    //Initialiserung ADC, Frequenzteiler: 8
82
  ADMUX = 0x03;                    //Zu verwendender Pin, ADC3
83
  
84
                            //Versorgungsspg. als Referenz
85
86
  
87
  //Dummy-Messung zwecks ADC Initialisierung bzw. nach Referenzspannungswechsel
88
  
89
  ADCSRA |= (1<<ADSC);           // eine ADC-Wandlung
90
  while(!(ADCSRA & (1<<ADIF)));       // auf Abschluss der Konvertierung warten (ADIF-bit)
91
  ADCSRA |= (1<<ADIF);           // ADIF löschen
92
  
93
  // Eigentliche Messung
94
 
95
  ADCSRA |= (1<<ADSC);         // eine Wandlung "single conversion"
96
  while(!(ADCSRA & (1<<ADIF)));     // auf Abschluss der Konvertierung warten (ADIF-bit)
97
  result = ADCW;             // Wandlungsergebnis
98
  ADCSRA |= (1<<ADIF);         // ADIF löschen
99
  
100
  ADCSRA &= ~(1<<ADEN);           // ADC deaktivieren (2)
101
  ADMUX = 0x00;              // ADMUX löschen
102
  
103
  return result;              // Rückgabewert der Funktion = Messwert
104
}

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.

von Karl H. (kbuchegg)


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.

von Johannes M. (johnny-m)


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.

von Stefan (Gast)


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 ?!

von Johannes M. (johnny-m)


Lesenswert?

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

von Stefan (Gast)


Lesenswert?

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

von Jan R. (Gast)


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

von Christof Kauba (Gast)


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).

von Christof Kauba (Gast)


Lesenswert?

Außerdem ist mir gerade aufgefallen, dass eigentlich statt
1
#include <avr/signal.h>      // Interruptroutinen 2
1
#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.

von Jan R. (Gast)


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.

von Karl H. (kbuchegg)


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.

von Christof Kauba (Gast)


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?

von Christof Kauba (Gast)


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.

von Jan R. (Gast)


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...

von Jan R. (Gast)


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

von Christof Kauba (Gast)


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.

von bitschieber (Gast)


Lesenswert?

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

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.