Problem mit ADC und ATTINY13

Gast #2882170
Lesenswert?

Hey Allerseits,
hat eventuell einer von euch eine Idee, warum ich immer 0 vom ADC 
zurückbekomme? (OSZI und Multimeter zeigen 0.08V direkt am pin PB4 => 
ADC-Wert sollte also 80 sein...)
1
/*
2
 * InPlugV1_ATTINY13.c
3
 *
4
 * Created: 21.10.2012 13:08:11
5
 *  Author: Roland Blank
6
 */ 
7

8

9

10
// Definitionen
11
#define F_CPU 9600000                    // Frequenze des Controllers
12

13

14
#define LWEISON PORTB |= (1<<PINB1)
15
#define LWEISOFF PORTB &= ~(1<<PINB1)
16
#define LROTON PORTB |= (1<<PINB2)
17
#define LROTOFF PORTB &= ~(1<<PINB2)
18
#define TransON PORTB |= (1<<PINB0)
19
#define TransOFF PORTB &= ~(1<<PINB0)
20

21
// Includes
22
#include <avr/io.h>
23
#include <util/delay.h>
24
#include <avr/interrupt.h>
25
#include <stdlib.h>
26
#include <stdint.h>
27
#include <avr/eeprom.h>
28

29
uint16_t readADC(uint8_t channel);
30

31
int main(void)
32
{
33
  //Init
34
  DDRB |= (1<<PINB1) | (1<<PINB2) | (1<<PINB0);      // PB0 = TransOUT, PB1 = LED-Weis, PB2 = LED-Rot
35
  DDRB &= ~(1<<PINB4);                  // PB4 als Eingang
36
  PORTB |= (1<<PINB4);
37
  //Var
38
  uint16_t t = 0;
39
  
40
  //Endlosschleife
41
  while(1)
42
    {
43
    LWEISON;
44
    TransON;
45
    _delay_ms(3);
46
    t = readADC(2);
47
    _delay_ms(1);
48
    if ((t>0))
49
    {
50
      LROTON;
51
    }else{
52
      LROTOFF;
53
    }
54
    LWEISOFF;
55
    TransOFF;
56
    _delay_ms(5);
57
    }
58
}
59

60
uint16_t readADC(uint8_t channel) {
61
  uint8_t i;
62
  uint16_t result = 0;
63
  
64
  // Den ADC aktivieren und Teilungsfaktor auf 64 stellen
65
  ADCSRA |= (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);
66

67
  // Kanal des Multiplexers waehlen
68
  // Interne Referenzspannung verwenden (also 2,56 V)
69
  ADMUX |= channel | (1<<REFS0);
70
  
71
  // Den ADC initialisieren und einen sog. Dummyreadout machen
72
  ADCSRA |= (1<<ADSC);
73
  while(ADCSRA & (1<<ADSC));
74
  
75
  // Jetzt 3x die analoge Spannung and Kanal channel auslesen
76
  // und dann Durchschnittswert ausrechnen.
77
  for(i=0; i<3; i++) {
78
    // Eine Wandlung
79
    ADCSRA |= (1<<ADSC);
80
    // Auf Ergebnis warten...
81
    while(ADCSRA & (1<<ADSC));
82
    
83
    result += ADCW;
84
  }
85
  
86
  // ADC wieder deaktivieren
87
  ADCSRA &= ~(1<<ADEN);
88
  
89
  result /= 3;
90
  
91
  return result;
92
}

Könnte es ein Problem sein, dass ich Debugwire aktive habe und den 
Controller mittels ICE3 + SPI/Debugwire programmiere/debugge?

Vielen Dank für eueren reichhaltigen Erfahrungsschatz :D

Gruß
Roland
Gast #2882246
Lesenswert?

Hi,

Das hilft die jetzt auch nur bedingt weiter:
Bei mir läuft dein Code. Hab ich zwar nicht auf nem ATtiny ausprobiert,
sondern mit nem ATmega. Kommt genau das raus, was rauskommen soll. Der 
erste Wert weicht gering von den beiden folgenden ab, das liegt m.E. 
daran, dass die Wartezeit nach ADEN=1 zu kurz ist.

Zurück zu deinem Problem: Gibts beim ATtiny vllt. noch irgendein 
Register, mit dem man den ADC global anfeuern muss ?
Gast #2882272
Lesenswert?

Hi,


ich würde nochmal folgendes ausprobieren:

1) in readADC zuerst ADMUX schreiben, dann ADCSRA ( so stehts im manual 
)

2) während der Initialisierung den digitalen Modus von PB4 komplett zu 
deaktivieren: DIDR0 = ( 1 << ADC2D )

3) Prescaler höher setzen, z.b auf Maximum.

4) nach dem Setzen von ADEN noch mal eine ms warten.
Gast #2882368
Lesenswert?

Hi, debugwire: ich denke nicht, da nur die pins miso Mosi sck und Reset 
über den 6-poligen Stecker verbunden werden. Pb4 vom attiny13 ist keiner 
davon. Nutzt du debugwire, um durch den Code zu Steppen? Ich habe keine 
ahnung, wie sich der Adc verhält, wenn man da mit debugwire durchsteppt.
In welcher Umgebung rennt dein attiny? Irgendein protoboard? Pb4 evtl 
davon belegt?
hast du die möglichkeit, mit nem anderen atmel Controller, der einen 
Uart hat, zu testen?
Hat den Vorteil, dass man nicht nur auf blinkende LEDs starren, sondern 
auch mal Text/Werte ausgeben und interaktiv testen kann. Wenn das dann 
funzt, dann auf den attiny bringen. Das adc Zeug kann man fast ohne 
Anpassung von Typ zu Typ übertragen.
Gast #2882380
Lesenswert?

Einen richtigen Fehler hab ich auf die schnelle nicht gefunden, aber 
gefährliche Sachen die sich irgendwann rächen werden.
1
  // Den ADC aktivieren und Teilungsfaktor auf 64 stellen
2
  ADCSRA |= (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);
3

4
  // Kanal des Multiplexers waehlen
5
  // Interne Referenzspannung verwenden (also 2,56 V)
6
  ADMUX |= channel | (1<<REFS0);



Besser
1
  // Den ADC aktivieren und Teilungsfaktor auf 64 stellen
2
  ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);
3

4
  // Kanal des Multiplexers waehlen
5
  // Interne Referenzspannung verwenden (also 2,56 V)
6
  ADMUX = channel | (1<<REFS0);

Warum?
Wenn dein Programm z.B. Erst Channel 1 und dann Channel 2 auslesen soll 
ließt zu bei der zweiten Wandlung Channel 3 statt 2 aus. Du setz das 
ADMUX Register nie zurück, durch "=" statt "|=" wird das Register genau 
auf den Wert gesetzt und nicht mit einem möglicherweise falschen Inhalt 
verodert.
Positiver Effekt, durch das weggelassene verodern schneller+weniger 
Programmspeicher


1
  // Jetzt 3x die analoge Spannung and Kanal channel auslesen
2
  // und dann Durchschnittswert ausrechnen.
3
  for(i=0; i<3; i++) {
4
    // Eine Wandlung
5
    ADCSRA |= (1<<ADSC);
6
    // Auf Ergebnis warten...
7
    while(ADCSRA & (1<<ADSC));
8
    
9
    result += ADCW;
10
  }
11
  
12
  
13
  result /= 3;

Such dir lieber ne 2^n zahl aus 2,4,8,16,... Teilen im µC ist immer 
langwierig und Programmspeicher intensiv bei einer 2^n Zahl ist es eine 
einfache Shift-Operation, die geht fix und kostet kaum Speicher.


Wie sich Debugwire auf den adc auswirkt kann ich dir nicht sagen, aber 
setzt doch einfach nen Breakpoint nach der ADC-Funktion und schau dir 
das Ergebnis an dann sollte es keine Probleme geben.

Gruß Matthias
Gast #2882484
Lesenswert?

@Katastrophenheinz: Es ist ein selbsterstelltes Board, welches sehr 
klein ist. Mehr als ein OSZI und zwei LEDS steht mir leider nicht zur 
Verfügung.

@Matthias: Danke für die Tips, ich habe sie gleich in meinen Code 
einfließen lassen. Leider lösen sie auch nicht das Problem.

Ich werde heute mal einen anderen Attiny13A verlöten, vielleicht hat nur 
er defekt.

Kann es Schaltungstechnik noch einen Fehler geben, selbst wenn ich 
direkt an PB4 mein Signal per OSZI messen kann?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren