Hi @all,
ich hab mal kurz eine frage bzw. breuchte mal euren Rat. Ich hab mir den
ADC wie im ACC-tutorial beschrieben initiealisiert (Aussenbeschaltung
und Refferenzspannung sind auch richtig).
ADC C-code:
1
#include"global.h"
2
3
voidadc_init(void)// (Hinzugefügt 20.06)
4
{
5
uint16_tresult;// Zwischenwariable für das erste Auslesen wird dan verworfen
6
7
ADMUX|=(1<<REFS0);// AVcc als Referenzspannung nutzen (5V)
adcwert1=adc_lesen(1);// ADC Kanal 1 (Representativ für Ieff) Wert in adcwert laden
5
Ihilf=(adcwert1*5.0)/1024;// Ihilf kriegt Wert von adcwert
6
Ieff=(Ihilf*0.1);// Ihilf durch 10 wegen verstärkung vom differenierer
wenn ich mir beide werte gleichzeitig ausgeben lasse merke ich das die
Werte nicht stimmen da ich dierekt an den Pins mal nachgemessen habe.
Ich hab auch schon gelesen das es dabei zu problemen kommen kann so das
die Werte nicht stimmen.
Kann mir jemand einen rat geben wie ich das beheben kann? die interrupts
sind bei der Berechnung und ausgabe ausgeschaltet die Globalen da es da
probleme mit einer anderen Berechnung gegeben hat. Ich danke schon mal
für eure Hilfe.
mfg
m.s.
Achso anzumerken sei noch mit Ueff und Ieff rechne ich weiter die werden
eigentlich nicht ausgegeben hab das nur mal zu testzwegken gemacht da
mir das komisch vorkamm.
m. S. schrieb:> ADMUX |= (ADMUX & ~(0x1F)) | (Kanal & 0x1F);
Wieso maskierst Du ADMUX mit 0x1f? Ich würde schreiben:
ADMUX |= Kanal & 0x0f;
Mit der Maskierung löschst Du REFS0, REFS1 und ADLAR.
Grüße, Kurt
Schaltplan ? Innenwiderstand der Signalquelle, Wie ist Avcc gefiltert,
wie wird die Bandbreite des Signals begrenzt, wie ist die Ground plane
gelegt bzw. wie sieht das Layout aus ? Was heißt gleichzeitig ausgeben ?
Avcc mit LC siehe Datenblatt ATmega8 seite 200. Bei dem Signal handelt
es sich um Gleichgerichtetes Signal.
Es handelt sich nur um ein Programmiertechnisches porblem, denke ich.
Ich meinte nacheinander. Nicht gleichzeitig, sorry.
Eigentlich solte die ausgabe so aussehen:
1
2
adcwert0=adc_lesen(0);// ADC Kanal 0 (Representativ für Ueff) Wert in adcwert laden
war auch ein Denfehler. Aber verwirrend und überflüssig ist der ADMUX &
... schon :-)
Du sprichst von "gleichgerichtet". Messen tust Du natürlich den
momentanen Wert, und das für Kanal 0 und Kanal 1 mit evtl. merklichem
Abstand.
Grüße, Kurt
Ja messe tu ich einen momentanen Wert. An ADC0 liegt eine Gleichspannung
an wenn ich gerade mal messe 456mV an ADC1 liegen 860mV an.
Wenn ich mir nur den ADC0 Spannungswert anzeigen lasse über Hyper
Terminal (Die zeile mit adcwert1 = adc_lesen(1) Auskommentiert) zeigt er
mir auch die 456mV an nicht exkt aber tolerier bar genau.
Wenn ich mir aber wie in dem nachfolgenden Code gerade zu sehen beide
ADC Werte nacheinader ausgeben lasse, ist der eine Ausgabe wert für Ueff
(ADC0) 0,8496mV und der Wert für Ieff (ADC1) 0,8594mV.
Ihrgend wie scheinen die Beiden Werte zusammen zuhängen. Achso ich
arbiete übrigens mit 16MHz Taktung für den µC.
Ich weis aber nicht wie ich die unabhängig voneinander machen kann.
Zudem Zeitpunkt wo ich die Berechnungen mache und die Ausgabe sind
nemlich alle Interrupts aus. Da es mit einer anderen Berechnung probleme
gegeben hat.
1
#include"global.h"
2
3
4
intmain(void){
5
// DDRB |= (1<<DDB0);
6
adc_init();// Funkt. Aufruf ADC initialisierung
7
uart_init();// Funkt. Aufruf UART initialisierung
8
INTRUP_frei();// Funkt. Aufruf Funktion zur Initialiesierung der INT0 & INT1 interrupts
9
sei();// Globale Interrupts freigeben
10
11
while(1)
12
{
13
if(fertig==1)
14
{
15
16
T0=(k*256)+TCNT0;// Wert ermittelung für T0 mit exaten Werten schiften <<8 = *256
17
T2=(j<<8)+TCNT2;// Wert ermittelung für T2 mit exaten Werten
18
PHI=((T2+0.0)/T0)*360.0;// Errechnung von Phi in Grad
19
20
adcwert0=adc_lesen(0);// ADC Kanal 0 (Representativ für Ueff) Wert in adcwert laden
fertig=1;// (Hinzugefügt 20.06)Variable zur Berechnung und dann Ausgabe
73
cli();// Ausschalten der Interrupts
74
start=1;
75
}
76
}
77
78
79
ISR(INT1_vect)
80
{
81
TCCR2&=~(1<<CS20);// Timer2 anhalten
82
}
83
84
ISR(TIMER0_OVF_vect)
85
{
86
k++;// Inkrementieren des Überlaufzählers
87
}
88
89
ISR(TIMER2_OVF_vect)
90
{
91
j++;// Inkrementieren des überlaufzählers
92
}
Die Timer arbeiten auch richtig wie sie sollen ich komme ja in die
Ausgabe rein also in if(fertig == 1).
Die Ausgabe der Timer ist auch richtig gerade gucke ich sie mir bloß
nicht an da ich weis das das past.
Also ich weis momentan nicht Wirklich weiter.
mfg
m.s.
while((ADCSRA&(1<<ADIF))==0)// Warten bis Konvertierung fertig
2
{}
hast du so aus dem AVR-GCC-Tutorial? Glaub ich nicht. Und der
Unterschied zur Tutorialversion ist wichtig!
Einfach mal drüber nachdenken, wann eigentlich Interrupt Flags wieder
gelöscht werden. Hinweis: Das erneute Starten des ADC tut es nicht.
Kurt Harders schrieb:> war auch ein Denfehler. Aber verwirrend und überflüssig ist der ADMUX &> ... schon :-)
verwirrend vielleicht.
Aber überflüssig: ganz im gegenteil
Ne das habe ich nicht aus dem Tutorial das habe ich aus: AVR-RISC
Embedded Software selbst entwickeln (von Roman Mittermayer Seite 87).
Ich hab das jetzt mal geendert aber es hat keine auswirkung auf das
Ergebnis es ist immer noch das selbe problem.
Mir ist auch schon aufgefallen wenn ich das Programm auf den µC lade das
die erste Ausgabe ans Hyper Terminal anscheinet richtig ist also die
Werte entsprechen so ungefähr dem was auch anliegt. Der rest dann aber
nicht mehr.
mfg
m.s.
m. S. schrieb:> Ne das habe ich nicht aus dem Tutorial das habe ich aus: AVR-RISC> Embedded Software selbst entwickeln (von Roman Mittermayer Seite 87).
Ist trotzdem Unsinn.
Es sei denn der Autor kümmert sich in seinem Code irgendwo darum, dass
das Interrupt Flag wieder zurückgesetzt wird oder aber er macht das
Auslesen das ADC Ergebnisses per Interrupt.
> Ich hab das jetzt mal geendert aber es hat keine auswirkung auf das> Ergebnis es ist immer noch das selbe problem.
OK. Dann suchen wir weiter nach dem nächsten Problem.
Wie ist dein Signal angekoppelt?
Jetzt könnte das Problem ins Spiel kommen, von dem Knut schon gesprochen
hat. Nach dem Umschalten des Kanals muss sich die Sample&Hold Stufe erst
mal auf die neue Spannnung einstellen, was auch ein wenig Zeit benötigt.
Du könntest nach dem Einstellen des Kanals in ADC_Read eine kleine Pause
einlegen
Oder überhaupt immer 2-mal samplen und die erste Messung verwerfen.
Das ist jetzt allerdings ein Schuss ins Blaue, denn ob das das Problem
ist, hängt davon ab, wie deine Aussenbschaltung an den ADC Eingängen
aussieht und wie hochohmig die ist.
Also der ADC1 Wert den ich mir gerade ausgeben lasse ist 0.8594mV
gemessen mit Digitalmultimeter sind es 0,871mV.
Hab auch gerade ein Delay eingebaut über _delay_ms(1000); zwischen den
einzelnen adclese() aufrufen. Kein unterschied.
mfg
m.s.
m. S. schrieb:> Also der ADC1 Wert den ich mir gerade ausgeben lasse ist 0.8594mV> gemessen mit Digitalmultimeter sind es 0,871mV.>> Hab auch gerade ein Delay eingebaut über _delay_ms(1000); zwischen den> einzelnen adclese() aufrufen. Kein unterschied.
Nicht zwischen den Aufrufen. Dort bringt er nichts.
Du brauchst IM ADC_Read eine kleine Pause (wenn die Vermutung stimmt).
Hier
ADMUX |= (ADMUX & ~(0x1F)) | (Kanal & 0x1F); // Kalnal Auswahl ohne
stellst du den nächsten ADC Kanal ein. Und zwischen diesem Zeitpunkt und
dem hier
ADCSRA |= (1<<ADSC); // Eine Wandlung "singel conversion"
muss die Sample&Hold Stufe in der Lage sein, die extern anliegende
Spannung auch 'anzunehmen'.
Also direckt vor den ADC Eingängen ist jeweils ein Verbesserter
Scheitelwertmesser (Tietze Schenk 13 Auflage seite 1029). Dessen Ausgang
praktisch aus einem Impedanzwandler kommt mit einem Widerstand am
Ausgang (Intern) von 200 Ohm.
@ Karl meinst du dierekt in adc.c oder nach dem adcwert0= adclesen(0).
Mit dem zwei mal sempeln wie meinst du das könntest du das vielleicht in
ein Code beispiel packen das ich mir das mla anschauen kann. oder meinst
du bei jeder messung den timer neu initialiesieren.
mfg
m.s.
Sorry das das gedauert hat. Bin eben erst zuhasue angekommen. Noch eine
kleine korrecktur muß ich sagen die mV werte vorhin sollen natürlich V
werte sein. Ich hoffe das o.k. wenn ich die als .c dateien hochlade.
mfg
m.s.
OK. sieht nicht schlecht aus (bis auf die cli() / sei() Steuerung, aber
das sollte jetzt erst mal nichts damit zu tun haben). Die 10 Sekunden
delay sollten auf jeden Fall reichen :-)
Wie ist dein AREF Pin beschaltet?
Ich hege zwar keine große Hoffnung, aber probiers mal so
1
adcwert0=adc_lesen(0);// ADC Kanal 0 (Representativ für Ueff)
2
adcwert0=adc_lesen(0);// ADC Kanal 0 (Representativ für Ueff) Wert in adcwert laden
adcwert1=adc_lesen(1);// ADC Kanal 1 (Representativ für Ieff)
7
adcwert1=adc_lesen(1);// ADC Kanal 1 (Representativ für Ieff) Wert in adcwert laden
8
Ieff=(adcwert1*5.0)/1024;// Ihilf kriegt Wert von adcwert
also 2 mal auslesen und den jeweils ersten Wert verwerfen.
Ich denke aber eher, dass du ein Harware-Problem hast (wenn ich nicht
etwas grundlegendes im Code übersehen habe)
Das werde ich morgen mal probieren zuhause geht das schlecht. Im Anhang
mal der eagle plan wie er uhr sprünglich mal gewesen ist. ICh weis das
da sind fehler in der µC beschaltung dahingehend das pin2 auf bin pin32
gelegt wurde und pin9 auf pin1. Der rechte schaltungsteil existiert so
nicht mehr da er nicht mehr funktioniert hat und ich es aber ähnlich
nachgebaut habe von daher passt das einegtlich noch auch wenn sich die
OPVs bischen geendert haben.
mfg
m.s.
Habs gerade ausprobiert hatt nicht geklapt. Ich werde mir mal einen
neuen code erstellen in dem ich nur den ADC verwende und sonst nichts
weiter mache.
Malschauen vielleicht stoße ich ja dann auf das problem bzw. auf eine
lösung.
mfg
m.s.
m. S. schrieb:> /* Nach der Aktivierung des ADC wird ein "Dummy-Readout" empfohlen, man liest> also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
... Nicht nur empfohlen, sondern notwendig. Und auch nach jeder
Kanalumschaltung, wenn ich mich nicht irre. (Das hab' ich bei dir nicht
gefunden.)
Weiss nicht ob das Teil des Problems ist,
aber ich würde diese Zeile ändern von
ADMUX |= (ADMUX & ~(0x1F)) | (Kanal & 0x1F);
in
ADMUX = (ADMUX & ~(0x1F)) | (Kanal & 0x1F);
Scheis auf Spiderman und Superman. Ziegenpeter ist der neu Held am
firnament. Das steht sogar so im Tutorial und ich hab das überlesen
sorry. Aber danke an alle die mir geholfen haben. ziegenpeter du hast
was gut bei mir ( Eigentlich Ihr alle für eure hilfe). Ich werde mal
paar messungen machen um das ergebnis zu veriffiezieren aber ich denke
das solte passen.
Noch mal danke an alle Ihr seit die besten. Jetzt kann ich wider berüigt
schlafen.
mfg
m.s.
Naja ist noch einiges zu machen. Ist ja erst halb eins. Aber die
schaltung funktioniert das programm auch. Jetzt geht es halt weiter dir
auch noch viel erfolg bei dem was du machst.
mfg
m.s.