Forum: Compiler & IDEs ATTiny13 2x ADC Gleicher Wert ?


von Bernd M. (adventureman1972)


Lesenswert?

Moin!
Ich möchte einen LIPO-Akku mit zwei in Reihe geschalteten Zellen mit 
einem ATTiny 13 überwachen. Dafür verwende ich den Balancieranschluss 
des Akkus, welcher auch den Kontakt zwischen den Zellen aus dem Akku 
führt.
Der µC soll die Spannung der einzelnen Zellen auswerten und bei 
unterschreiten der 3,0 Volt/Zelle den Ausgang PB0 ausschalten.
Da die Eingänge nur 5 Volt vertragen, der Akku aber bis zu 8,4 Volt hat, 
sind eingestellte Potis davor, die die jeweilige Zellenspannung 
halbieren.
Die Zelle, die als erste die Mindestmarke erreicht, schaltet den Ausgang 
aus. Das Abschalten des Ausgang ist auch das Ende der 
while-Schleifenbedingung. Danach soll nur noch für 60 Sekunden die LED 
leuchten, die für die passende Zelle eingeschaltet wurde.

Mein Problem ist, das bei unterschreiten einer Zellenspannung beide 
LED's leuchten. Folglich beide Bedingungen auslösen. Das kann aber 
eigentlich nicht sein, da es immer einen kleinen Unterschied in den 
Zellen gibt.

Ich gehe davon aus, dass ADMUX für die ADC-Wandlung nicht richtig 
funktioniert. Schaut bitte einmal über das Programm und schreibt mir ob 
ich richtig liege oder irgend was übersehe.

Danke...
1
#define F_CPU 9600000
2
#include <avr/io.h>
3
#include <util/delay.h>
4
5
//******************************************* 
6
7
unsigned int Spannung   = 0;
8
unsigned int Zelle_1    = 0;
9
unsigned int Zelle_2    = 0;
10
11
//******************************************* 
12
13
void ADC_Wandlung()
14
{
15
  ADCSRA |=   (1 << ADSC);           // erste Wandlung
16
  while (ADCSRA & (1 << ADSC)){;}    // warte bis ADWdlg. fertig
17
  Spannung = ADCW;                  // Übergabe Wert 1
18
  Spannung = 0;            // Löschen des Ergebnisses
19
    
20
  for(int i=0; i<10; i++ )      // Abfrage X mal wiederholen
21
  {
22
    ADCSRA |=   (1 << ADSC);       // start Wandlung
23
    while (ADCSRA & (1 << ADSC)){;} // warte bis ADWdlg. fertig
24
    Spannung += ADCW;        // Aufaddieren der Werte
25
  } 
26
    
27
  Spannung /= 10;            // Mittelwert bilden
28
}
29
30
//******************************************* 
31
32
int main (void)
33
{
34
  DDRB |= (1<<PB0) | (1<<PB1)| (1<<PB2);     //  
35
36
  // Grundeinstellungen für ADC-Wandlung
37
  ACSR |= (1<<ACD);          // Ausschalten des Analog Comperator
38
  CLKPR = 0x40;            // Takt Vorteiler hier 1 Clock Prescale Register
39
40
  ADCSRA |=   (1 << ADEN);            // Analog-Digital einschalten
41
//  ADCSRA |=  (1 << ADPS2);      // set prescaler
42
  ADCSRA |=  (1 << ADPS1);           // set prescaler
43
//  ADCSRA |=  (1 << ADPS0);           // set prescaler (clock / 2)
44
   
45
//  ADMUX  |=  (1 << ADLAR);          // 8bit in ADCH   
46
//  ADMUX  |=  (1 << REFS0);      // Interne Referenzspannung einschalten 1,1 Volt
47
48
//******************************************* 
49
50
  _delay_ms(4900);
51
  PORTB |= (1<<PB0);
52
  
53
  while (( PORTB & 0x01 ) == 0x01 )
54
  {
55
    ADMUX  |=   (1 << MUX1);  // ADC3 einschalten
56
    ADMUX  |=   (1 << MUX0);
57
    ADC_Wandlung();
58
    Zelle_1 = Spannung;  // Übergabe Wert 1   4,2 Volt
59
60
    ADMUX  |=   (1 << MUX1);  // ADC2 einschalten
61
    ADMUX  &=  ~(1 << MUX0);
62
    ADC_Wandlung();
63
    Zelle_2 = Spannung;  // Übergabe Wert 2   8,4 Volt
64
65
    Zelle_2 -= Zelle_1;  // 8,4 Volt - 4,2 Volt
66
67
    if ( Zelle_1 < 307 ) { PORTB &= ~(1<<PB0); PORTB |= (1<<PB1); }
68
    if ( Zelle_2 < 307 ) { PORTB &= ~(1<<PB0); PORTB |= (1<<PB2); }
69
70
    _delay_ms(100);
71
    }
72
  
73
  for (unsigned int a = 0; a<60000; a++) { _delay_ms(1); }
74
75
  PORTB &= ~(1<<PB1);
76
  PORTB &= ~(1<<PB2);
77
  
78
return(0);
79
}

von sven (Gast)


Lesenswert?

Hast Du deine beiden Spannungen direkt an den ADC-Eingängen selber 
nachgemessen ?
Ich vermute dass hier
1
   if ( Zelle_1 < 307 ) { PORTB &= ~(1<<PB0); PORTB |= (1<<PB1); }
 ein 'else' fehlt...

Nach 60 Sekunden gehen beide Pins eh auf 0 - das meinst Du nicht ?

von Karl H. (kbuchegg)


Lesenswert?

Bernd M. schrieb:

> Ich gehe davon aus, dass ADMUX für die ADC-Wandlung nicht richtig
> funktioniert.

Das müsste schon klappen.
Denn du machst ja hier

>     Zelle_2 -= Zelle_1;  // 8,4 Volt - 4,2 Volt

die Differenz, und wenn die beiden Messwert identisch wären, dann würde 
da immer 0 rauskommen und damit sofort die Überwachung anschlagen. Da 
dies aber deiner Beschreibung nach offenbar aber nicht passiert, heißt 
das, das die 2.te Messung ein höheres Ergebnis bringt als die erste.


Wie testest du?

Ich würde mir mit einem Poti eine variable Spannung erzeugen und die auf 
den ADC Eingang legen und den anderen mit einer fixen Spannung am 
auslösen hindern.


Deine jetzigen Spannungsteilerpoti sind sicher so verschaltet, dass sie 
die Eingangsspannung halbieren? Und zwar beide, jeder für sich (sonst 
kannst du nämlich die Messwerte nicht so einfach miteinander verrechnen)

von form (Gast)


Lesenswert?

Bernd M. schrieb:
> und bei unterschreiten der 3,0 Volt/Zelle den Ausgang PB0 ausschalten

3 Volt sind aber schon etwas brutal...
Ich glaube bei ca. 3,2 Volt wird es kritisch. Lieber schon bei 3,3 Volt 
abschalten.

von Bernd M. (adventureman1972)


Lesenswert?

Es klappt !!!

Habe aber nichts mehr geändert im Programm!?

Der Lipo wird bei 6,3 Volt von der Last befreit. Die zwei LEDs zeigen 
mir an, welche von den beiden Zellen die Schaltschwelle erreicht hat. 
Genau was ich wollte!

Der Tip(p) mit der Festspannung war Klasse...


Danke !

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.