PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ADC im Free-Run Modus



Che Guevara
20.07.2010, 22:17
Hallo Leute,

wollte mal versuchen, mit meinem ADC ein eher höher frequentes analoges Signal auszulesen, indem ich den ADC im Free-Run Modus laufen lasse und nur die höherwertigen 8 Bits auslese, allerdings funktioniert das nicht...

Hier mal mein Code:


$regfile = "m32def.dat"
$crystal = 16000000
$framesize = 80
$hwstack = 80
$swstack = 80
$baud = 19200


Admux = &B01100000
Adcsra = &B11000110

config pina.0 = input
porta.0 = 0

dim wertl as byte
dim werth as byte


enable interrupts


do

wertl = adcl
werth = adch
print wertl
print werth

loop

end


Sowohl im Simulator, als auch in Echt funktioniert das ganze nicht :(
Der eine Wert (entweder ADCH oder ADCL, weiß ich grad nicht) geht immer bis 256 und fängt dann wieder bei 0 an, das ganze 4 mal, also 4*256=1023.
Der andere Wert zählt nur von 0 bis 3.

Was genau mache ich den falsch? Hab die einzelnen Bits nach dem Datenblatt des Mega32 gesetzt. Aber irgendwo hab ich anscheinend einen Fehler drin?!

Der Prescaler ist momentan auf 64, glaub ich (aber das sollte jetzt nicht so wichtig sein). Die Bits für Interrupt hab ich glaub ich beide auf 0 oder 1 gesetzt, da ich keinen Interrupt benötige.

Wäre nett, wenn jemand mal den Code im Simulator probieren würde und mir sagen könnte, was ich falsch gemacht habe?!

Vielen Dank, Gruß
Chris

radbruch
20.07.2010, 22:50
Hallo

Richtig flott wird es erst mit Prescaler /2 ;) Das schafft ein Mega32 mit 8MHz in Bascom:

http://i1.ytimg.com/vi/H-p-W9r-_Vk/2.jpg (http://www.youtube.com/watch?v=H-p-W9r-_Vk)
(Filmchen aus https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=434274#434274)

Mein Lieblingsthema...

Ich hatte hier mal nach den Samplezeiten bei den AVRs nachgefragt:
https://www.roboternetz.de/phpBB2/viewtopic.php?t=33070

btw bin ich zu faul dein unkommentiertes Progrämmchen zu analysieren....

Gruß

mic

Kampi
21.07.2010, 07:48
Also ich habs mal im Simulator getestet. Und bei mir läuft das Programm. Es wird mir für wertl 255 ausgegeben und für werth 3 (wenn ich im Simulator den ADC auf 1023 stelle).
Was genau meintest du jetzt, was da nicht funktionieren soll?

Richard
21.07.2010, 09:50
Das ist ja auch richtig, L byte 255 + 1 (übertrag) + H byte 3*(1+255)
ergeben 1024. "3" im H byte bedeutet ja 3 * L byte + 1*L Byte....

Gruß Richard

Kampi
21.07.2010, 10:08
Ja deswegen versteh ich die Frage auch nicht só ganz 8-[
Für mich macht das Programm den Eindruck als ob es ordnungsgemäß funktioniert O:)

Richard
21.07.2010, 10:37
Ja deswegen versteh ich die Frage auch nicht só ganz 8-[
Für mich macht das Programm den Eindruck als ob es ordnungsgemäß funktioniert O:)

Möglich das der Poster nicht so recht weiß wie digital gezählt
wird. Sehr oft werden ja auch H-Byte und L Byte getauscht
gespeichert/ausgewertet dann wird das noch schwieriger zu
überblicken....

Speicherplatz 1= 3* 256 ( H-Byte)
Speicherplatz 2 = 1 * 256 ( L Byte )

Gerechnet wird aber andersherum Sp2 + ( Sp1 * 256) jetzt
komme ich schon selber ins schleudern. :-)

Gruß Richard

Kampi
21.07.2010, 10:48
Ja, das ist nunmal das Problem an den Berechnungen mit Bytes und Bits. Man muss da sehr genau sein sonst passieren da sehr schnell Fehler..... . Merk ich leider auch immer wieder. Beste Beispiel ist zwei Zahlen addieren, da bin ich gestern auch durcheinander gekommen mit der arethmetischen Addition (1+1 = 0 und 1 Übertrag) und der logischen Addition (also UND 1+1 = 1) :^o

Aber was ich jetzt nicht ganz verstehe.
Die Zeile Adcsra = &B11000110 konfiguriert ja das Special FUnction Register des ADCs. Laut Datenblatt ist das 7. Bit für das An-und Abschalten des ADCs da.

• Bit 7 – ADEN: ADC Enable
Writing this bit to one enables the ADC. By writing it to zero, the ADC is turned off. Turning the
ADC off while a conversion is in progress, will terminate this conversion.
Aber wenn ich das Bit auf Null setze, also wenn ich schreibe:
Adcsra = &B01000110
und dann die Simulation starte gibt er mir trotzdem nochwas über UART aus.
Ist das jetzt ein Simulationsfehler oder muss da noch ein Bit gesetzt werden?

Richard
21.07.2010, 11:34
Alter Wert, Zufallswert...? Da wird ja eher nur die/eine neue
Wandlung gestartet/gestoppt. Denke ich jetzt mal (einfach).

Gruß Richard

Che Guevara
21.07.2010, 14:36
hallo Leute,

danke erstmal für die große Anzahl an Antworten!

Also prinzipiell muss ich sagen, dass ich eig. schon weiß, wie digital gezählt wird.
Vielleicht reden wir hier aber aneinander vorbei?!
Wenn ich im Simulator den ADC auf 1023 stelle, kommt bei print 255(was ja richtig ist). Bei 0 im Sim kommt 0, was auch stimmt! Allerdings:
Stellt doch im Sim den ADC mal auf 511 (nur 1 Beispiel). Dann kommt wieder 255 raus und sobald man den ADC auf 512 stellt, beginnt das ganze wieder bei 0.
Aber das sollte doch nicht so sein, oder täusche ich mich da? Ich habe mir das so vorgestellt (und bis jetzt auch immer so aufgefasst), dass wenn ich nur die höheren 8Bit nehme, das dann das ganze einfach nur um die 2 unteren Bits (welche ich dann eben wegschneide/ignoriere) ungenauer wird, also dann der ADC nicht mehr mit 0,00488758 auflöst, sondern mit 0,01953125 Schritten.
Demnach sollte dann der ADC-Wert von 511 nicht 255, sondern 255/2=128 entsprechen, oder hab ich da einfach nur ein grundlegendes Verständnisproblem?

@radbruch:
WAS soll ich den an diesem Programm noch groß kommentieren?? Es werden nur 2 Bytes deklariert und diese werden dann in einer Endlosschleife immer wieder neu mit ADCL/H überschrieben. Verstehst du das nicht?

Gruß
Chris

Kampi
21.07.2010, 15:12
Ich glaube du hast da ein Verständnissproblem. Wenn du im Bascom einen Wert von 300 einstellst zählt das Programm das ADC L-Register bis 255 voll. Sobald dieses voll ist wird es auf 0 zurück gesetzt und das ADC H-Register wird um eins erhöht. Nun hast du einen Rest von 300-255 = 45.
D.h. du hast den Registerinhalt von ADC L = 45 und ADC H = 1
Wenn du jetzt ein Beispiel wie deine 511 hast dann geht das ganz glatt auf d.h. es wird bis 255 gezählt dann wird das H Register um eins erhöht dann bleibt noch ein Rest von 255 über und sobald das L Register wieder voll ist wird H auf 2 gesetzt.
Also hast du bei einem Wert von 511 L = 0 und H = 2
Sobald du das dann wieder umrechnest also Zahl = (L + (255 x H)) + 1 dann kommt bei:
Zahl = (0 + (255 x 2)) +1
Zahl = 511

BMS
21.07.2010, 15:38
Nein, man rechnet es folgendermaßen um:
Zahl = 256*HighByte + LowByte

@kampi: Nimm mal die Zahl 512. Das obere Byte hat dann den Inhalt 2, das untere Byte ist auf Null. Mit deiner Formel gäbe das (0+(255*2))+1=511
kann also nicht sein. =P~

Du kannst das Problem umgehen, indem du im Register ADMUX das ADLAR-Bit setzt. Dann werden die Zahlen linksbündig gespeichert, d.h.
die 8 höchstwertigen Bits in ADCH und die zwei restlichen in ADCL.
Schau mal im Datenblatt auf Seite 215 (untere Hälfte).
Für 8 Bit Auflösung reicht es, das Register ADCH auszulesen. Dann ist die Umrechnung sowieso unnötig.

Kampi
21.07.2010, 15:45
Ja ok. Tut mir leid hab einen kleinen Fehler gemacht O:)

PICture
21.07.2010, 16:13
Hallo!

@ Che Guevara

Wenn dir um Oversampling periodichen, sich wiederholenden Signalen geht, darf der ADC nicht freilaufen, sondern das nächste Sample muss immer um gleiche bestimmte Zeit gegen der voherigen veschoben werden.

Das geht nur mit einer permanenter Samplingfrequenz, die ein bißchen kleiner als vom gesampelten Signal ist. Beispielweise um 20 Samples zu bekommen, muss die Samplefrequenz 0,95 der von gesampelnden Signal sein. Dazu wird oft PLL benutzt um den Takt des ADC's an Signalfrequenz anzupassen.

MfG

Kampi
21.07.2010, 20:06
Also ich habe gerade ein bischen mit meinem Mega32 experimentiert und dabei festgestellt das du mit deinem Programm nur eine Wandlung machst. Will heißten du flasht den Chip und sobald Spannung anliegt (direkt nach dem Flashen z.B.) beginnt er das Programm abzuarbeiten. Dabei startet er durch das beschreiben der Register eine Wandlung und speichert das Ergebniss ab. In deinem Programm machst du nichts anderes als eine Endlosschleife wo der Controller den Registerinhalt in die Variablen schreibt. Aber selbst wenn du den Spannungswert am ADC änderst wird er keinen neuen Wert in die Register schreiben, weil der Controller keine neue Wandlung beginnen wird da er nicht die nötigen Befehle dazu erhält.

Che Guevara
21.07.2010, 21:07
@BMS: Du bist der erste, der versteht was ich meine :)
Allerdings hab ich ADLAR gesetzt, aber es funktioniert nicht!

@PICture: An das hab ich schon gedacht, ich möchte einfach das ADCh-Register
in einer Timer_isr auslesen, da ich eine Spannungskurve aufnehmen möchte und dann an den PC schicken, der mir das ganze dann zeichnet.

@Kampi: Wenn ich das Prog im Sim. laufen lasse, werden die Werte aber schon bei jederÄnderung des ADCs geändert, bist du sicher, dass du nicht irgendwo einen Fehler drin hast?
Oder wie sollte ich deiner Meinung nach eine Wandlung anstoßen?
Wenn dem aber wirklich so sein sollte, dass ich das immer anstoßen muss, warum nennt sich das dann "Free-Run"? Ich dachte, weils die ganze Zeit selbstständig Messungen durchführt
oder täusche ich mich da?

Gruß
Chris

Kampi
21.07.2010, 21:35
Naja zum einen ist ein Simulator =/= Realität. Der Simulator checkt es auch nicht das ich das ADC-Enable Bit auf 0 setze.....er macht trotzdem eine Wandlung :-s
Und ja ich bin mir ziemlich sicher. Ich habe dein Programm kopiert und es auf mein RN-Control aufgespielt. Als ich dann mit einem Widerstand eine Verbindung von GND zu ADC.0 gesteckt habe und das Programm aufgespielt habe hat mir TeraTerm eine 0 angezeigt. Sobald ich den Widerstand zwischen Vcc und ADC.0 gesteckt und es nochmal aufgespielt habe kam der maximal Wert vom ADC raus.
Das Problem an deiner Variante ist das es ein bestimmtes Register gibt. Sobald dieses Register auf 1 ist wird eine Wandlung gestartet. Dieses Bit wird nach einer Wandlung hardwarebedingt auf 0 gesetzt d.h. um eine neue Wandlung zu starten muss das Bit wieder auf 1 gesetzt werden. Und dies scheint der Simulator im Bascom auch nicht so zu peilen.
Du hast ja folgende Bitfolge:
Adcsra = &B11000110
Das 7. Bit ist dafür da den ADC zu aktivieren. Sobald das 0 ist ist der ADC aus. Das 6. Bit ist dafür da eine Wandlung zu starten. Sobald es 1 ist wird eine Wandlung gestartet und nach der Wandlung durch die Hardware auf 0 gesetzt.
Sowas kannste am besten live mal ausprobieren, weil ich hab die Erfahrung gemacht das man in solchen Sachen dem Simulator nicht trauen kann. Und wenn du mal genauer drüber nachdenkst ist das auch logisch das er nur eine Wandlung macht, weil das Bit für die Wandlung halt nach der Wandlung 0 wird und nirgends neu gesetzt wird. O:)
Im Free-Run Modus macht der ADC die ganze Zeit Wandlungen. Nur der Unterschied zu dem Single-Shot Modus ist das er bei dem Single-Shot Modus nach jeder Wandlung die, durch die Wandlung erzeugten Bytes umwandelt und evtl. ausgibt. Dieser Vorgang verbraucht vieeeeeeeeeeeeeeel Zeit.
Im Free-Run Modus ist das anders. Da macht er auch die ganze zeit Wandlungen nur er verarbeitet das Ergebniss nicht weiter. Er verarbeitet es nur weiter wenn du es möchtest. Wenn du mal unten im Simulator schaust siehst du wieviele Taktzyklen so eine einfache "Print" Ausgabe braucht (sind glaub ich ein paar 3000 Zyklen wenn ich mich nicht vertan habe heute Mittag). Und wenn du nun ein Hochfrequentes Signal sampeln willst z.B. bei der Digitalisierung von Musik ist es natürlich richtig dumm wenn du nach jeder Wandlung 3000 Zyklen extra brauchst um das Ergebniss zu haben. In so einem Fall lässt du den ADC im Free-Run Modus laufen und nach sag ich mal 1 Minute machst du eine Pause und verarbeitest den ganzen Stabel an Bytes in einem Rutsch weiter.
Danach startest du ein neues Sampling. Der Vorteil ist halt das der ADC quasi seine eigene "Geschwindigkeit" selber vorgibt und nicht durch sowas lästiges wie einen "Print" Befehl behindert wird.
Ach und zu dem Bit ADLAR. Das hier steht in der Doku:
"Das Bit ADLAR legt fest, ob das Ergebnis der AD-Umsetzung linksbündig (ADLAR=1,
xxxxxxxxxx000000) oder rechtsbündig (ADLAR=0, 000000xxxxxxxxxx) im 16-Bit Ergebnis
abgelegt wird".
Und das es nicht funktioniert hat liegt sicher auch am Simulator :-b

So ich hoffe das ist soweit alles schlüssig und verständlich und vorallem richtig! Hab die ganzen Sachen mit Hilfe der Datenblätter und einer netten Doku aus dem Internet über den ADC des Mega32 erarbeitet.

So hier mal die Doku:
http://www.ckuehnel.ch/Download/megaAVR%20ADC.pdf

Und hier mal das "überarbeitete" Programm


'Controller
$regfile = "m32def.dat"
$crystal = 16000000
$baud = 9600

'Stacks
$framesize = 80
$hwstack = 80
$swstack = 80

'Variablen
Dim Wertl As Byte
Dim Werth As Byte

Config Pina.0 = Input
Porta.0 = 0

Enable Interrupts

Do
Admux = &B01100000
Adcsra = &B11000110

'Übergabe der Registerinhalte in Variablen
wertl = adcl
Werth = Adch

'Ausgabe der beiden Registerwerte
Print Wertl
print werth
Wait 1

Loop
End

BMS
22.07.2010, 14:30
Es muss noch das ADATE-Bit (Bit 5) in ADCSRA gesetzt werden und außerdem SFIOR=0
Im Datenblatt :
Seite 214

Bit 5 – ADATE: ADC Auto Trigger Enable
When this bit is written to one, Auto Triggering of the ADC is enabled. The ADC will start
a conversion on a positive edge of the selected trigger signal. The trigger source is
selected by setting the ADC Trigger Select bits, ADTS in SFIOR.
Seite 216

If ADATE in ADCSRA is written to one, the value of these bits (Anmerkung: ADTS2:0 in SFIOR) selects which source will
trigger an ADC conversion. If ADATE is cleared, the ADTS2:0 settings will have no
effect.
ADTS2 ADTS1 ADTS0 Trigger Source
0 0 0 Free Running mode
...

und auf das bin ich auch noch gestoßen (Seite 203)

In Free Running mode, a new conversion will be started immediately after the conversion
completes, while ADSC remains high.
Das ADSC-Bit muss also wirklich nur 1x gesetzt werden

Dann müsste es wirklich funktionieren :)

Gruß
Bernhard

Kampi
22.07.2010, 14:43
Ja gut das macht im Free Run Modus sogar Sinn das er es selber neu setzt 8-[
Hab mich da leider selber noch nicht so richtig reingelesen :(

radbruch
22.07.2010, 16:07
Hallo


Verstehst du das nicht?Nee, das verstehe ich wirklich nicht:


...indem ich den ADC im Free-Run Modus laufen lasse und nur die höherwertigen 8 Bits ausleseBei linksbündigem 8Bit-Ergebniss liest man nur ADCH. Ich dachte zuerst, du hast den falschen Quellcode gepostet ;)

Naja, "wollte mal versuchen, mit meinem ADC ein eher höher frequentes analoges Signal auszulesen..." hab' ich ja eigentlich schon beantwortet. Ein schnelleres linksbündiges 8bit-ADC-Setup für ' nen Mega32 habe ich bisher noch nicht gesehen. Warum ihr dieses oben schon gezeigte ADC-Setup nicht verwenden wollt ist mir echt schleierhaft.

Gruß

mic

Che Guevara
23.07.2010, 22:23
Hi,



Ich dachte zuerst, du hast den falschen Quellcode gepostet ;)


Nein, ich wollte mir nur mal zur Sicherheit noch ADCL mit ausgeben lassen ;)



hab' ich ja eigentlich schon beantwortet.


Nein, da dein geposteter Link nichts anderes macht, als das, was ich schon selbst hinbekommen hab :( Mittlerweile ist mir ein Weg eingefallen, das ganze zu realisieren, allerdings ist das sehr umständlich!



$regfile = "m32def.dat"
$crystal = 16000000

config adc = free , prescaler = auto
start adc

config pina.0 = 0
porta.0 = 0

dim x as word


enable interrupts


do

x = makeint(adcl, adch)
x = x / 4

print x

loop

end


oder aber mittels Overlay:



$regfile = "m32def.dat"
$crystal = 16000000

config adc = free , prescaler = auto
start adc

config pina.0 = 0
porta.0 = 0

dim x as word at $60
dim xh as word at $60 overlay


enable interrupts


do

x = makeint(adcl, adch)
print xh

loop

end



Was ich benötige ist also ein vollautomatisierter Prozess:
1. ADCL und ADCH in eine 16Bit Variable (Word) konvertierren
2. Diese dann durch 4 teilen

Wäre natürlich toll, wenn man den ADC so initialisieren könnte, dass das alles selbstständig vom µC gemacht wird und man diese benötigten 8-Bit nur noch aus einem Register auslesen müsste ...

Wenn euch noch was einfällt bitte posten
Gruß
Chris


EDIT: Das mit dem Overlay funktioniert leider doch nicht :(

radbruch
24.07.2010, 10:01
Hallo


Wäre natürlich toll, wenn man den ADC so initialisieren könnte, dass das alles selbstständig vom µC gemacht wird und man diese benötigten 8-Bit nur noch aus einem Register auslesen müsste ...

Ergebniss rechtsbündig:

ADCH ADCL
xxxxxx98 76543210

Ergebniss linksbündig:

ADCH ADCL
98765432 10xxxxxx

Wenn man bei linksbündigem Ergebniss nur ADCH ausliest, erhält man die 8 höchstwertigen Bits.

Gruß

mic

Rone
24.07.2010, 10:24
Hallo!


$regfile = "m16def.dat"
$crystal = 14745600
$hwstack = 64
$swstack = 64
$framesize = 64
$baud = 19200



Admux = &B01100000 'Ref=AVCC;Left Adj.;Pina.0
Adcsra = &B11100110 'ADC Enable;Start Conversion;Auto Trigger;Prescaler=64
Sfior = &B00000000 'Free Run


Dim Adc_wert As Byte


Do

Adc_wert = Adch

Print Adc_wert

Loop
End

Einfacher gehts nicht!

MfG
Rone


Edit: All diese Hinweise wurden schon gegeben!

Che Guevara
24.07.2010, 11:15
Hi,

also erstmal danke für eure Antworten!
Ich glaube das Problem jetzt gefunden zu haben (bitte nicht hauen!):

Ich habe alle Programme im Simulator ausprobiert und nicht mit dem RN-Control ... Anscheinend funktioniert der Simulator da nicht richtig!
Tut mir leid, dass ihr euch alle so umsonst bemüht habt :(

Aber nochmals vielen Dank für die zahlreichen Antworten!

Gruß
Chris


EDIT: Außerdem hatte ich in meinem ersten Programm das ADATE-Bit nicht gesetzt.

Kampi
24.07.2010, 11:22
Nicht schlimm :D
Hab auch erst den Fehler gemacht das ich dem Simulator getraut habe. Aber anscheinend kommt der mit dem Registersetzen nicht so ganz klar damit.

Che Guevara
24.07.2010, 12:05
werds mir merken, nichts mehr NUR im Simulator zu machen ;)

Gruß
Chris

Kampi
24.07.2010, 12:55
Der Simulator eignet sich nur dafür um die Funktion von "einfachen" Programmen zu testen. Wenn es um das beschreiben einzelner Register geht ist er eher ungeeignet da man sonst jeden einzelnen Controller im Simulator speichern muss und das sehr detailgetreu.

for_ro
24.07.2010, 13:57
Der Simulator eignet sich nur dafür um die Funktion von "einfachen" Programmen zu testen. Wenn es um das beschreiben einzelner Register geht ist er eher ungeeignet da man sonst jeden einzelnen Controller im Simulator speichern muss und das sehr detailgetreu.
Was meinst du mit "... jeden einzelnen Controller im Simulator speichern muss und das sehr detailgetreu"?
Gerade für den Status und die Änderungen an den Registern finde ich den Simulator super geeignet. Einzig die externen Schnittstellen wie 1-wire und I2C sind nicht so schön zu simulieren, weil man die echten Eingaben nicht hat.
Und die paar Fälle, wo der Simulator nicht richtig arbeitet tauchen eher selten auf. Ansonsten ist ja da noch das AVRStudio.

Kampi
24.07.2010, 14:51
Ich meinte das so, dass wenn man den genauen Aufbau der Controller in einem Simulator hinterlegen würde, hätte man 1a Simulationsergebnisse.
Aber sonst hast du recht. Der Simulator ist trotzdem echt gut geworden, was die Anzeige der Register usw. angeht.
Zu dem Simulator aus dem AVRStudio kann ich nichts sagen da ich diesen nicht kenne......wusste nichtmal das AVRStudio einen hat :D