Vi har tidigare skrivit en enkel motorstyring med PWM (lektion 8) och denna lektion bygger vidare på det enkla exemplet fast vi skall ändra PWM från den interna 500Hz som analogWrite() använder sig av. Just 500Hz funkar bra för att dimma lysdioder och köra enkla motorer, men för att en DC motor skall fungera bättre krävs högre frekvens och det är ganska lätt att ändra detta i utvecklingsmiljön. I detta exempel skall vi justera upp PWM till 20KHz och styra 2st DC motorer både medurs (fram) och moturs (bakåt) för att t.ex. styra en liten robot.
För att varvtalsreglera DC motorer ändrar man inte spänningen, utan man använder sig av PWM (Puls Width Modulation), dvs. pulsbreddsmodulering och DC motorer kräver mycket mer ström än vad en I/O klarar av på en microkontroller (i detta fallet en ATMega328P) så vi måste använda oss av en motordrivkrets (finns enkla H-bryggor eller kretsar avsedda för att driva motorer). I detta fallet skall vi använda oss av en motordrivkrets från Texas Instrument som heter DRV8835, databladet finns här och för att göra det enkelt för oss skall vi använda en färdig produkt som lämpar sig mycket bra till Arduino, det är ett litet kort som fungerar som ett Shield, fast inte i full storlek, detta för att hålla nere kostnaderna. Motordrivkortet vi använder är POL-2511 och klarar att köra 2 motorer oberoende av varandra från 1.5V-11V och max 1.2A kontinuerligt per motor (peak 1.5A).
Motorn vi använder oss av är denna enkla billiga motor med inbyggd växellåda. Hjulen finns i olika utföranden men de vi använder oss av är dessa och kan snäppas på motoraxeln direkt. Vi har lött på en brun och en röd ledare på motorerna och båda motorer har samma konfiguration, så de snurrar på samma håll vid samma signal. Skall motorerna monteras mot varandra på t.ex. en robot så betyder det att roboten kommer snurra runt på samma ställe och inte gå fram eller tillbaka. Men det är enkelt att fixa det i koden i stället.
För att ändra frekvensen så modifieras 2 register i Timer 1 (TCCR1A samt TCCR1B). Detta görs i setup() som visas nedan, för mer information om hur Timer 1 fungerar se databladet för ATmega328p.
void setup() { // // Set up PWM to use 20Khz and 16Mhz, instead of standard 500Hz // 16Mhz / 1 / 2 / 400 = 20KHz // TCCR1A = 0xA0; TCCR1B = 0x11; ICR1 = 400;
Nu kan båda motorer styras med PWM i 20KHz genom att ändra OCR1A och OCR1B mellan 0 till 400 där 0 är helt avstängt och 400 är helt påslagen, 200 innebär då en PWM med 50% “Duty Cycle”, dvs. 50% på och 50% av. För att göra det lätt för oss finns det 2 funktioner som styr de olika motorerna, de heter setMotorRight(int Speed) och setMotorLeft(int Speed). De tar en parameter som är från -400 (max moturs/bakåt) till +400 (max medurs/framåt). Sätter man den till 0, så är den avstängd. Värdena kontrolleras att de är inom gränserna för säkerhetens skull samt en utgång sätts till 0 eller 1 beroende på om det är framåt (medurs) eller bakåt (moturs). När vi kör med PWM på detta viset så sköts detta helt i bakgrunden så när man satt en hastighet så går motorn med den hastigheten tills den ändras oavsett vad man gör för andra saker i koden.
Koden för detta projekt kan laddas ner här.