Start Elkretssimulator


Stegmotor

Vi får en stegmotor snurra med arduino.

Lite stegmotorteori

Först lite stegmotorteori. För att begripa teorin måste du ha ett hum om hur en dcmotor fungerar och hur en elektromagnet fungerar.

Allmänt

En stegmotor består enkelt uttryckt av en snurrande magnet. Runt om sitter elektromagneter vilka magnetiseras enligt ett mönster som driver runt axeln med magneten.
(Det kan såklart vara tvärtom också; dvs elektromagneterna sitter i mitten med en snurrande magnet runtomkring. Det är ofta så en bortslös motor brukar byggas. Skillnaden mellan en stegmotor och en borstlös motor är sublim)

Det finns olika komplicerade stegmotorer med olika många elektromagneter. Ju fler lindningar desto fler faser och desto jämnare och kontrollerad rörelse. Ju färre lindningar desto färre faser och "hackigare" rörelse - men billigare stegmotor. Det går också med styrelektroniken påverka antalet steg, med fullsteg, halvsteg eller mikrosteg (se nedan). Man skiljer också på 1-fas och 2-fas -drivning av stegmotorn. 2-fas ger ett starkare vridmoment. Mer om detta längre ner.

Olika varianter av stegmotorer

Man skiljer bl.a. mellan unipolär och bipolär. Stegmotorns anslutningar benämns A+ och A- respektive B+ och B-. Sedan kan det finnas 1 gemensam eller 2 gemensamma anslutningar som jag här döpt till ABcom eller Acom och Bcom.



Färger på anslutningar till stegmotor

Nedan några exempel på färgerpå anslutningar. Det kan i princip se ut hur som helst. Titta i dokumenteringen på den stegmotor du köpt. Det viktiga är att sortera upp dem i A+, A- och B+ och B- samt vilka som är gemensamma om det är 5 eller 6 ansluntingar.

Typ Ex. A+ Acom A- B+ Bcom B-
Bi 4 Nema xx Svart Grön Röd Blå
Bi 4 Orange Blå Röd Gul
Uni 5 BYJ48 Rosa Röd Orange Gul Röd Blå
Uni 6 Nema xx Svart Gul Grön Röd Vit Blå

Stegmotorns elektromagneter

Elektromagneterna jobbar oftast både attraherande (attraktiv = drar till sig) och repellerande (stöter ifrån). För att åstadkomma detta kan man antingen vända på polariteten (bipolär stegmotor) på en lindning eller så kan man när man bygger motorn lägga in dubbla lindningar, där den ena lindningen lindas medurs och den andra moturs (unipolär stegmotor). Beroende på vilken av dessa som strömsätts i den unipolära elektromagneten så får man sedan attraherande eller repellerande kraft. Skillnaden som uppstår blir alltså - mellan unipolär och bipolär - att när man driver unipolära behöver man aldrig vända på polariteten för en elektromagnet och drivelektroniken blir därför enklare. Med bipolär blir istället stegmotorn enklare men drivelektroniken mer komplicerad. En unipolär stegmotor kan kopplas så att den beter sig som en bipolär. Se bilden.

Viktiga begrepp

Bipolär
Förutsätter drivelektronik som vänder på lindningarnas polartitet.
Unipolär
Drivelektroniken behöver bara strömsätta aktuell lindning. Gemensam GND eller plus.

Exempel på fullsteg

En elektromagnet åt gången magnetiseras.



Exempel på halvsteg

Genom att varannat steg elektrifiera 2 elektromagneter skapas ett mellanläge, vilket ger dubbelt så många steg.



Mikrosteg

Mikrosteg är en teknik där man stegvis flyttar magnetiseringen mellan två lindningar. På så vis åstadkommer man ett antal virtuella steg mellan två magneter. Mikrosteg kräver därför en ganska avancerad drivelektronik.

Exempel på fullsteg med 2 faser

Genom att magnetisera 2 magneter åt gången får vi samma upplösning som ett vanligt fullsteg, men starkare vridmoment. Det är intutivt på något sätt eftersom 2 aktiva magneter bör vara starkare tillsammans än 1 magnet, eller hur?



Bipolär med 4 anslutningar

Vi måste här vända på polariteten för att driva runt stegmotorn. Stegmotorn är enklare konstruera men drivelektroniken lite mer komplicerat.



Unipolär med 5 anslutningar

Nu behöver vi inte vända på polariteten längre. Vi behöver bara flytta drivningen (-) till de lindningar vi vill magnetisera. Drivelektroniken blir enklare men stegmotorn blir mer komplicerad.



Stegsekvensen

Arbetet att driva runt stegmotorn handlar alltså om att aktivera elektromagneterna i stegmotorn enligt ett mönster som driver runt axeln. Denna aktivering kan göras på flera olika sätt.

Jag har en stegmotor här (en 5-trådars unipolär stegmotor BYJ48) som enligt dokumenteringen kan drivas runt med hjälp av nedanstående sekvens. Detta kallas fullsteg.

Fullsteg



I detta fall skall man upprepande mata ut mönstret 1000, 0100, 0010, 0001, ... (eller i omvänd ordning beroende på riktning) med lämplig hastighet på de digitala portar som matchar stegmotorns 4 lindningar.

Det finns som sagt något som heter halvsteg (beskrivet ovan) och det innebär att man lägger in ett steg mitt-i-mellan två elektromagneter i motorn genom att magnetisera båda elektromagneterna samtidigt.

Halvsteg


Vilket också kan visualiseras såhär:


Vi ska alltså upprepande mata ut mönstret 1000, 1100, 0100, 0110, 0010, 0011, 0001, 1001, ... (eller i omvänd ordning beroende på riktning) med lämplig hastighet på de digitala portar som matchar stegmotorns 4 lindningar.

Halvsteg ger en jämnare gång på stegmotorn men till priset att vridmomentet blir lägre. Det finns fler sätt att köra en stegmotor som ger andra egenskaper men jag hoppar över det här och nu, t.ex. mikrosteg eller fullsteg med 2 faser aktiva.

Vilken riktning stegmotorn snurrar beror helt på i vilken ordning dessa sekvenser matas ut till stegmotorn.

Driva stegmotorn

Strömmen på utgångarna på en mikrokontroller räcker inte för att driva en stegmotor så det behövs någon form av effektsteg här. Typiskt är det någon krets t.ex. ULN2803 eller ULN2003 som ligger mellan mikrokontrollern och stegmotorn enligt nedan.





Men det går även att konstruera detta effektsteg med t.ex. BC547 transistorer t.ex. enligt nedan.


När man tittar på ovanstående schema och även det med ULN2803, så kan man få intrycket att signalen inverteras och att man därför måste skicka in en inverterad signal för att det skall bli "rätt". Att signalen inverteras stämmer, men det blir rätt ändå. Lindningarnas gemensamma anslutning på stegmotorn går till 5 eller 12 volt, så det är just när lindningens andra anslutning "nollas" (sänks) som den blir aktiv (flyter en ström). Så en hög signal in betyder fortfarande att elektromageten i stegmotorn är aktiv och vice versa.

Programmet - med riktning och fartreglering

Uppkoppling

Först kanske ska sägas att eftersom stegmotorn 28BYJ48 har en växellåda så snurrar axeln ut ganska långsamt. Detta är därför kanske inte den mest visuella stegmotorn för att se vad som händer. Men strunt i den detaljen nu! (Men det är bra att veta att det existerar en växellåda annars kanske du undrar varför det går så långsamt)

Koden nedan bör fungera för vilken stegmotor som helst som är unipolär med 4 magneter (5 trådar).

Nedan kod kan ställas in så att den antingen kör fullsteg (FULLSTEP) eller halvsteg (HALFSTEP). De digitala utgångarna 8-9-10-11 kopplas till IN1-IN2-IN3-IN4. För att reglera hastigheten kopplas en potentiometers mittenutgång till pinne 1 och de andra pinnarna på potentiometern till GND resp. 5V (det blir en spänningsdelare som kan regleras från 0-5V).



Om ovan bild och text är lite otydlig, här kommer en bild till.


28BYJ48

Observera att stegmotorn använd här ser ut som nedan. Vi avfyrar sedan elektromagneterna i denna enligt följande för fullsteg; 1000, 0100, 0010, 0001 där lindningarna är BRGO (Blå-Rosa-Gul-Orange) och 1000, 1100, 0100, 0110, 0010, 0011, 0001, 1001 för halvsteg.



Användning

Funktionen är sådan att när potentiometern står i mitten så står stegmotorn stilla. Vrider man åt ena eller andra hållet snurrar stegmotorn medurs eller moturs och hastigheten beror på hur mycket man vrider åt ena eller andra håller.

Funktion

En timer-interrupt sätts med en väntetid som beror på vad potentiometer står på. Beroende på om potentiometern befinner sig på vänster eller höger halva (dvs utsignalen blir mer eller mindre än 512 (alltså halva 1024 som är full signal på analog ingång)) så sätts även rotate till +1 eller -1.

För varje steg (interrupt-avbrott) räknas fasen upp eller ner och börjar om i andre änden. Dvs 0-1-2-3-0-1-2-3-0-1-2 osv. eller vice versa och vi skriver sedan ut värdet på stegmotorns lindningar enligt tabellerna halfStep eller fullStep beroende på vad som är önskvärt.

Vi ändrar enbart interruptet om vi har vridit lite på potentiometern, därför sparar jag lastPotValue (senaste värdet). Värdet från A/D -omvandlaren rör sig alltid lite så därför jämför jag med en viss tröskel (3).

#define HALFSTEP 1
#define FULLSTEP 2

int stepMode = HALFSTEP;

int POT = 1;    // Potentiometer (fart)
int IN1 = 8;    // Blå - 28BYJ48 pin 1
int IN2 = 9;    // Rosa - 28BYJ48 pin 2
int IN3 = 10;   // Gul - 28BYJ48 pin 3
int IN4 = 11;   // Orange - 28BYJ48 pin 4

int halfStep[8] = {
	B01000, 
	B01100, 
	B00100, 
	B00110, 
	B00010, 
	B00011, 
	B00001, 
	B01001};

int fullStep[4] = {
	B01000, 
	B00100, 
	B00010, 
	B00001};

int phase = 0;
int rotate = 1;
int potValue;
int lastPotValue;

void setup() 
{
  Serial.begin(9600); 
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  
  potValue = analogRead(POT);
  setupInterrupt(potValue);
}

void setupInterrupt(int potValue)
{
  cli();
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;
  OCR1A =  16000 - abs(potValue-512)*30; 
  TCCR1B |= (1 << WGM12);
  TCCR1B |= (1 << CS12) | (1 << CS10); // 1024 prescaler
  TIMSK1 |= (1 << OCIE1A);
  sei();      
}

ISR(TIMER1_COMPA_vect)
{
  setOutput(phase);
  phase += rotate;

  if(stepMode == HALFSTEP)
  {
    phase%=8;
    if(phase<0)
    phase = 7;
  }
  if(stepMode == FULLSTEP)
  {
    phase%=4;
    if(phase<0)
    phase = 3;
  }

  potValue = analogRead(POT);
  if(abs(potValue - lastPotValue) > 3)
  {
    Serial.println(potValue);    
    if(potValue>512)
      rotate = 1;
    else
      rotate = -1;
    lastPotValue = potValue;    
    setupInterrupt(potValue);
  }  
}

void setOutput(int out)
{
  if(stepMode == HALFSTEP)
  {
    digitalWrite(IN1, bitRead(halfStep[out], 0));
    digitalWrite(IN2, bitRead(halfStep[out], 1));
    digitalWrite(IN3, bitRead(halfStep[out], 2));
    digitalWrite(IN4, bitRead(halfStep[out], 3));
  }
  if(stepMode == FULLSTEP)
  {
    digitalWrite(IN1, bitRead(fullStep[out], 0));
    digitalWrite(IN2, bitRead(fullStep[out], 1));
    digitalWrite(IN3, bitRead(fullStep[out], 2));
    digitalWrite(IN4, bitRead(fullStep[out], 3));
  }  
}

void loop()
{

}