Hallo Leute,
die letzte Frage für heute, ich seh's nicht.
wie löse ich das:
port 0b10101010
maske 0b01011100
werte 0b01010000
------------
port neu 0b11010010
also port mit maske auf wert setzen.
Ist das überhaupt effizient, um einen Schrittmotor anzutreiben?
Ich hatte mir das nämlich so gedacht:
1
// bit mask for stepper motor outputs (current setup: 0b01011100)
2
step_mask=1<<MCa1|1<<MCa2|1<<MCb1|1<<MCb2;
3
// contains active coils
4
step[0]=1<<MCa1|1<<MCb2;
5
step[1]=1<<MCa1|1<<MCb1;
6
step[2]=1<<MCa2|1<<MCb1;
7
step[3]=1<<MCa2|1<<MCb2;
Ich vermute, daß ich leider noch eine Hilfsvariable benötige. So etwa
HilfeV=port
HilfeV mit maske löschen
HilfeV mit step[] setzen
port=hilfe
und hoffe, jemand ist pfiffiger als ich und sagt es mir :-)
danke schonmal!
Hmmm...
Also professionelle Schrittmotorsteuerung macht man mit
Spezialschaltkreisen. Da werden die Spulen im Chopperbetrieb bestromt.
Gute, aber nicht ganz billige Lösungen gibt es z.B. von Trinamic.
Einfache Schrittmotorsteuerungen mache ich mit einer Tabelle mit
Bitmuster (Auszug aus Programm):
;Schrittmotor an PortD, Pins PD7, PD6, PD5, PD4
.equ smp=portd ;Schrittmotor-Port (PORTx)
.equ smm=0b11110000 ;Schrittmotor-Bitmaske
stellmot:
ldi zl,low(bimu*2) ;Zeiger auf
ldi zh,high(bimu*2) ;Motor-Bitmuster
mov wl,posi ;Kopie von Position zwecks
andi wl,7 ;Ausblendung der oberen Bits
add zl,wl ;Offset dazu,
adc zh,null ;Übertrag auch
lpm wl,z ;Bitmuster holen
andi wl,smm ;eventuell ungültige Bits ausblenden
in wh,smp ;Schrittmotor-Port einlesen
andi wh,255-smm ;Schrittmotor-Bits löschen
or wh,wl ;neue Schrittmotor-Bits dazu
out smp,wh ;und an Port ausgeben
rjmp fertig ;fertig...
bimu: ;Bitmuster für Schrittmotor
.db 0b10000000,0b11000000 ;
.db 0b01000000,0b01100000 ;
.db 0b00100000,0b00110000 ;
.db 0b00010000,0b10010000 ;
Das Ganze läuft dann in einem Timer-Interrupt.
...
Bringt das irgendwelche Vorteile:
Port=(Port& ~maske) | step[];
oder so:
port ^= step[i] | step[i+1] ;
(aber das geht nur gut, wenn der Motor bereits läuft)
Mhh.
oh, da war ja doch noch einer..danke schonmal, aber asm verstehe ich
jetzt mit sicherheit nicht mehr. aber morgen ist ja auch noch ein tag!
;-)
Obwohl, Du machst es ja auch so:
Schrittmotor-Port einlesen
Schrittmotor-Bits löschen
neue Schrittmotor-Bits dazu
und an Port ausgeben
und was passiert, wenn zwischen einlesen und ausgeben sich etwas an
einem eingang desselben ports ändert? chaos & mayhem? oder ist es eher
unwahrscheinlich, daß sich in 1/1000000 sekunde was ändert ?
Da kann sich in meinem Fall nix ändern, da das gesamte Programm aus
einer einzigen ISR (Timer-Int) besteht und in der Mainloop nur gepennt
wird. - Gepennt noch nicht, da das Programm noch nicht endgültig fertig
ist. Die Mainloop ist also (noch) eine leere Endlosschleife.
Ich häng das Programm mal an. Es entspricht zwar nicht den von Bolle
genannten Kriterien, aber vielleicht hlft es dir trotzdem.
...
Guten Morgen Hannes,
danke dafür. Werde ich mir aber aus Vernunftgründen erst bei Tageslicht
ansehen..
Ich habe jetzt meinen Einzeiler mal verwendet, in einer an Bolles
angelehnten Programmstruktur. Also TimerInt setzt Flag.Bit, Main()
klappert die Schrittmotorfunktion ab, wo je nach Flag.Bit dann der Port
umgeschaltet wird.
Aus dem, was Du in 4 (?) Befehlen schaffst, macht der Compiler das
Folgende:
1
PORTD=(PORTD&~step_mask)|step[currentstep];
2
84:80916400ldsr24,0x0064
3
88:8095comr24
4
8a:92b3inr25,0x12;18
5
8c:9823andr25,r24
6
8e:20916600ldsr18,0x0066
7
92:e22fmovr30,r18
8
94:ff27eorr31,r31
9
96:e05asubir30,0xA0;160
10
98:ff4fsbcir31,0xFF;255
11
9a:8081ldr24,Z
12
9c:982borr25,r24
13
9e:92bbout0x12,r25;18
Man kommt um Assembler also nicht drumherum.
Versuch ich jetzt aber nicht mehr zu verstehen..
Erfreulicherweise läuft der Motor sogar, wenn auch nicht so rund wie
bei meiner ersten Softwarelösung mit delay()s. Auch dafür gibt es einen
Grund, aber auch der geht jetzt erstmal schlafen..
Gute Nacht!
Hochsprachen bringen eigentlich erst etwas, wenn man ASM begriffen hat.
Wer Hochsprachen nutzt um sich vor dem Erlernen von ASM zu drücken, der
hat schlechte Karten...
...
humm, ein kleines Gedankenexperiment
Was ist, wenn man das Bitmuster des oberen Nibble einfach im unteren
Nibble wiederholt? Dann kann man die einfach nach rechts durchrotieren,
oder hab ich da was nicht bedacht?
Also aus
0b10000000,0b11000000
machen wir
0b10001000 und 0b11001100
durch das Rotieren (ohne Carry!) kommt automatisch das untere,
gleichlautende Nibble wieder in das oberste rein und man erspart sich
eventuell die Tabelle, wie auch das Laden der Tabelle.
Richtig...
Aber wie wird das, wenn z.B. aus Gründen des Layouts die
Spulenanschlüsse nicht in der richtigen Reihenfolge sind oder garnicht
innerhalb eines Nibbles?
Bitschieben ist auf jeden Fall schneller. Aber Tabelle ist flexibler,
lässt sich jederzeit anpassen.
...