bitoperation im halbschlaf

Gast #227722
Lesenswert?

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!
#227723
Lesenswert?

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.

...
Gast #227725
Lesenswert?

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 ?
#227726
Lesenswert?

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.

...
Angehängte Dateien:
Gast #227727
Lesenswert?

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:  80 91 64 00   lds  r24, 0x0064
3
  88:  80 95         com  r24
4
  8a:  92 b3         in  r25, 0x12  ; 18
5
  8c:  98 23         and  r25, r24
6
  8e:  20 91 66 00   lds  r18, 0x0066
7
  92:  e2 2f         mov  r30, r18
8
  94:  ff 27         eor  r31, r31
9
  96:  e0 5a         subi  r30, 0xA0  ; 160
10
  98:  ff 4f         sbci  r31, 0xFF  ; 255
11
  9a:  80 81         ld  r24, Z
12
  9c:  98 2b         or  r25, r24
13
  9e:  92 bb         out  0x12, 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!
#227731
Lesenswert?

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.
#227732
Lesenswert?

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.

...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren