Bei 1 MHz CPU Takt wird der ADC mit 125 kHz getaktet und differentiell genutzt; davon ist der negative Eingang auf GND. DIDR0 = (1 << ADC2D) | (1 << ADC3D); ADMUX = (1 << MUX2) | (1 << MUX1); Die Referenzspannung ist auf interne 1.1 V eingestellt: ADMUX = (ADMUX & ~((1 << REFS2) | (1 << REFS1) | (1 << REFS0))) | (1 << REFS1); Fällt der ADC-Wert auf unter ein zwanzigstel des Wertebereichs (eigentlich 50, ich nutze 25), schalte ich den Verstärker ein: ADMUX |= (1 << MUX0); Samt Wartezeit und Dummy-Messung: _delay_us(1000); ADCSRA |= (1 << ADSC); while (!(ADCSRA & (1 << ADSC)));(void)ADC; Leider ergeben die auf eine 0xF folgenden Messungen (single conversion) mit 20x Gain dann ziemlichen Murks: ein paar Werte im Bereich 0 gefolgt von Werten am oberen Anschlag, z.B. 0x3FE. Dabei erwarte ich irgendwas um 0xF*20 = 0x12C (300). Was übersehe ich? Abgesehen davon, dass der Messbereich dann nur noch 55 mV sind.. Hinweise habe ich folgende gefunden: - requires an input clock frequency between 50 kHz and 200 kHz to get maximum resolution - The first ADC conversion result after switching voltage reference source may be inaccurate, and the user is advised to discard this result. - When differential channels and gain are used, using VCC or an external AREF higher than (VCC - 1V) as a voltage reference is not recommended as this will affect the ADC accuracy.
Hatschi Puh schrieb: > Samt Wartezeit und Dummy-Messung: benötigst du die wirklich, wenn du nur den Gain wechselst. Ich dachte in dem Fall ist das unnötig, die Eingänge und Referenz ändern sich ja nicht. Was ist denn die Quelle deiner gemessenen Spannung? Schon mal mit einem 10 gang Poti oder Poti + Widerstand versucht einen Spannungswert unter 50mV zu messen? Was passiert, wenn du beim erreichen des oberen Anschlages wieder auf x1 gain umschaltest, bzw. was sind dann die gemessenen Werte? Unabhängig vom Problem bietet es sich an den µC in den ADC sleep mode zu setzen und nach der Messung per Interrupt zu wecken, da du sowieso nur wartest.
Hatschi Puh schrieb: > Samt Wartezeit und Dummy-Messung: Das Delay ist unnötig, eben so der Dummy-Read da du ja nicht die Referenzspannung änderst. Zu deiner Frage: Zeige uns bitte dein gesamtes Programm, dass den Fehler zeigt. Es kann ein Fehler im Code sein, hatte ich letztens beim Atmega32U4 auch gehabt und nicht mal dem Forum fiel mein Fehler auf obwohl er eigentlich offensichtlich war (Wald und Bäume und so ;))
Wenn Du Hilfe willst, dann compilierbarer Quelltext als Anhang und Schaltplan (Foto der Handzeichnung reicht). Mit Prosa und hingestreuten Schnipselchen kann keiner was anfangen.
Mit internem Pull-Up und externen 120 Ohm erreiche ich etwa 40 mV. Also PB4 mit 100 Ohm nach GND, PB3 nach GND. Dummy-Wandlung und Wartezeit jetzt nur noch nach Änderung von MUX. Minimaler Quelltext:
1 | // ATtiny85, 5V, 1MHz
|
2 | |
3 | // PB4 ---[100 Ohm]---GND
|
4 | // PB3 -------------- GND
|
5 | // PB1 serial out:
|
6 | // 8N1, 38400 baud
|
7 | |
8 | #include "stdint.h" |
9 | #include "stdbool.h" |
10 | |
11 | #include <avr/io.h> |
12 | #include <util/delay.h> |
13 | |
14 | void debug(uint8_t c) |
15 | {
|
16 | uint16_t d = 0b1000000000 | (c << 1); |
17 | while (d) |
18 | {
|
19 | if (d & 1) |
20 | PORTB |= (1 << PB1); |
21 | else
|
22 | PORTB &= ~(1 << PB1); |
23 | d >>= 1; |
24 | _delay_us((1e6 / 38400) - 12); // magic |
25 | }
|
26 | }
|
27 | |
28 | uint16_t convert(void) |
29 | {
|
30 | ADCSRA |= (1 << ADSC); |
31 | while (!(ADCSRA & (1 << ADSC))) |
32 | ;
|
33 | return ADC; |
34 | }
|
35 | |
36 | void debugadc(void) |
37 | {
|
38 | // _delay_us(1000);
|
39 | // convert();
|
40 | uint16_t x = convert(); |
41 | debug(x >> 8); |
42 | debug(x); |
43 | }
|
44 | |
45 | int main() |
46 | {
|
47 | PORTB = (1 << PB1) | (1 << PB4); |
48 | DDRB = (1 << PB1); |
49 | |
50 | DIDR0 = (1 << ADC3D); |
51 | ADMUX = (1 << MUX2) | (1 << MUX1); |
52 | ADCSRA |= (1 << ADEN); |
53 | ADCSRA |= (1 << ADPS1) | (1 << ADPS0); |
54 | _delay_us(1000); |
55 | convert(); |
56 | |
57 | while (1) |
58 | {
|
59 | PORTB &= ~(1 << PB4); |
60 | debug(0xFF); |
61 | debug(0xFF); |
62 | PORTB |= (1 << PB4); |
63 | |
64 | // VCC
|
65 | ADMUX = (1 << MUX2) | (1 << MUX1); |
66 | _delay_us(1000); |
67 | convert(); |
68 | debugadc(); |
69 | |
70 | // 2.56
|
71 | ADMUX = (1 << REFS2) | (1 << REFS1) | (1 << MUX2) | (1 << MUX1); |
72 | debugadc(); |
73 | |
74 | // 1.1 1x
|
75 | ADMUX = (1 << REFS1) | (1 << MUX2) | (1 << MUX1); |
76 | debugadc(); |
77 | |
78 | // 1.1 20x
|
79 | ADMUX = (1 << REFS1) | (1 << MUX2) | (1 << MUX1) | (1 << MUX0); |
80 | _delay_us(1000); |
81 | convert(); |
82 | debugadc(); |
83 | |
84 | _delay_ms(100); |
85 | }
|
86 | }
|
Ausgabe z.B.: FF FF 03 FF VCC = 5V ! 00 20 int. 2.56 V 80 mV 00 1D int. 1.1 V 31 mV 00 4D int. 1.1 V x20 4 mV FF FF 03 FF 00 2A 00 39 00 4C Hier stimmt was beim Umschalten auf VCC als Referenzspannung offenbar nicht. Die anderen Werte könnten stimmen, die Spannung ist ja ziemlich verrauscht und der ADC nicht so genau, insbesondere mit gain.
Der Fehler verschwindet, wenn als Zwischenschritt Gain abgeschaltet wird und eine Dummy-Wandlung ausgeführt wird.
Also nach // 1.1 20x erst umschalten zu // 1.1 1x
Die "debug()" find ich cool :)
Hab nen Moment gebraucht - soll ne Soft-Uart sein denk ich. (?)
Hast du die durchgeprüft? Ich hätte sonst Zweifel, dass das mit Blick
auf´s Timing so funktioniert.
Hast du an der anderen Seite einen USB<>UART Adapter? Könnte mir
vorstellen, der mag das so nicht.
>Hast du die durchgeprüft?
Ich mach das bei so was immer so, dass ich zum Test z.B. wie deine
"debug()" in ner Loop laufen lasse und das Argument von 0 bis 255 laufen
lassen.
Den Output fang ich in nem Hypertimal auf, speicher es als .txt ab und
mach das mit Excel auf. Die Daten dann in eine Spalte und in einer
Spalte daneben die Differenz bilden Diff = ((n - (n-1)) und 'davon'
einen Graphen darstellen. Wenn alles geklappt hat bekommt man eine
horizontale Linie mit der Amplitude 1 - so sieht man Ausreißer sofort :)
Jasson J. schrieb: > soll ne Soft-Uart sein denk ich. (?) > > Hast du die durchgeprüft? Ja, blöd benannt, kommt hier aus dem Forum. Klar, die übertragenen Daten sind ja plausibel, und zur Kontrolle sende ich auch immer bekannte Daten, hier die zwei 0xFF. Bei anderen AVRs bei anderer Temperatur und anderer Spannung und natürlich Takt wird es nicht ohne Anpassung gehen.
Es funktioniert leider immer noch nicht wie erwartet. Auch ohne Umschalten des Kanals oder der Referenzspannung erhalte ich ein falsches Ergebnis - evtl. das der letzten Wandlung, und nicht der aktuellen?! Irgendwo ist ein Dreher drin..
1 | // ATtiny85, 5V, 1MHz
|
2 | // PB4
|
3 | // PB3 -------------- GND
|
4 | // PB1 serial out:
|
5 | // 8N1, 38400 baud
|
6 | |
7 | #include "stdint.h" |
8 | #include "stdbool.h" |
9 | #include <avr/io.h> |
10 | #include <util/delay.h> |
11 | |
12 | void debug(uint8_t c) |
13 | {
|
14 | uint16_t d = 0b1000000000 | (c << 1); |
15 | while (d) |
16 | {
|
17 | if (d & 1) |
18 | PORTB |= (1 << PB1); |
19 | else
|
20 | PORTB &= ~(1 << PB1); |
21 | d >>= 1; |
22 | _delay_us((1e6 / 38400) - 12); // magic |
23 | }
|
24 | }
|
25 | |
26 | uint16_t convert(void) |
27 | {
|
28 | ADCSRA |= (1 << ADSC); |
29 | while (!(ADCSRA & (1 << ADSC))) |
30 | ;
|
31 | return ADC; |
32 | }
|
33 | |
34 | void debugadc(void) |
35 | {
|
36 | // _delay_us(1000);
|
37 | // convert();
|
38 | |
39 | uint16_t x = convert(); |
40 | debug(x >> 8); |
41 | debug(x); |
42 | }
|
43 | |
44 | int main() |
45 | {
|
46 | PORTB = (1 << PB1); |
47 | DDRB = (1 << PB1) | (1 << PB4); |
48 | DIDR0 = (1 << ADC3D); |
49 | ADCSRB = 0; |
50 | ADCSRA = (1 << ADEN); |
51 | ADCSRA |= (1 << ADPS1) | (1 << ADPS0); |
52 | ADMUX = (1 << MUX2) | (1 << MUX1); |
53 | _delay_us(1000); |
54 | convert(); |
55 | |
56 | while (1) |
57 | {
|
58 | |
59 | |
60 | debug(0xFF); |
61 | if(PORTB & (1 << PB4)){ |
62 | PORTB &= ~(1 << PB4); |
63 | debug(0x00); |
64 | }
|
65 | else{ |
66 | PORTB |= (1 << PB4); |
67 | debug(0xFF); |
68 | }
|
69 | |
70 | #if 0
|
71 | // VCC
|
72 | ADMUX = (1 << MUX2) | (1 << MUX1);
|
73 | debugadc();
|
74 | #endif
|
75 | |
76 | #if 1
|
77 | // 2.56
|
78 | // ADMUX = (1 << MUX2) | (1 << MUX1);
|
79 | // ADMUX |= (1 << REFS2) | (1 << REFS1);
|
80 | debugadc(); |
81 | #endif
|
82 | |
83 | #if 0
|
84 | // 1.1 1x
|
85 | ADMUX = (1 << REFS1) | (1 << MUX2) | (1 << MUX1);
|
86 | debugadc();
|
87 | #endif
|
88 | |
89 | #if 0
|
90 | // 1.1 20x
|
91 | ADMUX = (1 << REFS1) | (1 << MUX2) | (1 << MUX1) | (1 << MUX0);
|
92 | debugadc();
|
93 | #endif
|
94 | |
95 | _delay_ms(500); |
96 | |
97 | }
|
98 | }
|
Hatschi Puh schrieb: > falsches Ergebnis - evtl. das der letzten Wandlung, und nicht der > aktuellen?! Hatschi Puh schrieb: > while (!(ADCSRA & (1 << ADSC))) > ; S<43I$$%!
Hatschi Puh schrieb: > S<43I$$%! Ein typischer Fall von den Wald cor lauter Bäumen und so weiter. Ich hab sogar noch das Bit und Register im Datenblatt geprüft, aber das auch nicht gesehen. Funtkioniert es denn jetzt so wie gewollt?
Ich habe auch mal eine Differential-Messung mit T861 für eine direkte Strommessung gemacht. Dabei habe ich auch festgestellt dass die erste Messung nach dem Umschalten den Wert 0 liefern. Es funktioniert nur mit mehreren Dummy-Messungen oder mit einer Wartezeit nach dem Setzen des Mux. Seltsamerweise ist eine Wartezeit auch bei jeder Differential-Messung ohne Umschaltung nötig. Erst dann sind die Messwerte stabil. Ich hatte das schon mal hier beschrieben: Beitrag "ADC-Differential-Messung" Vielleicht hilft es auch, den ADC-Takt niedriger zu wählen. Ich werde die Messung noch mit dem T85 wiederholen, da wird wohl nichts anderes heraus kommen.
:) Ja, den T861 nutz ich auch gerade - heißes Gerät das Teil :>
Das war vorher der Test auf das Interrupt-Flag.. K. S. schrieb: > Funtkioniert es denn jetzt so wie gewollt? Nicht so richtig. Mit 20x gain geht er teils direkt an den oberen Anschlag, auch wenn vorher (1x gain) etwas am unteren Ende gemessen wurde. Aber in dem mV Bereich geht es auf dem Steckbrett nicht mehr so gut: ich sehe an den ADC-Werten, wenn ein anderer Pin ohne Last high gesetzt ist... An der Quellenimpedanz kann es eigentlich nicht liegen, da Werte hintereinander ähnlich sind (S&H umladen). Ergo: ich werde vorerst darauf verzichten. Aber falls ich mal eine Leiterplatte mache, guck ich es mir evtl. nochmal an. HermannW schrieb: > Wartezeit nach dem Setzen des > Mux. M.W. muss die nach der Dummy-Messung nach dem Setzen des Mux kommen, nicht dazwischen. Mag aber vom ADC abhängen. Jasson J. schrieb: > T861 Ist das ein T26 mit mehr Flash bzw. ein T85 mit mehr Pins?
Hatschi Puh schrieb: > Jasson J. schrieb: >> T861 > > Ist das ein T26 mit mehr Flash bzw. ein T85 mit mehr Pins? In erster Näherung ja, wobei intern noch Unterschiede da sind. Für einfache Aufgaben gehen dann beide. Der Tiny26 hat z.B. keinen Watchdog-Interrupt. Und andere Timer, weniger Interrupts und ist 8-10 Jahre älter. Ein kleiner '861 wäre der '261, mit weniger Flash, SRAM und EEPROM. Eher ist es ein Tiny85 mit mehr Pins, aber auch da gibt es funktionale Unterschiede bei den Timern und den Interrupts. Auch der ist etwas älter als der '861. Wie immer: Genaueres sagen die Datenblätter ... 😀
Hatschi Puh schrieb: > M.W. muss die nach der Dummy-Messung nach dem Setzen des Mux kommen, > nicht dazwischen Sag ich doch: erst den Mux setzen (z.B. Dummy-Messung), dann warten, dann die richtige Messung. Ich habe jetzt die Diffenential-Messung mit dem T85 getestet, erstmal nur den einen Kanal ohne Umschaltung. Die Wartezeit zwischen den Messungen (die ich beim T861 nötig hatte) war nicht nötig. Ich habe immer den Mittelwert aus 100 Messungen und den Max- und Min-Wert über RS232 an Hyperterm ausgegeben. Max-Min waren immer ca. 8 Rohwerte. Aber bei größeren Rohwerten (schon über 750) stieg die Streuung stark an. Bei 900 Rohwerten war Max-Min schon 40, egal welche Wartezeit. Das hatte ich auch beim T861 festgestellt: große Aussteuerung muss man vermeiden!
HildeK schrieb: > Wie immer: Genaueres sagen die Datenblätter ... 😀 Worüber sie aber nichts sagen, ist der Effekt, den Herrmann beschreibt und den ich beim Attiny 85 auch feststellte, als ich den internen Temperatursensor benutzte.
Hi >und den ich beim Attiny 85 auch feststellte, als ich den internen >Temperatursensor benutzte. Wie hast du ADC4 in im differentiellen Mode gemessen? Und das der interne Temperatursensor ein Schätzeisen ist, ist dir bekannt? MfG Spess
Spess53 schrieb: > Wie hast du ADC4 in im differentiellen Mode gemessen? Und das der > interne Temperatursensor ein Schätzeisen ist, ist dir bekannt? Das geht nicht! ADC4 ist immer im single mode. Ich habe ihn auch mal mitgemessen, weil ich demnächst die Temp-Abhängigkeit des ADC testen wollte. Man muss ihn schon kalibrieren. Aber für einfache Korrektuten reicht das vielleicht. Ich habe jetzt mal von Differential auf Single-Temperatur umgeschaltet. Jetzt wird eine Wartezeit wichtig. Ohne Dummy-Messung steigt die Unstabilität schon ab 500 Rohwerten an. Mit einer Dummy-Messung erst bei ca 750. Das liegt wohl auch daran, dass der Temperatur-Rohwert nur bei 270 liegt und die Kapazitäten umgeladen werden müssen. Ich hatte erwartet, dass ein niedrigerer ADC-Takt auch helfen würde. Das hat sich aber nicht gezeigt.
Hi
>Das geht nicht! ADC4 ist immer im single mode.
Das weiß ich selbst. Die Frage war auch an Datenblatt-Idealist (Gast)
gerichtet.
MfG Spess
Ich finde diesen Thread übrigens sehr interessant. Hatte vor ein paar Tagen eine ähnliche Kopfnuss mit der USI als SPI, wo ich mich gefragt habe, ob sich das komische Verhalten nicht ändert, wenn man den Quelltext einfach lange genug hart genug anstarrt :> In meinem Fall war eher die Lösung, dass Gesamtsystem härter an zu starren und was zu ändern :)
Spess53 schrieb: > Hi > >>Das geht nicht! ADC4 ist immer im single mode. > > Das weiß ich selbst. Die Frage war auch an Datenblatt-Idealist (Gast) > gerichtet. > > MfG Spess Hm... Das weißt Du selbst. Nun gut -dann frag mich nicht und versuche mir nicht, eine Frikadelle ans Bein zu nageln, o.k.?! @Hermann Ich stellte diese Nichtlinearität fest, als ich einen Thermostaten mit dem Attiny85 und dessen internem Geber für den Istwert benutzte. Sollwert gab ich von außen über Potentiometer mit Vorwiderstand als Spannungsteiler für 5V zu 1,1 V vor, da diese Referenzspannung ja nicht nach außen geführt werden kann. Da aber alle Kanäle nur zum gleichen Wandler gemultiplext durchgeschaltet werden, stimmt das Verhältnis zwischen Soll- und Istwert wieder, wenngleich die Poti-Skale diese Nichtlinearität deutlich widerspiegelt.
Datenblatt Idealist schrieb: > @Hermann > Ich stellte diese Nichtlinearität fest, als ich einen Thermostaten mit > dem Attiny85 und dessen internem Geber für den Istwert benutzte. Ich habe aber nur von den Abtastproblemen und dem begrenzten Messbereich bei der Differential-Messung berichtet. Der Temperatursensor ist ein anderes Problem. Im Datenblatt schreiben sie nur von Offset und Steigung, die man kalibrieren sollte und der Verlauf sei angeblich linear. Dass du auch Nichtlinearitäten feststellst, klingt nicht so toll. Das werde ich noch in meinem Thermoschrank überprüfen.
Datenblatt-Idealist schrieb: > HildeK schrieb: > >> Wie immer: Genaueres sagen die Datenblätter ... 😀 > > Worüber sie aber nichts sagen, ist der Effekt, den Herrmann beschreibt > und den ich beim Attiny 85 auch feststellte, als ich den internen > Temperatursensor benutzte. Ich habe nur auf diese Frage geantwortet: Hatschi Puh schrieb: > Ist das ein T26 mit mehr Flash bzw. ein T85 mit mehr Pins? Und da sagt das Datenblatt schon viel dazu aus!
Hi > Nun gut -dann frag mich nicht und versuche mir >nicht, eine Frikadelle ans Bein zu nageln, o.k.?! Hast du womöglich selbst gemacht. Aus deinen Ausführungen ist nicht ersichtlich welchen der drei ADC-Mode du benutzt ( Single- Ended, Unipolar- oder Bipolar Mode). Entspreche dieser Modes ergeben sich auch recht unterschiedliche Werte für Gain- und Offset Error (siehe Datenblatt ATTiny: 21.7 ADC Characteristics) . Dazu kommen noch Z.B. noch Nichtlinearitäten bei deinen Potis ( eine 'Poti-Skale' ist nicht besonders assagekräftig) ... Genausowenig ist das Ganze ohne Schaltbild und Programm. MfG Spess
Spess53 schrieb: > Hi > >> Nun gut -dann frag mich nicht und versuche mir >>nicht, eine Frikadelle ans Bein zu nageln, o.k.?! > > Hast du womöglich selbst gemacht. > > Aus deinen Ausführungen ist nicht ersichtlich welchen der drei ADC-Mode > du benutzt ( Single- Ended, Unipolar- oder Bipolar Mode). Ich muss für den internen Sensor (Kanal 15) Single-ended verwenden und verwende das genauso auch für den Kanal 1, an dem ein lineares 10K Potentiometer mit einem 39K Widerstand gegen +5V hängt. Warum? Weil ich die Spannung an ADC1 im gleichen Maß einstellen können muß, wie sie auch der interne Sensor liefert, der an 1,1V Referenzspannung hängen muss > Entspreche > dieser Modes ergeben sich auch recht unterschiedliche Werte für Gain- > und Offset Error (siehe Datenblatt ATTiny: 21.7 ADC Characteristics) . > Eben diese Angaben kann man in der Pfeife rauchen. 2 Attiny 85 und ein 25 liefern bei gleichen Voraussetzungen unterschiedlichste Resultate. > Dazu kommen noch Z.B. noch Nichtlinearitäten bei deinen Potis ( eine > 'Poti-Skale' ist nicht besonders assagekräftig) ... Das Poti ist linear zum Drehwinkel. Das habe ich gemessen Gut nun. Mir ging es nur darum, diese Datenblatt-Gläubigkeit ein wenig ins Wanken zu bringen und nur das zu glauben, was man selbst festgestellt hat.
Hi > 2 Attiny 85 und ein 25 liefern bei gleichen Voraussetzungen unterschiedlichste >Resultate. Gibt es endlich mal kongrete Zahlen oder ist das alles nur Gewäsch? MfG Spess
Spess53 schrieb: > Hi > >> 2 Attiny 85 und ein 25 liefern bei gleichen Voraussetzungen unterschiedlichste >>Resultate. > > Gibt es endlich mal kongrete Zahlen oder ist das alles nur Gewäsch? > > MfG Spess Ganz kongret (sic) Wegen Deines Verlangens werde ich ganz sicher keine Maschine auseinandernehmen, um die dort eingebaute Schaltung zu vermessen um Dir die ADC-Werte zu kredenzen! Probier es selbst aus, dann hast Du Deine Werte. Ende der Durchsage.
Hi >Wegen Deines Verlangens werde ich ganz sicher keine Maschine >auseinandernehmen, um die dort eingebaute Schaltung zu vermessen um Dir >die ADC-Werte zu kredenzen! Die Antwort habe ich fast erwartet. >Probier es selbst aus, dann hast Du Deine Werte. Womit? Ich habe zwar ca. 100 AVRs herum liegen, aber keinen ATTiny2/4/85. Und nur weil du solche Behauptungen aufstellst werde ich mir keinen kaufen. MfG Spess
Datenblatt Idealist schrieb: > Ich stellte diese Nichtlinearität fest, als ich einen Thermostaten mit > dem Attiny85 und dessen internem Geber für den Istwert benutzte. Da das Datenblatt sagt, der interne Temp-Sensor sei linear, habe ich das mal beim T85 nachgemessen. Der Sensor ist bei meiner Messung sehr schön linear (siehe Bild). Die minimalen Abweichungen von der Gerade liegen an der Auflösung von nur einem Grad. Die Steigung und den Offset muss man individuell bestimmen, da sie erheblich vom Dabla abweichen (siehe Regressions-Koeffizienten). Dann kann man den Sensor gut z.B. für die Korrektur der Vref oder des RC-Oszi verwenden.
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.