Erste Hilfe?

mcflay

Neues Mitglied
25. Feb. 2011
26
0
0
Sprachen
[Erledigt] Erste Hilfe für AD-Wandler?

So nun gehts los meine ersten Fragen:

Für die Spannungsüberwachung eines Akkus möchte ich mit nem Tiny25 die Spannung im Ad-wandler einlesen und dann weiter verarbeiten.
Jetzt hänge ich aber schon seit einer Woche am Ad-Wandler fest
und begreife nicht warum er nicht das macht was ich möchte.

Code:
;-------------------------------------------------------------------------
; Titel : AD-Test
;-------------------------------------------------------------------------
; Funktion : 
; Schaltung : 
;-------------------------------------------------------------------------
; Prozessor : ATtiny25
; Takt : 1000000 Hz
; Sprache : 
; Datum : 25.2.2011
; Version : 1.0
; Autor : 
; Programmer: 
; Port : 
;-------------------------------------------------------------------------
; created by myAVR-CodeWizard
;-------------------------------------------------------------------------
.include	"tn25def.inc" ; Prozessordefinition
.cseg
.org 0 
begin:	rjmp	main	; 1 Reset
 	reti 		; 2 
 	reti 		; 3 
 	reti 		; 4 
 	reti 		; 5 
 	reti 		; 6 
 	reti 		; 7 
 	reti 		; 8 
 	rjmp 	onadc	; 9 ADC Wandlung komplett
;------------------------------------------------------------------------
; Initialisierungen
;------------------------------------------------------------------------
main:
	;Stackpointer initialisieren
 	ldi	r16,LOW(RAMEND) 
	out	SPL,r16
	ldi	r16,HIGH(RAMEND)
	out	SPH,r16


 	; Ports initialisieren
 	sbi 	Ddrb, pb1	; PORT1
 	sbi 	Ddrb, pb2	; PORT2
 	cbi 	Ddrb, pb3	; PORT3
; ADC initialisieren
 	ldi     r16, (1<<REFS2)                   
    out     ADMUX, r16
    ldi     r16, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
    out     ADCSRA, r16

;------------------------------------------------------------------------
; Hauptprogramm-Schleife
;------------------------------------------------------------------------
mainloop: wdr
	rjmp 	mainloop ; Sprung
;--------------------------------------------------------------------
; getValueADC - liest den aktuellen Wert vom ADC
; PA: r14 = Ergebnis
;--------------------------------------------------------------------
onadc:
 	in 	r14,adcl; Einlesen
 	reti

1. Warum bricht AVR-Studio 4 schon beim Stackpointer initialisieren von SPH mit der Fehlermeldung ab
error: Undefined symbol: SPH
2. Was bringt das wdr im mainloop?
Ich weiß des es ein Watchdog-Reset ist aber brauche ich den dort?
3. Wenn ich das Proggie im Studio4 in einzelschritten durchlaufen lasse
und nun in ADCL einen Wert einstelle wird dieser nicht r14 geladen,
ist das normal oder mache ich was falsch?

Ich kann mir vorstellen das es mal wieder typische Anfänger Probleme sind,
aber ich werde trotz lesen und studieren darauß nicht schlau.
Deshalb hoffe ich auf Gnade bei Euren Antworten :adore:
 
Hallo Mcflay,

willkommen im AVR-PRAXiS-Forum.

Da es schon spät ist, gehe ich nur mal kurz auf deine Fragen ein.

zu 1)
Der Tiny25 hat keinen SPH (StackPointer HighByte), da der Mikrocontroller nur 128Byte SRAM besitzt. Es reicht also aus wenn du SPL initialisierst, genauer gesagt, du musst den Stackpointer garnicht initialisieren. Der Tiny25 ist ein neuerer Mikrocontroller, bei denen der Stackpointer durch die Hardware nach Reset schon richtig auf RAMEND gesetzt wird.

zu 2)
wdr (Watchdog Reset) brauchst du nur, wenn du den Watchdog aktiviert hast. Aktiviert wird er zu Programmstart durch die Software, oder wenn vorhanden durch ein Fusebit.

zu 3)
Du meinst im Simulator? Ich habe mal kurz drübergeschaut. Du aktivierst zwar den ADC (Bit ADEN), du startest aber keine Wandlung. Eine Single-Wandlung startest du durch Setzen des Bits ADSC (ADC Start Conversion) im Register ADCSRA. Das Bit bleibt solange auf "1", bis die Wandlung fertig ist. Du kannst dieses Bit abfragen und dann das Ergebnis aus dem Datenregister ADCH ADCL lesen.

Vielleicht hilft dir das schon einmal weiter.

Grüße,
Dirk
 
Guten Morgen Dirk,
danke für Deine klärenden Worte!

zu 1)
Danke das hat mir schonmal den Morgen versüßt,
ich habe mich schon gewundert warum das da hängen bleibt.

zu 2)
Ich habe nun mal den Wdr rausgenommen.
Nun hängt das Proggie bei rjmp mainloop und wartet.

zu 3)
Ja meinte den Simulator von AVR-Studio da ist doch rechts so ein Fenster,
wo man dann bei ADCL auf die Bits klicken kann,
oder habe ich die Funktion falsch verstanden?
Bei Adcsra habe ich die "Start conversion" nun gesetzt,
aber es werden immer noch keine AD-Wandler Daten geholt:(
 
Guten Morgen Mcflay,

also dass das Programm bei rjmp mainloop "wartet" ist richtig. Die Adresse von "mainloop:" ist jetzt im Prinzip die Adresse vom Instruction Opcode "rjmp mainloop". So sieht es im Simulator aus, als würde das Programm hier hängen, tut es aber nicht. Mach zum Beispiel mal ein nop anstelle wdr zwischen das label mainloop und rjmp mainloop, dann siehst du im Simulator wieder den Rücksprung, da er ja über den Opcode nop zurückspringt, der ProgrammCounter PC ändert sich dann nämlich.

Ich habe gerade gesehen, du nutzt den Interrupt vom ADC und in der Interruptserviceroutine liest du ADCL. Der Interrupt wird nie ausgelöst, da kein ADC Interrupt freigegeben wurde, ausserdem hast du die Interrupts global nicht freigegeben (sei). Die ISR wird also nie ausgeführt.

Grüße,
Dirk
 
Mach zum Beispiel mal ein nop anstelle wdr zwischen das label mainloop und rjmp mainloop,
Danke jetzt sehe ich das auch wieder gearbeitet wird:D
du nutzt den Interrupt vom ADC und in der Interruptserviceroutine liest du ADCL. Der Interrupt wird nie ausgelöst, da kein ADC Interrupt freigegeben wurde, ausserdem hast du die Interrupts global nicht freigegeben (sei). Die ISR wird also nie ausgeführt.
Klingt logisch:eek:
Aber muß ich das über einen Interrupt auslösen oder geht das auch so
das er einfach nur den aktuellen Wert im AD-Wandler nimmt und das immer und immer wieder.
Es soll ja einen Spannungüberwachung werden da muß ich ja durchgehend auf dem laufenden sein:confused:
 
Wenn du Lösung mit dem ADC Interrupt verwendest, hast du im Register r14 ständig den aktuellen Wert, ADCH musst du auch berücksichtigen. Wenn dir 8bit Auflösung ausreichen, kannst du das Ergebnis mit dem Bit ADLAR linksbündig anordnen, dann brauchst du nur ADCH lesen.

Alternativ zum Interrupt kannst du auch jedesmal eine SingleConversion starten und dann das Bit ADCSC pollen. Ist ADCSC wieder 0, liest du das Ergebnis und startest erneut durch Setzen von ADCSC.


Es gibt folgende Möglichkeiten bei dem Mikrocontroller, eine AD-Wandlung durchzuführen:

Single Conversion
Hier setzt du das Bit ADSC. Die Wandlung startet und das Bit bleibt solange gesetzt, bis die Wandlung beendet ist. Danach ist das Ergebnis in ADCH ADCL gültig.

Auto Trigger
Hier wird eine ADC Wandlung automatisch gestartet, wenn ein bestimmtes Ereignis eintritt. Den Auto Trigger Mode wählst du, indem du das Bit ADATE setzt. Im Register ADCSRB wählst du die Triggerquelle, also die Quelle die das Ereignis liefert. Nach dem Reset ist FreeRunningMode gewählt, du brauchst also nicht unbedingt eine andere Quelle auswählen. Falls es dich interessiert, welche Quellen es noch gibt, schau einfach mal in das Datenblatt, das findest du in unserer Mikrocontroller Datenbank. Im FreeRunningMode triggert das Interruptflag des ADC die neue Wandlung selber und es wird somit immer wieder eine neue Wandlung ausgeführt ... deswegen "Free running".

Dirk
 
:adore: :adore: :adore: :adore: :adore:
Da habe ich jetzt erstmal genug mit zu lesen.
Danke das Du Dir soviel mühe gibst
 
Was mir gerade noch auffällt.
Wie ist das mit dem Simulator,
eignet der sich um das vorher zu checken?
Also kann ich ihm beim Werte vorgeben in ADCL und ADCH vorgauckeln
das es einen neuen Wert gibt.
Oder gibts da eine andere Möglichkeit:confused:
 
Also wenn
  • der ADC enabled ist (Bit ADEN im Register ADCSRA),
  • der ADC Interrupt freigegeben ist (Bit ADIE im Register ADCSRA),
  • Freerunning Mode eingestellt ist (Bit ADATE in Register ADCSRA),
  • global Interrupts freigegeben sind (sei) und
  • einmalig ASDSC (Start Conversion) gesetzt wird,
sollte der ADC Interrupt im Simulator eigentlich permanent ausgelöst werden. (habe ich allerdings noch nie benötigt/geprüft)

Wenn das zeitliche Auswerten des Wandelergebnisses nicht wichtig ist, musst du nicht unbedingt den Interrupt nutzen, sondern kannst direkt im Hauptprogramm auf ADCL ADCH (in dieser Reigenfolge) zugreifen.

Möchtest du zum Beispiel über mehrere Messungen einen Mittelwert bilden, benötigst du natürlich einen zeitlichen Zusammenhang zu der Wandelzeit, so dass du hier den Interrupt nutzt.

Dirk
 
Ich habe es nun geschaft das er einmal nach 0,42ms den AD-Wert abgeholt hat,
seit dem nicht mehr, immer nur einmal und wenn ich dann den nächsten eingebe,
passiert nichts mehr.

sondern kannst direkt im Hauptprogramm auf ADCL ADCH (in dieser Reigenfolge) zugreifen.
Verstehe ich das jetzt richtig ich kann die auch direkt im mainloop auslesen lassen, das klappt nehmlich so wie ich mir das vorstelle.
Ich will nun auch nicht ungeduldig erscheinen,
aber ich verstehe das eigentlich mit dem Interupt so das wenn ein neuer Wert
im AD-Wandler eintrift dieser abgerufen werden sollte.
Gibts eigentlich irgendwo nen Tutorial in Assembler für den AD,
was ich bis her gefunden habe war nur in C oder Bascom:confused:
Wenn das zeitliche Auswerten des Wandelergebnisses nicht wichtig ist
Ne denke das ist eigentlich nicht wichtig.
Die Priorität liegt in der Höhe der Spannung,
die kontinuierlich ansteigt beim Laden und beim Benutzen abfällt.
 
Ich habe es nun geschaft das er einmal nach 0,42ms den AD-Wert abgeholt hat, seit dem nicht mehr...

Kannst du noch einmal den aktuellen Stand deines Programms einstellen.

Verstehe ich das jetzt richtig ich kann die auch direkt im mainloop auslesen lassen

Ja das ist möglich. Wie schon geschrieben, du kannst das auch ohne Interrupt realisieren. Ein Tutorial für ADC und Assembler kenne ich leider nicht. Lese dir vielleicht auch einfach mal das Kapitel ADC im Datenblatt des AVR durch, schau dir auch am Kapitelende die Erklärungen zu den Registern des ADC an.

Dirk
 
Hier der aktuelle Code:
Code:
;-------------------------------------------------------------------------
; Titel : AD-Test
;-------------------------------------------------------------------------
; Funktion : 
; Schaltung : 
;-------------------------------------------------------------------------
; Prozessor : ATtiny25
; Takt : 1000000 Hz
; Sprache : 
; Datum : 25.2.2011
; Version : 1.0
; Autor : 
; Programmer: 
; Port : 
;-------------------------------------------------------------------------
; created by myAVR-CodeWizard
;-------------------------------------------------------------------------
.include	"tn25def.inc" ; Prozessordefinition
.cseg
.org 0 
begin:	rjmp	main	; 1 Reset
 	reti 		; 2 
 	reti 		; 3 
 	reti 		; 4 
 	reti 		; 5 
 	reti 		; 6 
 	reti 		; 7 
 	reti 		; 8 
 	rjmp	 	onadc; 9 ADC Wandlung komplett
;------------------------------------------------------------------------
; Initialisierungen
;------------------------------------------------------------------------
main:
 	; Ports initialisieren
 	
 	cbi 	Ddrb, pb4	; PORT3
; ADC initialisieren
 	ldi     r16, (1<<MUX1)|(1<<REFS1)|(1<<ADLAR) ;ADC2 | 1.1V referenz | Links ausgerichtet                  ; Kanal 3
    out     ADMUX, r16
    ldi     r16, (1<<ADEN) |(1<<ADSC)|(1<<ADATE)|(1<<ADIE)| (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
    out     ADCSRA, r16
	ldi		r16, (1<<BIN)|(0<<ADTS2)|(0<<ADTS1)|(0<<ADTS0)
	out		adcsrb,r16
;--- Interrups erlauben ---
 sei

;------------------------------------------------------------------------
; Hauptprogramm-Schleife
;------------------------------------------------------------------------
mainloop:
	nop
	rjmp 	mainloop ; Sprung
;-------------------------------------------------------------------- 
; getValueADC - liest den aktuellen Wert vom ADC ; PA: r14 = Ergebnis 
;-------------------------------------------------------------------- 
onadc: 
	in r14,adch; Einlesen
 	reti
 
Also ich sehe direkt keinen Fehler in deinem Sourcecode.

Das Bit BIN hat glaube nur einen Sinn bei Differential Mode, also wenn du im Mux-Register Differential Input wählst, dann kann nämlich auch der Pegel am negative Eingang höher sein, als am positiven. Aber das hat mit dem Problem nichts zu tun.

Probiere mal folgendes:
Initialisiere den SPL direkt nach main.
ldi r16,LOW(RAMEND)
out SPL,r16
Der Mikrocontroller sollte das zwar nach Reset selber machen, aber ich habe so die Vermutung, dass es der Simulator nicht macht und das würde bedeuten, dass irgendwelche Speicherstellen des SRAM überschrieben werden, bzw. dass reti sich eine falsche Rücksprungadresse vom Stack holt. Die Wandlung funktioniert dann nur einmal.

Dirk
 
Mahlzeit da bin ich wieder:D
dass es der Simulator nicht macht
Er macht es auch mit spl angabe nicht.
Haben nun testweise einen freien Port mit sbi und cbi in die onadc eingebaut
und mit dem Oszi uns angeschaut ob der geschaltet wird.
Das scheint so zu klappen, also das onadc wird abgearbeitet.

Nun zu meinem nächsten Problem:flute:

In der Mainloop rufe ich nun folgende Unterprogramme auf:
Code:
onadc: 

in r18,adcl
in r19,adch; Einlesen 
		
reti
;--------------------------------------------------------------------
; r19, r18=AD-Wert r17,r16=Vergleichswert aus Tabelle 
;--------------------------------------------------------------------
balance:			
	push	r16
	push	r17
	ldi		r17,0x02 ; High VGL Wert aus Tabelle zum Vergleichen mit r19
	ldi		r16,0xe4	; Low VGL Wert aus Tabelle zum Vergleichen mit r18
	cp		r16, r18
	cpc		r17, r19
	BRcs	Bal_on
	rjmp	Bal_off
;---------------------------------------------------------------------------
bal_fertig:
	pop		r17
	pop		r16
	ret
;----------------------------------------------------------------------------
bal_on:	;Balancer ein
	sbi PORTB,pb2
	rjmp bal_fertig
;----------------------------------------------------------------------------
bal_off:	 ;Balancer aus
	cbi PORTB,pb2
	rjmp bal_fertig
;----------------------------------------------------------------------------
An PB2 hängt eine LED die dann an oder ausgehen soll.
Nun meine Frage:

In einer Tabelle haben wir uns die Hexwerte für verschiedene Spannungen ausgerechnet.
So würde z.B eine Spannung von 4,2 Volt einem Highwert von 0x02
und einem Lowwert von 0xe4.
Jetzt wollten wir mit cp und cpc einen Vergleich machen,
nur wie muß die Reihenfolge dabei sein?
Wir machen das nun so:
r16=0x4e gewollter Lowwert
r17=0x02 gewollter Highwert
r18=???? gemessener Lowwert
r19=???? gemessener Highwert

Nun die Formel dazu:
cp r16, r18
cpc r17, r19


Wenn ich nun aber die Tutorials durchlese sollte das ja anders sein
cp r17, r16
cpc r19, r18
Habe ich das jetzt so richtig verstanden?
 
Hallo,

warum das mit dem Simulator nicht funktioniert, kann ich im Moment auch nicht sagen, es gibt schon öfter mal Probleme mit dem Simulator (wurde im Forum schon einige male festgestellt), die in der Realität nicht auftreten, also nicht immer drauf verlassen, sondern sich auch mal anders behelfen, so wie du es mit den Portpins innerhalb der ISR gemacht hast.

Bei dem Vergleich kannst du dir das so vorstellen, dass du hier vom 16bit Wert r17 r16 den 16bit Wert r19 r18 abziehst. Die Register werden hier jedoch im Vergleich zu sub und sbc nicht verändert, das Carrys Bit c aber schon.
Du kannst hier also prüfen, ob r17 r16 größer ist als r19 r18. Wenn größer dann c=0.

Achtung: vor dem Vergleich Interrupts disablen (cli) und danach wieder enablen (sei). Der Grund ist, der ADC Interrupt könnte zwischen cp und cpc auftreten und deinen ADC Wert verändern, der ja in r19 r18 steckt.

Grüße,
Dirk
 
Hallo,

Mahlzeit da bin ich wieder:D
dass es der Simulator nicht macht
Er macht es auch mit spl angabe nicht.
Haben nun testweise einen freien Port mit sbi und cbi in die onadc eingebaut
und mit dem Oszi uns angeschaut ob der geschaltet wird.
Das scheint so zu klappen, also das onadc wird abgearbeitet.
Ihr immer mit eurem Simulator in BASCOM und AVR-Studio. Das Ding kann die
Sachen simulieren die intern ablaufen. Es kann aber nicht die Hardware die
draußen dranhängt simulieren. Und das es mit Interrupts und anderem Gedöns
im Simulator schon oft genug "nicht funktioniert" hat und auf der realen
Hardware war alles erste Sahne. Ich halte von dem Ding immer noch ... nix :rolleyes:

Das Beste ist immer noch ne Debug-Schnittstelle (RS232, LCD, ne LED, ...
was auch) Da arbeitet man am realen Objekt und sieht wie es in Wirklichkeit
reagiert.

Gruß
Dino
 
Gebt zu, ihr zwei habt nur darauf gewartet das der Döskop von der Weser wieder ne Frage stellt:dirol:

@Dirk
Achtung: vor dem Vergleich Interrupts disablen (cli)
Danke werde ich so machen,
bin mal gespannt ob das dann morgen endlich so läuft wie wir das gerne hätten:D

@Dino
Ich halte von dem Ding immer noch ... nix
Steht aber auch nirgends das die Dinger nichts taugen.
Für mich stand der zum Checken daheim,
weil ich hier keinen Möglichkeit hatte es am lebenden Objekt zu checken
und ich wollte doch ne Lösung finden.
Jetzt bin ich da schlauer und werde mir einen Versuchsaufbau für mich zusammen stricken;)
 
Hi,

Gebt zu, ihr zwei habt nur darauf gewartet das der Döskop von der Weser wieder ne Frage stellt:dirol:

...

@Dino

Steht aber auch nirgends das die Dinger nichts taugen.
Für mich stand der zum Checken daheim,
weil ich hier keinen Möglichkeit hatte es am lebenden Objekt zu checken
und ich wollte doch ne Lösung finden.
da sind schon mehrere dran verzweifelt das es im Simulator nicht so lief
wie es sollte ;) Da bist du nicht der einzige :D

Gruß
Dino
 
Hallo,
ich bin es wieder:(

Ich muß nochmal wegen der Formel nachhaken.
Wenn ich sie so wie beschrieben eingebe

cp Htabelle, Ltabelle
cpc Hmess, Lmess

dann bekomme ich ein Blinken in unterschiedlichen Rythmen:eek:

Gebe ich sie wieder wie vorher ein
cp Ltabell, Lmess
cpc Htabelle, Hmess
Leuchtet die Diode dauernd

Zur Gegenprobe habe ich den Messwerten mal feste Werte,
höher und niedriger wie die Tabellenwerte, gegeben
und da macht sie das in der unteren Formel richtig aber in meiner Leuchtet sie dann dauernd.
Nun stellt sich mir die Frage welche nun richtig ist:stupido2:

Anbei habe ich auch mal ne Skize der Schaltung gemacht:
Die Eingangsspannung kann im Bereich von 0-5 Volt sein
und wird mittels Labornetzteil eingestellt und auch hoch und runter gefahren,
um einen Akku zu simulieren.
attiny25.gif

Ich glaube das war es erstmal, wenn noch was unklar sein sollte bitte fragen.
Und ich setze mich jetzt nach draußen in die Sonne und schlage mit nem Hammer auf die Platine:cool:
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)