Forum: Mikrocontroller und Digitale Elektronik bitoperation im halbschlaf


von leif (Gast)


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!

von Hannes L. (hannes)


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.

...

von leif (Gast)


Lesenswert?

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.

von leif (Gast)


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 ?

von Hannes L. (hannes)


Angehängte Dateien:

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.

...

von leif (Gast)


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!

von Hannes L. (hannes)


Lesenswert?

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...

...

von leif (Gast)


Lesenswert?

was ich über die 4 befehle gesagt habe ist ja quatsch, das bitmuster
berechnest du ja vorher auch noch.

so jetz aber.

von Hannes L. (hannes)


Lesenswert?

Die berechne ich nicht, die stehen im Flash in einer Tabelle...

Gute N8...

...

von Mark S. (struberg)


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.

von Hannes L. (hannes)


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.

...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.