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
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.
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
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.
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
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
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
Hi >dann muss man auch zwingend den ADC-Wert lesen ! >Steht auch alles im Datenblatt. Wo steht das so? MfG Spess
? 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
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
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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.