Hallo,
ich versuche einen Drehzahlmesser zu programmieren.
Plan ist, die Zeit zwischen den Zündimpulsen über
das Zählen der eigenen Takte auszurechnen. Dazu ist
es notwendig, das alle 2 Takte gezählt wird und in
der Zeit dazwischen die Drehzahl ausgegeben wird.
Also Zap-CounterStarten-Zap-CounterStoppenUndAnzeigen-Zap... :-)
Nun läuft das ganze über den Int0. Eine Routine soll
nachgucken, ob sie nun den Counter starten oder
die Anzeige realisieren soll. Da habe ich an ein
Statusbit in r17 gedacht. Nur irgendwie will das
garnicht so wie ich.
Hier die Int-Routine:
wdr
cli ; Interrupts AUS
cpi r17,0
breq int_ende
sbi PORTD,4
rcall wait
cbi PORTD,4 ; wird nur jedes 2. Mal ausgeführt
rcall wait
int_ende:
ldi r17,1
sei ; Interrupts wieder AN
reti
Was mache ich falsch? Er kommt nicht in die
Routine rein, sondern loopt nur die Hauptschleife..?
Danke! :-)
Die komplette Architektur ist Mist.
Aus einem Int in irgendwelche externen Wait-Schleifen zu springen ist
ganz, ganz schlechter Stil, das ist mal das erste.
Sende bitte den gesamten Code, dann kann man das sehr viel besser
bewerten und auch lösen!
Joe
Frage:
Was soll das Abschalten des Ints im Int?
Der ist in diesem Moment sowieso aus.
Dito Einschalten am Ende der ISR.
Des weiteren die Register auf Stack
retten.
Ich möchte behautpten die Wait-Routine
wird auch außerhalb des Int aufgerufen!
Welcher Int ist es, wird der Initialisiert?
USW. USW.
Vorsichtig gesagt schlechter Stil.
Und ohne kompletten Code Hilfe nicht möglich,
meine Glaskugel ist gerade beim Reinigen.
Einfach mal Inputcapture nachschlagen mal googlen oder Datenblatt.
Sollte Perfekt geignet sein. Muß nur einmal konfiguriert werden und
läuft dann in Hardware. Man muß nur noch Register auslesen.
Aha, jetzt klappts. Ich habe das "sei" und "cli" aus dem
Int entfernt. Komisch. Naja, jedenfalls der Code:
;Reset and Interruptvectoren ;VNr. Beschreibung
begin:
rjmp main ; 1 POWER ON RESET
rjmp ignition ; 2 Int0-Interrupt
reti ; 3 Int1-Interrupt
reti ; 4 TC2 Compare Match
reti ; 5 TC2 Overflow
reti ; 6 TC1 Capture
reti ; 7 TC1 Compare Match A
reti ; 8 TC1 Compare Match B
reti ; 9 TC1 Overflow
reti ;10 TC0 Overflow
reti ;11 SPI, STC Serial Transfer Complete
reti ;12 UART Rx Complete
reti ;13 UART Data Register Empty
reti ;14 UART Tx Complete
reti ;15 ADC Conversion Complete
reti ;16 EEPROM Ready
reti ;17 Analog Comperator
reti ;18 TWI (I²C) Serial Interface
reti ;19 Strore Program Memory Ready
;-----------------------------------------------------------------------
-
;Start, Power ON, Reset
main:
;Stack
ldi r16,hi8(RAMEND)
out ioSPH,r16
ldi r16,lo8(RAMEND) ;Stack Initialisierung
out ioSPL,r16 ;Init Stackpointer
;Interrupt
ldi r16,0b01000000 ;Maskiere INT0
out GICR,r16
ldi r16,0b00000011 ;Konfiguriere
out MCUCR,r16 ;fallende Flanke
;Taster, Lampen
cbi DDRD,2 ;PORTD2 Taster = IN
sbi PORTD,2 ;Pull-Up
sbi DDRD,3 ;Port D.3 = LED OUT
sbi DDRD,4 ;D4 als testport um Signal zu erzeugen
ldi r17,0b00000000 ;Statusbit auf 0
sei ;alle Interrupts erlauben
;-----------------------------------------------------------------------
-
mainloop:
wdr
cli
; Anzeigen
sbi PORTD,3 ; LED AUS
rcall wait
cbi PORTD,3
rcall wait
rcall wait
rcall wait
sei
rjmp mainloop
;-----------------------------------------------------------------------
-
ignition:
wdr
cpi r17,0
brne int_ende
sbi PORTD,4
rcall wait
cbi PORTD,4 ;
rcall wait
int_ende:
com r17
reti
;-----------------------------------------------------------------------
-
;-----------------------------------------------------------------------
-
; UP WaitMs, Warteroutine im Millisekundenbereich
wait: push r16 ;r16 retten
push r17 ;r17 retten
push r18 ;r18 retten
ldi r16,100 ;Laufvariable ca x ms bei 3,6MHz
loop1: ldi r17,0xFF ;Laufvariable loop1
loop2: ldi r18,13 ;Laufvariable loop3
loop3: dec r18 ;Zähler 3 -1, hier Kalibrierung auf MCU Takt
brne loop3 ;Solange nicht NULL
dec r17 ;Zähler 2 -1
brne loop2 ;Solange nicht NULL
dec r16 ;Zähler1 -1
brne loop1 ;Solange nicht NULL
pop r18 ;r18 wiederherstellen
pop r17 ;r17 wiederherstellen
pop r16 ;r16 wiederherstellen
ret ;Rücksprung
;-----------------------------------------------------------------------
-
Ist nur Testcode. Die Waits sind nur temporär drin, damit
ich sehen kann was er macht. Der Code für den DZM ist zu
großen Teilen fertig, läuft aber hinten und vorne nicht.
Ich danke erstmal für die Hilfe und meld mich die Tage
nochmal mit der einen oder anderen Kleinigkeit ;)
Danke,
Olli
Nochwas @Anton
Wieso die Register retten? Wenn ich sie nicht in anderen
Routinen auch brauche, kann ich sie doch so lassen? Muss
ich nicht retten, oder?
olli schrieb:> Der Code für den DZM ist zu> großen Teilen fertig, läuft aber hinten und vorne nicht.
ist auch kein Wunder - du sicherst in dem Interupt SREG nicht.
> Der Code für den DZM ist zu> großen Teilen fertig, läuft aber hinten und vorne nicht.
Was für einen Unsinn erzählst Du da eigentlich?
Wenn etwas "vorne und hinten nicht läuft"....
...dann ist das NICHT "in grossen Teilen fertig"!
WAS SOLL DER QUATSCH BITTE? WAS SOLL DAS?
Nochmal konkret:
Wie kann etwas "fertig" sein, das hinten und vorne nicht läuft?
Deine Architektur ist immer noch VÖLLIGER Mist.
Du hast praktisch NICHTS von dem verstanden, was Dir helfende Kräfte
hier schrieben.
Wann würde sich das ändern, was muss geschehen?
Wie lernresistent kann ein Mensch sein?
Bitte um konkrete (SEHR konkrete) Antworten!
Joe
Hi
Nun ja, so manche Kritik ist nicht unbegründet...
Also, Register, die in einer ISR benutzt werden, brauchen dann nicht
gesichert werden, wenn sie nirgends anders verwendet werden, aber...
mach es trotzdem. Du suchst dir einen Wolf, wenn aus welchen Gründen
auch immer später mal schnell ein solches Register für andere Zwecke
eingesetzt wird. Speziell, wenn es "nur" r17 heißt....
Außerdem ist es auch notwendig, das Statusregister zu sichern. Du hast
doch in deiner ISR Abfragen, die das Statusregister beeinflussen, oder
nicht ? Damit sind vorherige Statusinformationen nicht mehr gültig, auch
die, die vor dem Interrupt noch irgendelche Aktionen ausführen sollten.
Dann gewöhn dir an, die Blöcke deines Programmes deutlich
auseinanderzuhalten und um Gotteswillen ruf nicht aus einer ISR einen
Wait auf. Wozu brauchst du dann noch eine ISR, wenn du sowieso nicht
immer auf eintreffende Signale scharf bist ?
Wenn du eine Zeitverzögerung brauchst, dann nutze die Timer-ISR.
Parametriere sie so, das sie im mSek-Takt aufgerufen wird. Wenn du nun
eine Zeitverzögerung brauchst, zähl einfach in der ISR einen Wert nach
Null, ob nun im mSek-Takt oder im Sekundentakt, das leitest du in der
ISR ab.
1
2
;-----Interruptroutine Timer 1 für Zeitbasis -------------------------
Ich hab dir mal einen Aufruf für ein Zeitabhängiges Unterprogramm
dirngelassen. Genausogut kannst du dir in dieser Timer ISR bits setzen,
die dann vom Hauptprogramm einmalig abgearbeitet werden, d. H. die
Routinen, die du dann aufrifst, löschen dieses Bit wieder. So kannst du
Ereignisse, die z. B. im Sekundenbereich liegen ohne merklichen
Zeitversatz abarbeiten lassen.
Gruß oldmax
olli schrieb:> Aha, jetzt klappts. Ich habe das "sei" und "cli" aus dem> Int entfernt. Komisch.
Nicht komisch. Wenn die Warteschleifen lang genug sind wird das
Interruptflag wieder gesetzt bevor die ISR verlassen wurde. Da du die
Interrupts in der ISR mit sei wieder aktivierst dürfte das eine Art
Rekursion ergeben, die ISR wird immer wieder aufgerufen und irgendwann
ist der Stack alle...
nachdenklicher schrieb:>> Der Code für den DZM ist zu>> großen Teilen fertig, läuft aber hinten und vorne nicht.>> Was für einen Unsinn erzählst Du da eigentlich?> Wenn etwas "vorne und hinten nicht läuft"....> ...dann ist das NICHT "in grossen Teilen fertig"!>> WAS SOLL DER QUATSCH BITTE? WAS SOLL DAS?>> Nochmal konkret:> Wie kann etwas "fertig" sein, das hinten und vorne nicht läuft?>> Deine Architektur ist immer noch VÖLLIGER Mist.> Du hast praktisch NICHTS von dem verstanden, was Dir helfende Kräfte> hier schrieben.>> Wann würde sich das ändern, was muss geschehen?> Wie lernresistent kann ein Mensch sein?>> Bitte um konkrete (SEHR konkrete) Antworten!
Man, sag mal hast Du keine anderen Probleme oder
Quellen der Lebensfreude? Stress mit der Frau?
Ich versuch mir ASM seit einer Weile beizubringen, ist da
irgendwas falsch dran, soll ich das ändern oder was?
Der prinzipielle Ablauf ist fertig geschrieben, es
muss nur noch die genaue Taktanzahl ausgerechnet
und angepasst werden. Problem war eben, dass das Programm
eben nicht das macht was es soll, ich aber nicht weiß
wo der Fehler liegt. Deshalb nehme ich das Stück für
Stück auseinander und suche den Fehler. Darf ich
das? Danke.
@oldmax
Danke Dir. Ich werde es mir nachher mal genauer
angucken. Mein Ziel ist eigentlich das ganze ohne
den Timer zu machen, nur durch Zählen der Takte.
Mal gucken! :-)
olli schrieb:> Mein Ziel ist eigentlich das ganze ohne> den Timer zu machen, nur durch Zählen der Takte.
Warum? Der uC ist ganz bezahlt und es gibt kein Geld zurueck fuer nicht
verwendete Hardware.
Hi
Du kannst schon die Takte zählen und dir so eine Warteschleife aufbauen,
aber... und hier steckt der Teufel im Detail, nicht diese Warteschleife
aus einer ISR heraus aufrufen. Eine ISR ist dazu da, Ereignisse von
kurzer Dauer zu erfassen und mit Kurz meine ich auch Kurz. Wenn du deine
ISR mit irgendwelchen sinnlosen Schleifen beschäftigst, läufst du
Gefahr, das ein Interrupt halt nicht ausgelöst wird, wenn er dadurch
geblockt ist oder wie auch schon erwähnt, wenn freigegeben, eben den
Stack vollmüllt.
Und nun mal ein kleines Rechenexempel, wenn es um kurze Impulse geht.
Deine Welle macht bei jeder Umdrehung 360°. Dein Nocken betätigt etwa
für 5° einen Sensor. Eine Umdrehung braucht bei 6000 U/Min 1/100
Sekunden.
5° sind (1*5) / (100 *360) also 0,000138 sek. also 138 µSek.
Bei einer Frequenz von 16 MHZ dauert die Bearbeitung eines Befehles 125
nSek. Nun kommt es auf den umfang deines Programmes an, ob du das Signal
noch pollen kannst oder auf eine ISR ausweichen mußt. Taktest du
geringer, ist natürlich auch die Befehlsverarbeitungszeit größer.
Also, egal wie du es machst, es ist keine gute Idee, in einer ISR eine
Zeitschleife einzubauen. Das ergibt auch nicht wirklich Sinn. Viele
Zeitverzögerungen sind bei genauer Betrachtung überflüssig. Also nutz
die Innereien deines Controllers und mach keine Klimmzüge, die dich
sowieso nicht zu einem vernünftigen Ergebnis bringen. Nur weil der Timer
eine neue Erfahrung ist, braucht man darum keinen Bogen machen. Wenn
dein Drehzahlmesser z. B. eine 7 Segmentanzeige bekommen sollte, macht
es auch sinn, diese über den Timer zu multiplexen. Das garantiert dir
gleichbleibende helligkeit, da die Programmlaufzeitunterschiede
ausgebügelt werden.
Gruß oldmax
Also ich wollts so machen: Angenommene Höchstdrehzahl ist
16384 (2^14). Bei 3,7 MHz würden zwischen den Zündungen 220 Takte
vergehen. Also baue ich eine Routine die alle 220 Takte
ein 16bit-Register hochzählt. Dann kommt die ISR, der
16-bit Zähler wird übergeben. Ist der Zähler niedrig, ist
die Drehzahl hoch und andersrum.
Dann setze ich die obersten 2 Bits auf 1 und komplementiere
das gesamte 16 Bit Register. Viola, da steht dann meine
Drehzahl drin.
Insofern ohne besondere Wait-Schleife, außer eben die 220
Takte.
Da wird dann der Zwischenraum jeder ungeraden Zündung
gezählt, in der Zeit nach der Zündung mache ich die Auswertung
(die dann auch nicht mehr als 220 Takte lang sein darf,
oder ich zähle nur alle 3 Zündungen mal).
Ausgabe auf 8 LEDs, ich will z.B. nur den Bereich von
5500-7500 darstellen, weil da mein Zweitakter seine
Resokurve hat.
Problem ist auch: Das ganze ist für ein Preisauschreiben
und muss inkl. PDF am 1. Mai fertig sein. Weiß nicht,
ob ich das noch schaffe. Nur jetzt alles umzuschmeißen
kostet Zeit, auch wenn der Timer des ATMega schon
abbezahlt ist g
Dafuer wurde der Inputcapture Mode erfunden.
Du brauchst nur einen der Timer zu starten. Dann Flanke auswaehlen und
Interrupt fuer Input Capture freigeben. Jetzt kommt dein Capture
Interrupt. Die Hardware des uC speichert dir dann den aktuellen
Timerwert (der laueft staendig durch) ins Inputcapture Register ab.
Dann wird ein Interrupt generiert und deine Service Routine gestartet.
Die liest den Wert des Registers aus. Dann ziehst du davon den alten
Wert Vorzeichenrichtig ab und dann hast du deinen Messwert. Und das
alles ohne selber hochzaehlen zu muessen. Die Hardware des uC macht das
fuer dich.
olli schrieb:> Das ganze ist für ein Preisauschreiben
Das gibt aber so keinen Preis :-)
Icke wieder :-)
Programm ist länger geworden, wurde umstrukturiert.
Den AVR Timer will ich nicht nutzen, da ich sonst
alles umschmeißen müsste und dafür die Zeit nicht
reicht. Ich würds schon gern so lassen.
Das ist recht kompliziert, wenn sich jemand reinstürzen
möchte... dauert ein bisschen :->
Programmablauf arbeitet mit zwei Flags in r17 und r18.
Ablauf ist:
Zündung, r17 nicht gesetzt, also Zählschleife beginnen, r17 setzen;
Zündung, r17 gesetzt, Drehzahl anzeigen; r17 und r18 auf 0; danach
Endlosschleife (was soll er auch sonst in der Zeit machen)
dann wieder von vorn.
r17 sorgt dafür das nach den Zündungen sich Zählschleife
und Auswertung+Anzeige abwechseln
r18 sorgt dafür das im Mainloop die Endlosschleife betreten
wird (nach Anzeige)
Ich mache da nochmal ein Ablaufdiagramm, damit es
anschaulicher wird (Frau will einkaufen^^)
Hier das Programm:
------------------------------------------------------------------------
.equ F_CPU, 3686400
.include "AVR.H"
;Reset and Interruptvectoren ;VNr. Beschreibung
begin:
rjmp main ; 1 POWER ON RESET
rjmp ignition ; 2 Int0-Interrupt
reti ; 3 Int1-Interrupt
reti ; 4 TC2 Compare Match
reti ; 5 TC2 Overflow
reti ; 6 TC1 Capture
reti ; 7 TC1 Compare Match A
reti ; 8 TC1 Compare Match B
reti ; 9 TC1 Overflow
reti ;10 TC0 Overflow
reti ;11 SPI, STC Serial Transfer Complete
reti ;12 UART Rx Complete
reti ;13 UART Data Register Empty
reti ;14 UART Tx Complete
reti ;15 ADC Conversion Complete
reti ;16 EEPROM Ready
reti ;17 Analog Comperator
reti ;18 TWI (I²C) Serial Interface
reti ;19 Strore Program Memory Ready
;-----------------------------------------------------------------------
-
;Start, Power ON, Reset
main:
;Stack
ldi r16,hi8(RAMEND)
out ioSPH,r16
ldi r16,lo8(RAMEND) ;Stack Initialisierung
out ioSPL,r16 ;Init Stackpointer
;Interrupt
ldi r16,0b01000000 ;Maskiere INT0
out GICR,r16
ldi r16,0b00000011 ;Konfiguriere
out MCUCR,r16 ;fallende Flanke
;Taster, Lampen
cbi DDRD,2 ;PORTD2 Taster = IN
sbi PORTD,2 ;Pull-Up
sbi DDRD,3 ;Port D.3 = LED OUT
cbi PORTD,3
sbi DDRB,0
cbi PORTB,0
sbi DDRB,1
cbi PORTB,1
sbi DDRB,2
cbi PORTB,2
sbi DDRC,0
cbi PORTC,0
sbi DDRC,1
cbi PORTC,1
sbi DDRC,2
cbi PORTC,2
sbi DDRC,3
cbi PORTC,3
sbi DDRC,4
cbi PORTC,4
ldi r17,0b00000000 ;Statusbit B auf 0
ldi r18,0b00000000 ;Statusbit A auf 0
sei ;alle Interrupts erlauben
;-----------------------------------------------------------------------
-
mainloop:
wdr
cpi r18,0 ; Statusbit "nach Anzeige -> endless" gesetzt?
breq endless ; Wenn nicht gesetzt, dann springe in Endlosschleife
ldi R17, 73
Warte220: dec R17
brne Warte220
nop
adiw r24,1 ; Zähler
rjmp mainloop
endless: wdr
rjmp endless
;-----------------------------------------------------------------------
-
ignition:
wdr
push r19 ; Statusregister retten
in r19, SREG ; eben
cpi r17,0 ; Statusflag "jedes zweite Mal" gesetzt?
brne r17r18loeschen ; Wenn gesetzt, dann Flags löschen und zurück
zum Mainloop
ldi r17,1 ; Statusflag "jedes zweite Mal" setzen
ldi r18,1
;Ausrechnen
set ; T-Bit setzen; wird für folgende Anweisung gebraucht
bld r25,7 ; die oberen 2 Bits werden nicht gebraucht,
bld r25,6 ; müssen aber im nächsten Schritt "0" sein; also T-Bit
auf Pos 6 und 7
com r25 ; Komplement bilden, also Bits umdrehen
com r24 ; R25:24 enthält nun Drehzahl/Minute in Reinform <---
movw r26,r24 ; R24:25 in R26:27 sichern <---
;Anzeigen <-------------------------------
sbrc r24,0
rcall lampe0
sbrc r24,1
rcall lampe1
sbrc r24,2
rcall lampe2
sbrc r24,3
rcall lampe3
sbrc r24,4
rcall lampe4
sbrc r24,5
rcall lampe5
sbrc r24,6
rcall lampe6
sbrc r24,7
rcall lampe7
int_fertig:
eor r24,r24 ; r24:25 löschen
eor r25,r25
eor r26,r26
eor r27,r27
out SREG,r19 ; Statusregister wiederherstellen
pop r19 ; dito
reti ; zurück zu main und Ints wieder an
;-----------------------------------------------------------------------
-
r17r18loeschen:
ldi r17,0 ; Statusbit "jedes zweite Mal" löschen
ldi r18,0 ; Statusbit "nach Anzeige -> endless" löschen,
rjmp int_fertig ; denn er muss erstmal Zählen
;-----------------------------------------------------------------------
-
lampe0:
sbi PORTB,0
ret
lampe1:
sbi PORTB,1
ret
lampe2:
sbi PORTB,2
ret
lampe3:
sbi PORTC,0
ret
lampe4:
sbi PORTC,1
ret
lampe5:
sbi PORTC,2
ret
lampe6:
sbi PORTC,3
ret
lampe7:
sbi PORTC,4
ret
------------------------------------------------------------------------
-
Jetzt mein Problem: Die Routine "Anzeigen" (mit Pfeil)
zeigt mir probeweise nur den Inhalt von r24 an. Müsste
aus 0er und 1er bestehen, hängt an einem Frequenzgenerator
mit 118 Hz. Zeigt aber alles 1er an. Warum?
2. Problem... sichern von SREG. Die Routine ist in
anderer Reihenfolge als im Tutorial beschrieben. Ich
sehe keinen Sinn darin r19 zu pushen und dann r19
zu belegen. Müsste nicht SREG in r19 gesichert
werden und dann gepusht?
Danke und frohes Osterfest :-)
olli schrieb:> Jetzt mein Problem: Die Routine "Anzeigen" (mit Pfeil)> zeigt mir probeweise nur den Inhalt von r24 an. Müsste> aus 0er und 1er bestehen, hängt an einem Frequenzgenerator> mit 118 Hz. Zeigt aber alles 1er an. Warum?
Ich kann nicht erkennen, wo und wie Du die Anzeigen wieder löscht.
>> 2. Problem... sichern von SREG. Die Routine ist in> anderer Reihenfolge als im Tutorial beschrieben. Ich> sehe keinen Sinn darin r19 zu pushen und dann r19> zu belegen. Müsste nicht SREG in r19 gesichert> werden und dann gepusht?
Der AVR verfügt über 32 Register, das ist recht viel. Ich verurteile
immer eins davon zur SREG-Kopie, der Rest ist immernoch mehr als genug.
Und zwar ein unteres Register (meist r2 oder r3), da diese nicht ganz so
wertvoll sind (können nicht mit Konstanten operieren). Ich nenn' das
dann "SRSK" (SREG-SicherheitsKopie) und nutze das für nix Anderes als
die Sicherung des SREG. Da braucht man nix Pushen und Poppen, da reicht
einfach
in srsk,sreg ;SREG sichern
zu Beginn der ISR und
out sreg,srsk ;SREG wiederherstellen
reti ;fertig, zurück...
am Ende der ISR.
Und da wir gerade bei den Exclusivregistern (Register für nur einen
Zweck) sind, wenn ich 16-bittig addieren oder subtrahieren muss, dann
benutze ich ein weiteres Exclusiv-Register namens "null" (meist r3 oder
r2), das den Wert 0 enthält und nie für andere Zwecke genutzt wird. Es
eignet sich dann sehr gut zum Addieren/Subtrahieren von Überträgen
(Carry) und macht den Code etwas schlanker und schneller.
...
Danke hannes, das Löschen hab ich vergessen. Ist nun
drin, ändert aber nichts an der Ausgabe. Es erscheint
als wenn das Register r24:25 immer leer übergeben wird?
Jedenfalls sind alle LEDs noch an.
Ich habe mal 2 Ablaufpläne wegen der Übersichtlichkeit
erstellt, einmal Hauptprogramm und die ISR.
Ich Depp habe außerdem r17 für die Zählschleife und
das Flagregister genutzt :-/
also r17 "jede 2. Zündung" und
r18 "nach Anzeige Endlosschleife"
------------------------------------------------------------------------
-
.equ F_CPU, 3686400
.include "AVR.H"
;Reset and Interruptvectoren ;VNr. Beschreibung
begin:
rjmp main ; 1 POWER ON RESET
rjmp ignition ; 2 Int0-Interrupt
reti ; 3 Int1-Interrupt
reti ; 4 TC2 Compare Match
reti ; 5 TC2 Overflow
reti ; 6 TC1 Capture
reti ; 7 TC1 Compare Match A
reti ; 8 TC1 Compare Match B
reti ; 9 TC1 Overflow
reti ;10 TC0 Overflow
reti ;11 SPI, STC Serial Transfer Complete
reti ;12 UART Rx Complete
reti ;13 UART Data Register Empty
reti ;14 UART Tx Complete
reti ;15 ADC Conversion Complete
reti ;16 EEPROM Ready
reti ;17 Analog Comperator
reti ;18 TWI (I²C) Serial Interface
reti ;19 Strore Program Memory Ready
;-----------------------------------------------------------------------
-
;Start, Power ON, Reset
main:
;Stack
ldi r16,hi8(RAMEND)
out ioSPH,r16
ldi r16,lo8(RAMEND) ;Stack Initialisierung
out ioSPL,r16 ;Init Stackpointer
;Interrupt
ldi r16,0b01000000 ;Maskiere INT0
out GICR,r16
ldi r16,0b00000011 ;Konfiguriere
out MCUCR,r16 ;fallende Flanke
;Taster, Lampen
cbi DDRD,2 ;PORTD2 Taster = IN
sbi PORTD,2 ;Pull-Up
sbi DDRD,3 ;Port D.3 = LED OUT
cbi PORTD,3
sbi DDRB,0
cbi PORTB,0
sbi DDRB,1
cbi PORTB,1
sbi DDRB,2
cbi PORTB,2
sbi DDRC,0
cbi PORTC,0
sbi DDRC,1
cbi PORTC,1
sbi DDRC,2
cbi PORTC,2
sbi DDRC,3
cbi PORTC,3
sbi DDRC,4
cbi PORTC,4
ldi r17,0b00000000 ;Statusbit B auf 0
ldi r18,0b00000000 ;Statusbit A auf 0
sei ;alle Interrupts erlauben
;-----------------------------------------------------------------------
-
mainloop:
wdr
cpi r18,0 ; Statusbit "nach Anzeige -> endless" gesetzt?
breq endless ; Wenn nicht gesetzt, dann springe in Endlosschleife
ldi r21, 73
Warte220:
dec r21
brne Warte220
nop
adiw r24,1 ; Zähler
rjmp mainloop
endless: wdr
rjmp endless
;-----------------------------------------------------------------------
-
ignition:
wdr
in r2, SREG ; Statusregister retten
cpi r17,0 ; Statusflag "jedes zweite Mal" gesetzt?
brne r17r18loeschen ; Wenn gesetzt, dann Flags löschen und zurück
zum Mainloop
ldi r17,1 ; Statusflag "jedes zweite Mal" setzen
ldi r18,1
;Ausrechnen
set ; T-Bit setzen; wird für folgende Anweisung gebraucht
bld r25,7 ; die oberen 2 Bits werden nicht gebraucht,
bld r25,6 ; müssen aber im nächsten Schritt "0" sein; also T-Bit auf
Pos 6 und 7
com r25 ; Komplement bilden, also Bits umdrehen
com r24 ; R25:24 enthält nun Drehzahl/Minute in Reinform <---
movw r26,r24 ; R24:25 in R26:27 sichern <---
cbi PORTB,0
cbi PORTB,1
cbi PORTB,2
cbi PORTC,0
cbi PORTC,1
cbi PORTC,2
cbi PORTC,3
cbi PORTC,4
;Anzeigen
sbrc r24,0
rcall lampe0
sbrc r24,1
rcall lampe1
sbrc r24,2
rcall lampe2
sbrc r24,3
rcall lampe3
sbrc r24,4
rcall lampe4
sbrc r24,5
rcall lampe5
sbrc r24,6
rcall lampe6
sbrc r24,7
rcall lampe7
int_fertig:
eor r24,r24 ; r24:25 und Sicherheitskopie löschen
eor r25,r25
eor r26,r26
eor r27,r27
out SREG,r2 ; Statusregister holen
reti ; zurück zu main und Ints wieder an
;-----------------------------------------------------------------------
-
r17r18loeschen:
ldi r17,0 ; Statusbit "jedes zweite Mal" löschen
ldi r18,0 ; Statusbit "nach Anzeige -> endless" löschen,
rjmp int_fertig ; denn er muss erstmal Zählen
;-----------------------------------------------------------------------
-
lampe0:
sbi PORTB,0
ret
lampe1:
sbi PORTB,1
ret
lampe2:
sbi PORTB,2
ret
lampe3:
sbi PORTC,0
ret
lampe4:
sbi PORTC,1
ret
lampe5:
sbi PORTC,2
ret
lampe6:
sbi PORTC,3
ret
lampe7:
sbi PORTC,4
ret
-----------------------------------------------------------------------
Any more ideas? :-)
Frohe Ostern,
Olli
edit:
wenn ich einen Wert in der Hauptroutine in r24 lade,
kommt "0" raus. Wenn ich in die Interruptroutine diesen
Wert lade, wird dieser korrekt angezeigt. Wird r24 irgendwie
gelöscht?
Nimm mal den Befehl WDR ( Watchdog Reset) raus.
So wie ich das sehe hast du den nicht richtig initalisiert und
behandelt.
Dadurch könnte der Controller möglicherweise selber einen Reset auslösen
bevor die ISR aufgerufen wird.
wdr hat nichts gebracht. Die unseelige Endlosschleife habe
ich jetzt aber entfernt, jetzt kann ich in die Bits
je nach Frequenz reingucken :-) Ich frage mich nur, ob
der jetzt auch anzeigt was ich mir ausdenke^^
Hi
>endless: wdr> rjmp endless
Was soll danach noch passieren?
>reti ; zurück zu main und Ints wieder an
Glaubst du das wirklich?
> set ; T-Bit setzen; wird für folgende Anweisung gebraucht> bld r25,7 ; die oberen 2 Bits werden nicht gebraucht,> bld r25,6 ; müssen aber im nächsten Schritt "0" sein; also T-Bit auf
Ein 'ori r25, 0b11000000' hätte auch gereicht.
> com r25 ; Komplement bilden, also Bits umdrehen> com r24 ; R25:24 enthält nun Drehzahl/Minute in Reinform <---
Unnötig, wenn du
sbrs r24,0
rcall lampe0 benutzt
> movw r26,r24 ; R24:25 in R26:27 sichern <---
Wozu?
MfG Spess
> cpi r17,0 ; Statusflag "jedes zweite Mal" gesetzt?> brne r17r18loeschen ; Wenn gesetzt, dann Flags löschen und zurück>zum Mainloop> ldi r17,1 ; Statusflag "jedes zweite Mal" setzen> ldi r18,1
Kannst du dir alles sparen. Einfach
1
inc r17
2
sbrc r17,0
3
rjmp int_fertig
> ldi r17,0b00000000 ;Statusbit B auf 0> ldi r18,0b00000000 ;Statusbit A auf 0> eor r24,r24 ; r24:25 und Sicherheitskopie löschen> eor r25,r25> eor r26,r26> eor r27,r27
Hi
Zu schnell auf 'Absenden' gedrückt.
>> ldi r17,0b00000000 ;Statusbit B auf 0>> ldi r18,0b00000000 ;Statusbit A auf 0>> eor r24,r24 ; r24:25 und Sicherheitskopie löschen>> eor r25,r25>> eor r26,r26>> eor r27,r27
Dafür gibt es 'clr rxy'.
MfG Spess
spess53 schrieb:
Ah, danke Spess. Fangen wir an...
>>endless: wdr>> rjmp endless>> Was soll danach noch passieren?
Der soll von der Zündung wieder zum Leben
erweckt werden. Da liegt dann aber wohl der Fehler,
er rennt zurück in die Endlosschleife und hängt
sich dort... ahhh! :-)
Fahre den jetzt in SLEEP, allerdings bin ich nicht
sicher ob das zu was gut ist.
>>reti ; zurück zu main und Ints wieder an> Glaubst du das wirklich?
Zurück zu Mainloop meinte ich.
>> set ; T-Bit setzen; wird für folgende Anweisung gebraucht>> bld r25,7 ; die oberen 2 Bits werden nicht gebraucht,>> bld r25,6 ; müssen aber im nächsten Schritt "0" sein; also T-Bit auf>> Ein 'ori r25, 0b11000000' hätte auch gereicht.
okay.
>>> com r25 ; Komplement bilden, also Bits umdrehen>> com r24 ; R25:24 enthält nun Drehzahl/Minute in Reinform <--->> Unnötig, wenn du>> sbrs r24,0> rcall lampe0 benutzt
Das ist nur für die weitere Rechnung. Ich muss noch
die Bereiche jeder einzelnen LED festlegen, das eine z.B.
zwischen 6540 und 6590 Umdrehungen angeht. Jetzt wollte
ich ja nur mal eine Anzeige machen, ob der überhaupt
>> movw r26,r24 ; R24:25 in R26:27 sichern <---
Relikt. :-)
> Kannst du dir alles sparen. Einfach> inc r17> sbrc r17,0> rjmp int_fertig
Right you are!
>> ldi r17,0b00000000 ;Statusbit B auf 0>> ldi r18,0b00000000 ;Statusbit A auf 0>> eor r24,r24 ; r24:25 und Sicherheitskopie löschen>> eor r25,r25>> eor r26,r26>> eor r27,r27
Okay, clr. Ich habe als Teenager mal einen ASM-Kurs
für PCs mitgemacht. Da hieß es: Register löschen mit XOR ;-)
Problem jetzt ist, das er bei 113 Hz (6780 U/m) in
r24:25 eine Umdrehungszahl von 16237 hat. Da muss ich jetzt mal
suchen.
-----------------------------------------------------------------------
;Start, Power ON, Reset
main:
;Stack
ldi r16,hi8(RAMEND)
out ioSPH,r16
ldi r16,lo8(RAMEND) ;Stack Initialisierung
out ioSPL,r16 ;Init Stackpointer
;Interrupt
ldi r16,0b01000000 ;Maskiere INT0
out GICR,r16
ldi r16,0b00000011 ;Konfiguriere
out MCUCR,r16 ;fallende Flanke
;Taster, Lampen
cbi DDRD,2 ;PORTD2 Taster = IN
sbi PORTD,2 ;Pull-Up
sbi DDRD,3 ;Port D.3 = LED OUT
cbi PORTD,3
sbi DDRB,0
cbi PORTB,0
sbi DDRB,1
cbi PORTB,1
sbi DDRB,2
cbi PORTB,2
sbi DDRC,0
cbi PORTC,0
sbi DDRC,1
cbi PORTC,1
sbi DDRC,2
cbi PORTC,2
sbi DDRC,3
cbi PORTC,3
sbi DDRC,4
cbi PORTC,4
clr r17
clr r18 ;Statusbit B auf 0
sei ;alle Interrupts erlauben
;-----------------------------------------------------------------------
-
mainloop:
ldi r21, 73
Warte220:
dec r21
brne Warte220
nop
adiw r24,1 ; Zähler
rjmp mainloop
;-----------------------------------------------------------------------
-
ignition:
wdr
in r2, SREG ; Statusregister retten
inc r17
sbrc r17,0
rjmp int_fertig
;Ausrechnen
ori r25,0b11000000
com r25 ; Komplement bilden, also Bits umdrehen
com r24 ; R25:24 enthält nun Drehzahl/Minute in Reinform <---
cbi PORTB,0
cbi PORTB,1
cbi PORTB,2
cbi PORTC,0
cbi PORTC,1
cbi PORTC,2
cbi PORTC,3
cbi PORTC,4
;Anzeigen
sbrc r24,0
rcall lampe0
sbrc r24,1
rcall lampe1
sbrc r24,2
rcall lampe2
sbrc r24,3
rcall lampe3
sbrc r24,4
rcall lampe4
sbrc r24,5
rcall lampe5
sbrc r24,6
rcall lampe6
sbrc r24,7
rcall lampe7
int_fertig:
clr r24
clr r25
out SREG,r2 ; Statusregister holen
sleep
reti ; zurück zu mainloop und Ints wieder an
;-----------------------------------------------------------------------
-
r17r18loeschen:
clr r17 ; Statusbit "jedes zweite Mal" löschen
clr r18 ; Statusbit "nach Anzeige -> endless" löschen,
rjmp int_fertig ; denn er muss erstmal Zählen
;-----------------------------------------------------------------------
-
lampe0:
sbi PORTB,0
ret
lampexy...
------------------------------------------------------------------------
-
Hmmm ....
Was ist das eigentlich?
2-Takter, 4-Takter?
Wieviele Zylinder?
Reihen-, Boxer- oder V-Motor?
Und wo greifst Du die Impulse ab?
Weshalb ich diese Fragen stelle: Zwischen den einzelnen Zylindern hast
Du möglicherweise unterschiedliche Zündwinkel. D.h. bei selber Drehzahl
unterschiedliche Zeiten zwischen den Zündungen.
Aber selbst wenn ich von einem 1-Zyl. 2-Takter ausgehe, finde ich die
Herangehensweise etwas ungeschickt.
Du möchtest doch letzlich Umdrehungen pro Zeit haben und nicht Zeit pro
Umdrehung. (Was bringt Dir die Angabe '8,57ms/U' ... ? :-)
Meine Herangehensweise wäre:
- Hauptprogramm initialisiert Timer und IRQs und legt sich dann
schlafen.
- Zähle 'Zündimpulse' in einem IRQ.
- Timer-IRQ alle 120ms: Zündimpulse*500 (=U/min) auf Display ausgeben
und Zündimpulse auf 0 setzen.
Gruß
Jobst
olli schrieb:> ori r25,0b11000000> com r25 ; Komplement bilden, also Bits umdrehen> com r24 ; R25:24 enthält nun Drehzahl/Minute in Reinform <---
Komplement ist im übrigen nicht der Kehrwert, den Du aber benötigst ...
Gruß
Jobst
Nebenbei: AVR-ASM bitte in [avrasm ] Hier steht der Code [/avrasm ]
(ohne Leerzeichen) einfassen bzw. (wenns länger ist) als Datei (Endung
asm!) anhängen.
Jobst M. schrieb:> Hmmm ....>> Was ist das eigentlich?
Eine Simme. Also 2 Takte, ein Zylinder. geht ab wie Schmidt seine Katze
=:-)
> Und wo greifst Du die Impulse ab?
Ein Schmitt-Trigger, 4093 heißt der glaube ich. Ist schon
fertig, tut was er soll und kann direkt an den AVR angeschlossen
werden.
> Aber selbst wenn ich von einem 1-Zyl. 2-Takter ausgehe, finde ich die> Herangehensweise etwas ungeschickt.
Hm, hm, mag sein. Anfänger halt ;)
> Du möchtest doch letzlich Umdrehungen pro Zeit haben und nicht Zeit pro> Umdrehung. (Was bringt Dir die Angabe '8,57ms/U' ... ? :-)
Oh man. Ich glaube ich verstehe langsam was Du meinst. Ich
habe mir das falsch überlegt. Das ist ja kein Wunder wenn nicht
das rauskommt was ich will.
> Meine Herangehensweise wäre:>> - Hauptprogramm initialisiert Timer und IRQs und legt sich dann> schlafen.> - Zähle 'Zündimpulse' in einem IRQ.> - Timer-IRQ alle 120ms: Zündimpulse*500 (=U/min) auf Display ausgeben> und Zündimpulse auf 0 setzen.
Ohne irgendwas zu verstehen, versuche ich mich jetzt mal daran.
Problem bei den 120ms und Impulse*500 ist doch aber
die Auflösung, oder? Ich möchte später Umdrehungen in
einer Auflösung von ungefähr 100 darstellen. Zusätzlich
wäre noch die Erweiterbarkeit auf ein LCD angedacht, deshalb
würd ich die Umdrehungen gern sehr genau angeben.
Oh man, ich seh schon. Das wird was. Bis Donnerstag muss der
Code fertig sein, damit ich noch die Stromversorgung und Halterung
fürs Mopped bauen kann. PDF muss auch noch geschrieben werden
und Sonntag ist Abgabe. Ob ich das noch hinkrieg? :-/
olli schrieb:> Ich möchte später Umdrehungen in> einer Auflösung von ungefähr 100 darstellen.
Dann nimmst Du den Mittelwert aus den letzten 5 Messungen.
Das ist aber leicht nachzurüsten, wenn der Rest läuft.
Aber rechne auch mal nach, wie viele LEDs Du dafür benötigst!
Jobst M. schrieb:> Und wo greifst Du die Impulse ab?
Damit meinte ich eigentlich die Stelle im Motor. Ist aber bei einem
1-Zylinder auch egal.
olli schrieb:> Bis Donnerstag muss der Code fertig sein
Sollte machbar sein ;-)
Gruß
Jobst
Also ich machs so wie Du mit den 120ms geschrieben hast
und nehme dann den Mittelwert von 5 Umdrehungen? Klingt
logisch, ich frag mich nur ob es nicht genauer geht?
Muss ich unbedingt den Interrupt-Capture von PortB nutzen?
Weil der ist schon mit einer LED belegt...
Das mit den LEDs passt. Es sind 8 Stück. Mit denen soll
nur die Resokurve dargestellt werden, also z.b. 5500-7500.
Mit 8 Lampen kann ich bei Doppelbelegungen 15 Zustände
anzeigen, also 2000/15=133 Umdrehungen.
Hmpf...
olli schrieb:> Muss ich unbedingt den Interrupt-Capture von PortB nutzen?
Für den Eingang des Zündimpulses benötigst Du einen IRQ-Pin. Welchen ist
egal. Aber den hast Du doch schon angeschlossen!?
Für den Timer-IRQ benötigst Du keinen Pin.
olli schrieb:> Mit 8 Lampen kann ich bei Doppelbelegungen 15 Zustände> anzeigen
Was bedeutet Doppelbelegung?
olli schrieb:> und nehme dann den Mittelwert von 5 Umdrehungen?
Nein, den Mittelwert von 5 Messungen. Du kannst auch alternativ 600ms
warten, aber ich vermute, daß Dir das zu ruckelig wird.
D.h. Du musst Dir die letzten 5 Messungen merken. Diese 5 Werte addierst
Du schlicht und setzt '00' dahinter. Bis 255+'00' U/min geht das noch in
einem Byte.
Welchen uC verwendest Du eigentlich?
Gruß
Jobst
Hallo Jobst,
ich nutze den Int0, also D2 beim AtMega8.
Doppelbelegungen heißt erst alle Lampen hintereinander
an, dann bei 1 beginnend wieder ausknispen. Ergibt 15
Kombinationen bei 8 LEDs und stellt die Leistungskurve
recht anschaulich dar.
Nochmal: Ich konfiguriere den Timer darauf, alle 120ms
einen Int auszulösen. Innerhalb dieser Ints zähle ich
die Zündungen, also bei 8000 U/min sind das z.B.
133 U/s / 8,33 = 15,96 Impulse in dem 120ms Intervall.
Dann speichere ich 5 Messungen, also 5*16 = 80. Und
da kommen dann eben die zwei 00er dran. Aha. Auflösung
ergibt dann 100 Umdrehungen, gelle? Könnte ich 1500
Umdrehungen aus meinem Band raussuchen. Habe die Kurve
mal angehangen, oben Leistung, unten Drehmoment. Würde
den Huckel bei 7000 darstellen wollen.
Danke,
Olli
olli schrieb:> ich nutze den Int0, also D2 beim AtMega8.
Das kannst Du ja auch so lassen, wenn das schon läuft.
> Würde den Huckel bei 7000 darstellen wollen.
Also 6300 - 7700 U/min
6300 U/min ist der Wert 63 - da soll die Skala also beginnen.
Also vom Wert 62 abziehen. Klappt das ohne Unterlauf (Carry-Flag) ist
der Wert gültig, sonst alle LEDs aus.
Bei 1 dann die erste LED einschalten, bei 2 auch die zweite ... etc.
Gruß
Jobst
Hi
>ignition: CLI> LDS backup, SREG -> in backup, SREG> INC counter> STS SREG, backup -> out SREG, backup> SEI -> das macht RETI
Lds/sts gehen auch, aber nur mit SREG + $20.
> ADD temp, merker2> ADD temp, merker3> ADD temp, merker4> ADD temp, merker5> ; LED-Muster aus dem ROM holen> ldi ZL, LOW(LEDs*2) ; Basisadresse in Z laden> ldi ZH, HIGH(LEDs*2)> ADD ZL, temp ; temp dazu addieren> ....
Meinst du nicht, das hier eine Division durch 5 fehlt?
MfG Spess
Eingepflegt. (Wieso kann das nicht alles, wie beim 8051 MOV sein? :)
spess53 schrieb:> Meinst du nicht, das hier eine Division durch 5 fehlt?
Nein, fehlt nicht. Wird ja immer nur 1/5 gemessen
Gruß
Jobst
spess53 schrieb:> Die riesen Tabelle kannst du dir übrigens mit ein befehlen sparen:
Die ist nachträglich sogar erst rein gewandert ;-)
So ähnlich hatte ich es zuerst.
(Das war zu diesem Zeitpunkt:
Beitrag "Re: AVR asm - Befehl nur jedes 2. mal ausführen" )
Aber damit hat man nun die Möglichkeit, auch für die anderen Drehzahlen
noch Muster festzulegen.
Ausserdem ist der Speicherplatz ja da ...
Edit: Ich hatte zwischendurch auch die Idee, in der Tabelle die
Drehmomentkurve abzulegen.
Gruß
Jobst
Halt ein, ich arbeite ja auch dran. Bisher ändern sich
die LEDs mit der neuen Routine wenn ich die Frequenz ändere...
ich hatte nur noch nicht viel Zeit für die eigentliche
Abfrage der richtigen Bereiche für die LEDs. Morgen abend! :-)
Danke,
Olli :-)
Der Code gefällt mir. Problem ist, das ganze ist
zur Teilnahme an einem Gewinnspiel von myavr.de .
Ich nutze die Software von denen, Workpad. Und obwohl
es mit AVR-Assembler kompatibel sein soll, kann ich
die .db Tabelle nicht einfügen. Jetzt kann ich natürlich
AVR-Studio nutzen, aber ich probier noch ein bisschen
rum ob ich es in Workpad zum Laufen kriege ;) Habe mit
AVR-Studio auch noch nicht gearbeitet und weiß nicht
ob er mein Board erkennt (ISP wäre möglich, ist
aber kompliziert).
olli schrieb:> Workpad
Ähm ... sehe ich das richtig, daß es kein pdf-Handbuch dafür gibt,
sondern nur ein Windows-Hilfe-File? -.-
Wie fügt man denn dort Datenfelder ein?
Hannes Lux schrieb:> Dann solltest Du aber den Gewinn an die Helfer abtreten...
Sehe ich persönlich nicht so eng. Ich wusste es ja schon vorher.
Gruß
Jobst
Jobst M. schrieb:> Sehe ich persönlich nicht so eng. Ich wusste es ja schon vorher.
Ich will da keinesfalls was von abhaben, habe mich ja auch rausgehalten,
seitdem von Abgabetermin die Rede war. Allerdings mag ich es nicht
besonders, wenn man sich mit fremden Federn schmückt.
Andererseits passt das ja voll in unsere heutige Gesellschaft. Das
Pferd, das den Hafer verdient, bekommt ihn sowiso nicht...
...
Hannes Lux schrieb:> Allerdings mag ich es nicht> besonders, wenn man sich mit fremden Federn schmückt.
Ja, prinzipiell gebe ich Dir da Recht.
Allerdings war der Code zur Hälfte in einem anderen Programm schon
fertig und es hat mir in den Fingern gekribbelt. :-)
Und dann finde ich es auch blöd zu sagen: 'Hey! Ich hab's schon fertig,
bekommst Du aber nicht'
Und ich hatte nicht den Eindruck, als ob er faul auf dem Arsch sitzt und
auf die Lösung wartet. Da kann man das mal machen. ;-)
Gruß
Jobst
Ist mir doch auch schon öfters passiert, das letzte mal ist noch gar
nicht so lange her: Beitrag "Re: Schalter zu Taster"
Da ging's aber glaube nicht um einen Wettbewerb oder um Hausaufgaben.
;-)
Ich versuche ja, mich auf Hilfe zur Selbsthilfe zu beschränken. Aber oft
sind die Programmansätze dermaßen daneben (umständlich), dass es sich
nicht lohnt, daran herumzubasteln.
Hast übrigens 'ne schöne HP. Habe aber leider keine Elektronikbasteleien
gefunden... 8-(
...
("..." heißt soviel wie: "Beste Grüße, Hannes")
@hannes
Den Gedanken habe ich auch. Ohne Euch, besonders Jobst,
wäre die Sache jetzt aussichtslos.
Ich habe da auch schon was im Sinn. Ganz mit fremden Federn
schmücken werde ich mich jedenfalls nicht, auch wenn es
sich schwer vermeiden lässt. Eine Nennung ist selbstverständlich,
ein Anteil (sofern es sich nicht um den Büchergutschein handelt)
ist auch drin. Ich schätze sehr das sich Jobst so reingehangen
hat, immerhin schwirrte das Projekt schon Monate in meinem Kopf.
So, jetzt aber ran ans Werk.
Gruß,
Olli
p.s. Übrigens sehr schicke Fotos, Jobst! :-D
Also ich habe den Code von Jobst etwas abgeändert, u.a.
wird eine andere Warteroutine verwendet.
Die .db bekomme ich mit Workpad nicht in den Speicher
geladen, er erkennt den Syntax nicht. Habe den
Support angeschrieben.
Ich versuche es ohne die .db, mit <> Abfragen.
Momentan reicht mir aber eine korrekte Anzeige
von r16 (temp), ich gebe sie direkt auf die LEDs
aus. Diese ist bei 113 Hz (6800 Umdrehungen)
01000100, also 68, bzw. bei 166,67 Hz (10.000 U)
01100100, also 100 dezimal!! (Jetzt fehlt der Smiley
mit den zwei Biergläsern^^). :-)
Muss grad los, heute Abend entweder mit .db Tabelle,
oder ich versuche die <> Abfragen einzufügen.
Muss man in Workpad wirklich alle IRQ-Vektoren auflisten? =-O
Und für Register kann man auch keine Namen definieren? :-/
Wieso möchtest Du nur jedes 2. Mal messen?
Und wenn, dann mach es auch. Denn den Zähler setzt Du erst nach dem
Sprung wieder zurück.
(Und wenn Du es dann geschafft hast, funktioniert es nicht mehr!) ;-)
Okay, Du gibst die Drehzahl derzeit binär aus - leider nicht sehr
einfach abzulesen.
Füge nach den 4 Additionen doch mal dies ein:
1
SUBI r16, 62 ; 62 abziehen (negative Ergebnisse sind egal)
2
3
CLR r24 ; default-Muster
4
5
CPI r16, 1 ; vergleichen
6
BRNE test2
7
LDI r24, 128 ; wenn zutreffend, neues Muster setzen
8
test2;
9
CPI r16, 2
10
BRNE test3
11
LDI r24, 192 ; ... und so weiter
12
test3;
13
CPI r16, 3
14
BRNE test4
15
LDI r24, 224
16
test4;
17
CPI r16, 4
18
BRNE test5
19
LDI r24, 240
20
test5;
21
CPI r16, 5
22
BRNE test6
23
LDI r24, 248
24
test6;
25
CPI r16, 6
26
BRNE test7
27
LDI r24, 252
28
test7;
29
CPI r16, 7
30
BRNE test8
31
LDI r24, 254
32
test8;
33
CPI r16, 8
34
BRNE test9
35
LDI r24, 255
36
test9;
37
CPI r16, 9
38
BRNE test10 ; Klapper-di-klapper
39
LDI r24, 127
40
test10;
41
CPI r16, 10
42
BRNE test11
43
LDI r24, 63
44
test11;
45
CPI r16, 11
46
BRNE test12
47
LDI r24, 31
48
test12;
49
CPI r16, 12
50
BRNE test13
51
LDI r24, 15
52
test13;
53
CPI r16, 13
54
BRNE test14
55
LDI r24, 7
56
test14;
57
CPI r16, 14
58
BRNE test15
59
LDI r24, 3
60
test15;
61
CPI r16, 15
62
BRNE test16
63
LDI r24, 1
64
test16;
65
66
MOV r16,r24
Ich hasse Workpad jetzt schon ... die reinste Spaghettischleuder ...
... und am ENDE sagst Du ihm, er soll sich in 60ms wieder melden ...
+grübel+ (Tut er das?)
Gut, der Code nimmt nur wenig Zeit in Anspruch - das wird es kaum
verfälschen.
Wenn Du das sowieso 2 mal machst, wieso nimmst Du dann nicht gleich 1x
120ms ?
Ach, ... aber wieso? ... häää? :-D
Also: Du wirfst jeden 2. Timer-IRQ quasi weg. Dafür hast Du die Anzahl
verdoppelt ... Wieso machst Du das?
Gruß
Jobst
> Muss man in Workpad wirklich alle IRQ-Vektoren auflisten? =-O
Ich bin mir nicht sicher, ich glaube es wird als
Empfehlung gegeben. Gewöhnt man sich aber schnell dran,
finde ich leichter zu lesen als Atmel-AVR.
> Und für Register kann man auch keine Namen definieren? :-/
Ich habe es noch nicht gefunden wie es geht... wenn es geht.
1
ganz viel Code...
Mensch Jobst... da wars dann um meinen Eigenanteil.
Ich hab den neuen Code eingefügt, muss noch die Richtung
ändern. aber erstmal genau überlegen was der macht.
Danke erstmal soweit.
> Ich hasse Workpad jetzt schon ... die reinste Spaghettischleuder ...
Du meinst viele Zeilen? ;)
> Wenn Du das sowieso 2 mal machst, wieso nimmst Du dann nicht gleich 1x> 120ms ?
Ich habe die Routine geschrieben, bevor Deine kam. Habs
aus dem myAVR-Buch, nur in dem Beispiel gingen eben nur
maximal irgendwas unter 120ms... also hab ich einfach zweimal
eine 60er gemacht :-) Schlechter Stil, oder?
Routine passt ja jetzt soweit. Ich denk mich da
jetzt noch rein und mache etwas Feinschliff. Dann kann
ich ja morgen schon mit der PDF anfangen :-)
Danke Dir und wir hören uns ;)
Olli
Ach nochwas. Die Anzeige pendelt immer um eine LED
am Rand. Ist wegen der 120er Intervalle, die die
Kommastelle abhacken, oder?
Also z.B. bei 12,3 U/s:
12, 12, 12, 12, 13, 12...
Hmmm...
olli schrieb:> Mensch Jobst... da wars dann um meinen Eigenanteil.
Ach, verdammt. Tut mir leid. Nimm's wieder raus! :-)
olli schrieb:> Du meinst viele Zeilen? ;)
Vor allem Zeilen, die alle (fast) das selbe machen ...
olli schrieb:> Die Anzeige pendelt immer um eine LED> am Rand. Ist wegen der 120er Intervalle, die die> Kommastelle abhacken, oder?
Solange Du die Drehzahl nicht mit den 120ms synchronisierst, wird das
immer wieder passieren. Das ist nochmal eine kleine Denkaufgabe, das
heraus zu filtern ;-)
Gruß
Jobst
olli schrieb:> Die Anzeige pendelt immer um eine LED> am Rand.
Das ist eigentlich bei so ziemlich jeder Messwerterfassung der Fall. Ich
eliminiere das meist mittels Hysterese, übernehme also Änderungen des
Messwertes erst, wenn sie einen bestimmten Betrag überschreiten.
olli schrieb:> Die .db bekomme ich mit Workpad nicht in den Speicher> geladen, er erkennt den Syntax nicht. Habe den> Support angeschrieben.>> Ich versuche es ohne die .db, mit <> Abfragen.
Als Alternative gibt's noch das EEPROM oder ein Array im SRAM.
Wobei ich mich schon lange nach der Existenzberechtigung des Workpads
und der anderen myAVR-Software frage, denn AVR-Studio ist kostenfrei und
trotzdem sehr brauchbar.
Jobst M. schrieb:> Muss man in Workpad wirklich alle IRQ-Vektoren auflisten? =-O
Das mache ich auch im AVR-Studio grundsätzlich so, ergibt halt eine
unfragmentierte Hex-Datei. Ist auch kein Problem, denn ich habe
inzwischen die Interrupt-Sprungtabellen der von mir benutzten AVRs in
eine Textdatei kopiert, aus der ich mir bei jedem neuen Projekt die
Tabelle herauskopiere. Mit .Org und Angabe der Adresse über vereinbarte
Namen muss man ja auch die korrekte Reihenfolge einhalten, da kann man
auch gleich die ganze Liste kopieren und die unbenutzten Einträge
"deaktivieren". Ist in meinen Augen übersichtlicher. Eine neue
Sprungtabelle kopiere ich aus dem Datenblatt heraus und lösche dann die
Adressen raus.
...
Hannes Lux schrieb:> Jobst M. schrieb:>> Muss man in Workpad wirklich alle IRQ-Vektoren auflisten? =-O> [...]
Okay. Ich meinte das eigentlich anders:
Gibt es bei Workpad kein .org ?
Nicht, daß man es benutzen muß.
Gruß
Jobst
Jobst M. schrieb:> Gibt es bei Workpad kein .org ?
Gibt es einen Grund, Workpad zu benutzen?
> Nicht, daß man es benutzen muß.
Eben!
Was gibt es für einen Grund, ein Drittanbieter-Produkt zu benutzen, das
dem kostenlos erhältlichen Original nicht das Wasser reichen kann?
Und ja, ich habe auch mal ein Projekt auf einem myAVR-Board
programmiert, hatte auch die (sauteure) CD mit der Sisy-Software hier.
Ich habe es aber mit AVR-Studio realisiert und den "Auftraggeber" (ein
Papi, der dem Sportverein seiner Tochter eine lichtschrankengesteuerte
Stoppuhr sponsern wollte) dazu gebracht, den Mist zu ignorieren und das
AVR-Studio zu benutzen. Das Projekt steht seit Jahren auf meiner HP.
Sisy hat es gefunden und mich gebeten, es auf ihrer Seite als Referenz
angeben zu dürfen, obwohl ich es nicht mit ihrem Workpad realisiert
hatte und auch kein Kunde von ihnen bin.
Wer Hardware von dort kaufen will, weil er nicht basteln will, der soll
es tun.
Wer aber meint, er könne dort "Wissen" kaufen, der irrt. Das Wissen muss
man sich selbst erarbeiten. Und da ist es nicht besonders ratsam, auf
die Original-Programmiersoftware von Atmel zu verzichten und eine völlig
quelltextinkompatible Alternative zu benutzen.
Ich sehe also keinerlei Anlass, zu erforschen, wie man bei Workpad
gewisse Dinge löst, die anders sind als bei AVR-Studio.
...
> Was gibt es für einen Grund, ein Drittanbieter-Produkt zu benutzen, das> dem kostenlos erhältlichen Original nicht das Wasser reichen kann?
myAVR macht das alles komplett. Also Hardware+Software+Buch.
Workpad ist sehr übersichtlich, hat z.B. eine farbliche
Abhebung der einzelnen Befehle und viele Beispiele die
out-of-the-box mit myAVR Hardware läuft und so spielerisch
die Grundlagen vermittelt. Es ist nicht das non+ultra,
aber ich arbeite gern damit.
Was etwas nervt sind die unterschiedlichen Dialekte von
Atmel und Gnu. .db wird zu .byte usw. Ist leider auch nicht
gut von myAVR dokumentiert.
Sisy ist wirklich etwas teuer, aber Workpad gibts ja schon
für 15 bzw. 25 Euro.
Momentaner Stand der Software ist jetzt, das ich die Overrev-LEDs
mit 8,3 Hz blinken lasse, wenn 7700 Umdrehungen überschritten
werden. Wollte das Bit in r5 nutzen, ging aber nicht?!
jedenfalls jetzt r4 genommen und alles schick. Ich schau nochmal
wegen eines Filters, wenn ich es gleich nicht hinbekomme, ist
auch nicht so wild. Wenn Ihr noch stilistische Ideen habt,
immer her damit! :)
Heute wurde ich per Mail von myAVR-Team benachrichtigt, dass dieser
Wettbewerb läuft. Ist ja noch viel Zeit bis zum Termin... ;-)
Man gut, dass ich für Wettbewerbe sowiso nichts übrig habe...
...
spess53 schrieb:> Z.B. wenn ich deine CPI-Orgie wird mir richtig schlecht.
Mir auch. Obwohl sie von mir stammt.
Also die CPI-Orgie. Aber woher stammt Dein Zitat? :-)
Olli:
Wenn .db durch .byte ersetzt werden kann, bau doch die Tabelle einfach
wieder ein :-)
Gruß
Jobst
Jungs, da habt Ihr wohl recht. Die Sache ist nur, ich bin
Anfänger und finde das Programm so wie es jetzt ist gut
und Eure Veränderungen gehen mir etwas zu sehr ins Mark.
Also nicht böse sein, ich lass es jetzt so und sehe zu
das Video und PDF zu basteln... vielleicht habe ich
sogar am Sonntag noch ein bisschen Freizeit um in die
Sonne zu gehen.. ;)
Hi
>Jungs, da habt Ihr wohl recht.
du hast doch geschrieben:
Wenn Ihr noch stilistische Ideen habt, immer her damit! :)
Z.B. die exessive Benutzung von sbi/cbi bei der Initialisierung der
Ports.
An der Stelle brauchst du keine Rücksicht auf den Zustand der Register
nehmen. Da reicht also:
ldi r16,blabla
out Portxy, r16
MfG Spess
Danke soweit.
Ich habs heute mal eingebaut. Es ging ab und zu mal,
war schon fein. Nur ständige Aussetzer. Also nochmal
die Zündabnahme nachgelötet.
Jetzt geht es garnicht mehr am Moped. Schließe ich
einen Frequenzgenerator (anderer AtMega) an, funktionierts.
Habe mein Problem mit Bild zwecks größerem Publikum
nochmal in einen anderen Thread geschrieben, also wer
will kann auch nochmal ein Auge werfen:
Beitrag "Selbstbau Drehzahlmesser und 5V Signal"
Danke,
Olli :-)
So, ich habe es eingereicht. Sind dann doch 14 Seiten PDF
mit Bildern geworden. Ich stells mal rein wenn es
dort veröffentlicht wurde, myAVR will erst nochmal drübergucken.
Danke an alle die mitgeholfen haben,
Olli :-)
So, das Projekt samt Abstimmung ist online. Sind immerhin 10
Projekte, was bei 10 Preisen schonmal mindestens einen
Einkaufsgutschein ausmacht ;)
Ich habe mir überlegt das wenn ich es unter die ersten 3 schaffen
sollte - was ein Preisgeld bedeutet - ich Jobsten 1/3 davon
abgebe. Was meint Ihr, ist das angemessen?
Hier, wenn Ihr schauen&voten wollt:
http://projekte.myavr.de/?sp=voting/listProjekt&vId=2&MENUS=Infos%20/%20Preisausschr.
Gruß,
Olli :-)