Forum: Mikrocontroller und Digitale Elektronik Problem mit ADC-Wandlungen Attiny-85


von Walter H. (waha)


Lesenswert?

Hallo,

Ich versuche mit einem Attiny-85 in Verbindung mit einem L200 eine Art 
überwachtes Netzteil zu realiiseren.

Den jeweiligen Betriebszustand soll der MC über eine LED-Ampel anzeigen.
Um den Zustand festzustellen werden zwei Analog-Digital wandlungen im 
Wechsel durchgeführt.
Die Ausgangsspannung wird über eine normale Messung realisiert.
Der Strom wird über eine Shuntwiderstand ermittelt, mit einer 
Differenzmessung und einem Gain von 20.

Das Problem:

Wenn ich im Quellcode den Funktionsaufruf einer der beiden Messungen 
auskommentiere klappt das Wunderbar. Die Genauigkeit ist sehr gut.

ABER beide im Wechsel geht nicht...

Hatte vielleicht jemand ein ähliches Problem oder kann sich da einen 
Reim draus machen?

Mfg

: Bearbeitet durch User
von Felix A. (madifaxle)


Lesenswert?

Kaum, ohne deine Software und einen Schaltplan zu sehen.

von Dennis K. (scarfaceno1)


Lesenswert?

Wandlungsdauer beachtet?

Schaltest du die Ports während der Wandlung um, kann das auch in die 
Hose gehen.
Also Timing beachten und ggf den Abschnitt ADC im Datenblatt nochmal 
lesen.

von Uwe (de0508)


Lesenswert?

Hallo Walter H.,

was Dennis K. unter anderem meint, ist , dass die ADC-Eingänge 
niederohmig betrieben werden sollen.
Das kann man über jeweils einen OPV a=1 erreichen.
Die Shunt-Spannungsmessung würde ich immer über einen differenziellen 
OPV realisieren.

Siehe AN105 - Current Sense Circuit Collection

# http://cds.linear.com/docs/en/application-note/an105fa.pdf

Ich verwende den LT1637 zur High-Side Strommessung, mit einem 
4-Leiter-Shunt 1mOhm und a=100. Es entsteht dadurch eine Offsetfehler, 
den man einfach korrigieren kann.

# http://cds.linear.com/docs/en/datasheet/1637fd.pdf

von Julian B. (julinho)


Lesenswert?

Walter H. schrieb:
> Der Strom wird über eine Shuntwiderstand ermittelt, mit einer
> Differenzmessung und einem Gain von 20.

Den ersten Wert nach dem Umschalten in den "Gain"-Modus solltest du 
verwerfen, also zwei mal hintereinander messen. Steht glaub ich auch im 
Manual.

von Walter H. (waha)


Lesenswert?

Hallo,

erstmal danke für die Anregungen.

Die Bauteile stehen fest, da es sich um eine Arbeit für die Uni handelt. 
Wäre super wenn sich das jemand angucken könnte.

Hier der Quellcode:
1
#include<avr/io.h>
2
#include <stdio.h>
3
#include <math.h>
4
#include <util/delay.h>
5
//Funktionprototypen
6
int  Messung(void);
7
int DiffMessung(void);
8
void Zustandsanzeige(int VDIFFadc, int VOUTadc,int VadcKS, int VadcVerplg, int VadcUeberstrom, int VadcLlauf);
9
10
int VOUTadc, VDIFFadc,VadcKS,VadcVerplg,VadcUeberstrom,VadcLlauf;
11
12
int main(void)
13
{
14
15
  DDRB = 0xff;
16
  PORTB = 0xff;
17
  // Grenzen
18
  VadcKS     = 83;      // entsprechen 0,4 V 
19
  VadcVerplg = 207;      // entsprechen 1V
20
  VadcUeberstrom = 997;    // entsprechen 4,75V
21
  VadcLlauf = 75;        // entsprechen 18 mV (10mA)
22
  VOUTadc=1000;
23
  
24
  for(;;)    // Endlosschleife
25
  {  
26
    VOUTadc = Messung();
27
                VDIFFadc = Diffmessung();
28
                Zustandsanzeige();
29
30
  }
31
}// Ende main
32
33
// Funktionen 
34
35
int Messung(void)
36
{
37
  /* ------- Spannungsmessung am Ausgang   ----------------------------------------*/
38
  ADMUX = 0b00000011;    // ADC3 (PB3) 
39
  
40
  ADCSRA |= (1<<ADSC)|(1<<ADEN);  // eine Wandlung "single conversion"
41
  while (ADCSRA & (1<<ADSC));  // auf Abschluss der Konvertierung warten*/
42
  
43
  ADCSRA |= (1<<ADSC)|(1<<ADEN);  // eine Wandlung "single conversion"
44
  while (ADCSRA & (1<<ADSC));
45
  
46
  return ADC;
47
}
48
49
int DiffMessung(void)
50
{
51
52
    
53
  ADMUX =0b00000111;            // Differenzmessung ADC2 (PB4) und ADC3 (PB3) mit Gain = 20
54
    
55
  ADCSRA |= (1<<ADSC)|(1<<ADEN);    // eine Wandlung "single conversion"
56
  while (ADCSRA & (1<<ADSC));  // auf Abschluss der Konvertierung warten*/
57
    
58
  ADCSRA |= (1<<ADSC)|(1<<ADEN);  // eine Wandlung "single conversion"
59
  while (ADCSRA & (1<<ADSC));
60
    
61
  return ADC;
62
    
63
}
64
void Zustandsanzeige(int VDIFFadc, int VOUTadc,int VadcKS, int VadcVerplg, int VadcUeberstrom, int VadcLlauf)
65
{
66
/*-------- Fallunterscheidung für LED Steuerung------------------------------*/
67
    //  5  Leerlauf -> Grüne und gelbe LED leuchtet
68
    if(VDIFFadc <= VadcLlauf)
69
    {
70
      // LED´s sind LOW-Aktiv, also müssen die Bits zum einschalten 0 werden (zurücksetzen)
71
      PORTB &= ~(1<< PB1);
72
      PORTB &= ~(1<< PB2);
73
      
74
      PORTB |= (1<< PB0);
75
    }
76
    
77
    //  4 Normalbetrieb -> Grüne LED(2) leuchtet
78
    else if(VOUTadc > VadcUeberstrom)
79
    {
80
      PORTB &= ~(1<< PB2);
81
      
82
      PORTB |= (1<< PB0);
83
      PORTB |= (1<< PB1);
84
    }
85
    
86
    //  3 Überstrom -> Rote und Gelbe LED leuchten
87
    else if(VOUTadc >VadcVerplg)
88
    {
89
      PORTB &= ~(1<< PB1);
90
      PORTB &= ~(1<< PB0);
91
      
92
      PORTB |= (1<< PB2);
93
    }
94
    
95
    //  2 Verpolung -> Gelbe LED(1) leuchtet
96
    else if( VOUTadc > VadcKS )
97
    {
98
      PORTB &= ~(1<< PB1);
99
      
100
      PORTB |= (1<< PB0);
101
      PORTB |= (1<< PB2);
102
    }
103
    
104
    //1 Kurzschluss -> Rote LED (0) leuchtet
105
    else if(VOUTadc <=VadcKS)
106
    {
107
      PORTB &= ~(1<< PB0); // Setzen
108
      
109
      PORTB |= (1<< PB1);  //Rücksetzen 
110
      PORTB |= (1<< PB2);
111
      
112
    }
113
    
114
    else
115
    {
116
      PORTB |= (1<< PB0);
117
      PORTB |= (1<< PB1);
118
      PORTB |= (1<< PB2);
119
    }
120
}

: Bearbeitet durch User
von Uwe (de0508)


Lesenswert?

Hallo Walter,

wo finden wir deinen Schaltplan ?

Es ist eher ein elektrisches Problem, wenn man das nicht beseitigt, dann 
wird das nichts..

: Bearbeitet durch User
von Uwe (de0508)


Lesenswert?

Hallo Walter,

hast Du AP von Atmel für dem AVR gelesen und umgesetzt ?

AVR120: Characterization and Calibration of the
ADC on an AVR

AVR121: Enhancing ADC resolution by
oversampling

Ich verwende immer 2^n; n E {4,..,64} ADC-Messungen am Stück und bilde 
dann den Mittelwert über alle Messergebnisse.

------------------------------------------------------------

Zu deinem Programm Code, sollte man nicht als erstes den ADC 
initialiseren.

Ich bevorzuge die Bit-Nummer, um Probleme zu vermeiden und es dem Leser 
einfacher zu machen.
Bsp.:
1
ADCSRA |= (1<<ADEN);

Der Attiny85 hat folgende Register, die man alle kennen sollte:
ADMUX – ADC Multiplexer Selection Register
REFS1 REFS0 ADLAR REFS2 MUX3 MUX2 MUX1 MUX0

Du schreibst nichts in die Bits REFS[2:0] somit wird
VCC used as Voltage Reference, disconnected from PB0 (AREF) verwendet.
Sehr ungünstig !

ADCSRA – ADC Control and Status Register A
ADEN ADSC ADATE ADIF ADIE ADPS2 ADPS1 ADPS0

Wichtig sind hier u.a.:
ADCSRA.ADEN = 1
ADCSRA.ADATE = 0
ADCSRA.ADIE = 0
ADCSRA.ADPS[2:0] := 50kHz <= ADC-Takt <= 200kHz hier muss man lesen und 
rechnen.

ADCSRA.ADSC = 1 für den Start einer ADC-Wandlung.

ADCSRB – ADC Control and Status Register B
BIN ACME IPR – – ADTS2 ADTS1 ADTS0
ADCSRB.ADTS[2:0] = 000

Das ist evtl. für Dich wichtig ?
Bit 7 – BIN: Bipolar Input Mode
The gain stage is working in the unipolar mode as default, but the 
bipolar mode can be selected by writing the BIN bit in the ADCSRB 
register.
In the unipolar mode only one-sided conversions are supported and the 
voltage on the positive input must always be larger than the voltage on 
the negative input.
Otherwise the result is saturated to the voltage reference.
In the bipolar mode two-sided conversions are supported and the result 
is represented in the two’s complement form. In the unipolar mode the 
resolution is 10 bits and the bipolar mode the resolution is 9 bits
+ 1 sign bit.

DIDR0 – Digital Input Disable Register 0
– – ADC0D ADC2D ADC3D ADC1D AIN1D AIN0D

Hier sollte man schon die verwendeten und seine analogen Eingänge 
eintragen !

------------------------------------------------------------

Wenn mann dann eine Dummy ADC-Wandlung macht
1
ADCSRA |= (1<<ADSC)|(1<<ADEN);
2
  while (ADCSRA & (1<<ADSC));
dann muss man auch zwingend den ADC-Wert lesen !
Steht auch alles im Datenblatt.

Noch schlimmer ist es, wenn man seine Ports nicht richtig setzt:
1
DDRB = 0xff;
2
  PORTB = 0xff;

Schon mal im Datenblatt nachgesehen was dass bedeutet ?

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

>dann muss man auch zwingend den ADC-Wert lesen !
>Steht auch alles im Datenblatt.

Wo steht das so?

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

?

Und dein Compiler hat gar nichts dazu zu sagen, dass du eine Funktion 
ohne Argumente aufrufst
1
....
2
                Zustandsanzeige();
3
...

die eigentlich eine ganze Latte an Funktionsparametern erwartet?
1
void Zustandsanzeige(int VDIFFadc, int VOUTadc,int VadcKS, int VadcVerplg, int VadcUeberstrom, int VadcLlauf)
2
.....

: Bearbeitet durch User
von Walter H. (waha)


Angehängte Dateien:

Lesenswert?

Vielleicht vorweg...

Das ist mein erstes eigenes Projekt. Daher bitte ich um ein bischen 
Nachsicht und Hilfe :)

Doch die Funktionsaufrufe stimmen. Ich habe es in der Eile falsch hier 
reinkopiert, weil ich noch einiges auskommentiertes rausgelöscht habe.

Hier der Schaltplan:

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Walter H. schrieb:

> Doch die Funktionsaufrufe stimmen. Ich habe es in der Eile falsche hier
> reinkopiert, weil ich noch einiges auskommentiertes rausgelöscht habe.

Dadurch, dass du anderen COde rauslöscht werden aber korrekte 
Funktionsaufrufe nicht illegal.
Im übrigen machst du dir hier keine Freunde, wenn du nicht exakt den 
Code postest, der dann auch tatsächlich genau so auf deinem µC läuft. 
Denn ganz offensichtlich hast du deine verkürzte Version nicht getestet, 
ob sie das von dir 'in der Langversion' beobachtete Verhalten immer noch 
aufweist.

DU brauchst Hilfe, nicht wir. Dann schmeiss uns auch keine Prügel 
zwischen die Beine.

von Uwe (de0508)


Lesenswert?

Nun ja,

Ich würde an der Uni kein Projekt machen, von dem ich 0 Ahnung habe.

Selbst der Schaltplan enthält Fehler und so kann die Schaltung nicht 
funktionieren. Stichwort LED.
Der Attiny85 benötigt einen 100nF Kondensator direkt an Vcc - Gnd.
Zu Messen (ADC), dass kann man nur, wenn man eine saubere 
Referenzspannung hat, sonst bleiben nur Tendenzen übrig.
Die Spannungsregler benötigen jeweils ihre eigene Filterung an ihren 
Ein- und Ausgängen. Wie steht in deren Datenblättern.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

1
  ADCSRA |= (1<<ADSC)|(1<<ADEN);
den Default Prescaler von 2 zu benutzen ist nicht gerade schlau.
So wie das aussieht, wird dein Tiny mit 1Mhz getaktet (default 
RC-Oszillator). Mit einem Prescaler von 2 hast du damit eine ADC 
Taktfrequenz von 500kHz. Da leidet die Genauigkeit dann schon sehr. 
Atmel empfiehlt einen Bereich von 50kHz bis maximal 200kHz. Mit den 
500kHz bist da da schon einiges über das Ziel hinausgeschossen.

Edit: und ich könnte mir durchaus vorstellen, dass da nich nur die 
Genauigkeit drunter leidet, sondern dass die ADC internen Vorgänge 
dadurch ganz einfach viel zu schnell ablaufen, damit der ADC korrekt auf 
die jeweiligen Eingänge geschaltet werden bzw. sich die Sample & Hold 
Stufen auf die jeweiligen Spannungen umladen können.

: Bearbeitet durch User
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.