/* OZ1HJR Program til styring af Mercury Motor SM-42BYG011-25 (ROB-09238) med EasyDriver V4.4 (ROB-10267). Når MS1 og MS2 begge er High, er et step (1.8 grader) opløst i 8 mikrostep. Et mikrostep svarer således til 0,225 grader. 1600 mikrostep svarer 360 grader. Input: g sætter 'gå til vinkel' mode - vinklen behandles som en absolut vinkel d sætter 'drejemode' - den aktuelle vinkel adderes til den aktuelle f stepmode sættes til helstep (1/200 del af en omdrejning) h stepmode sættes til halvstep (1/400 del af en omdrejning) k stepmode sættes til kvartstep (1/800 del af en omdrejning) o stepmode sættes til ottendedelsstep (1/1600 del af en omdrejning) en talværdi (float) med fortegn angiver vinklen der kan benyttes både store og små bogstaver drejemode, stepmode og vinkel kan angives i samme linie De valgte størrelser fremgår af displayet (ved start: G og O) Forskellen mellem den ønskede vinkel og den nærmeste mulige gemmes og bruges til korrektion ved næste valg. Der sker altså ikke tab af nøjagtighed ved gentagne indstillinger. Det gælder også ved skift af stepmode. */ // inkluder library kode: #include <LiquidCrystal.h> #include <Serial.h> // Initialiser display LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // Arduino signaler til EasyDriver: #define DirPin 6 #define StepPin 7 #define MS1Pin 8 #define MS2Pin 9 // Konstanter til stepmotor (mikrosekunder) #define Delayf 1500 // delay for fuldstep stepmode = 8
#define Delayh 750 // delay for halvstep stepmode = 4 #define Delayk 375 // delay for kvartstep stepmode = 2 #define Delayo 185 // delay for ottendedelsstep stepmode = 1 int Delay = Delayo; // aktuelt delay, start i ottendedelsstep int s = 1; // aktuel stepmode, start i ottendedelsstep int drejemode = false; // ved false drejes til værdien i vinkel (d), ved true drejes værdien i vinkel (g) long int steps = 0; // aktuel position i ottendedels step uanset stepmode (betegnes mikrostep) float StepFejl = 0; // forskellen i ønsket og aktuel position målt i ottendedels step float vinkel = 0; // ønsket vinkel eller drejning i grader float vinkelold = 0; // aktuel vinkel i grader // opsætning void setup () { pinmode(dirpin, OUTPUT); // Opsætning af motorstyring pinmode(steppin,output); pinmode(ms1pin, OUTPUT); pinmode(ms2pin, OUTPUT); digitalwrite(ms1pin,high); // HIGH LOW HIGH LOW digitalwrite(ms2pin,high); // HIGH HIGH LOW LOW // ottendedelsstep kvartstep halvstep fuldstep // S: 1 2 4 8 lcd.begin(16,2); Serial.begin(9600); } // Opsætning af LCD: antal kolonner og rækker // Opsætning af seriel kommunikation 9600 bps // funktioner til programmet void mode(int m) { // her sættes stepopløsningen for motoren vinkel = vinkelold; // her skal vi slutte deltastep(); // gå til nærmeste helstepsposition i aktuel mode switch (m){ case 8: digitalwrite(ms1pin,low); digitalwrite(ms2pin,low); Delay = Delayf; break; case 4: digitalwrite(ms1pin,high); digitalwrite(ms2pin,low); Delay = Delayh; break;
case 2: digitalwrite(ms1pin,low); digitalwrite(ms2pin,high); Delay = Delayk; break; case 1: digitalwrite(ms1pin,high);digitalwrite(ms2pin,high); Delay = Delayo; break; default: break; } delaymicroseconds(200); // lille pause efter opsætning s = m; // gem mode rotate(vinkel-vinkelold); // gå til den gamle vinkel vinkelold=vinkel; if (drejemode==true) vinkel=0; } // gem aktuel vinkel // drejning udført // mode slut void rotate(float grader){ //drejer motoren grader regnet med fortegn float ms = (grader/360)*1600+stepfejl; // antal mikrostep med fortegn, korrigeret for stepfejl long int MS =(ms<0)?ms/s-0.5:ms/s+0.5;// antal aktuelle step med fortegn, korrekt afrundet StepFejl=ms-MS*s; // ny stepfejl i mikrostep steps = steps+ms*s; // opdatering af steptælleren // print til LCD: Vinkel, mikrostep, drejemode og stepmode lcd.setcursor(0,0); lcd.print("vinkel: "); lcd.setcursor(8,0); lcd.print(float(steps)*360/1600); lcd.setcursor(0,1); lcd.print("steps: "); lcd.setcursor(14,1); lcd.print((drejemode == true)? 'D':'G'); lcd.setcursor(15,1); lcd.print((s==1)?'o':(s==2)?'k':(s==4)?'h':'f'); stepper(ms); // kald af stepfunktionen lcd.setcursor(8,1); lcd.print(steps); } // ratate slut void deltastep() { long int dstep = steps%8; dstep = (dstep<4)? -dstep: 8-dstep; steps += dstep; vinkelold+=float(dstep)*360/1600; stepper(dstep/s); } // deltastep slut void stepper(long int st) { // denne funktion bringer stepmotoren i den nærmeste fuldstepposition // overskridelse af sidste fuldstepposition // nærmeste position // korrektion af steps // den nye vinkelposition // positionen korrigeres i mikrostep // denne funktion drejer stepmotoren
digitalwrite(dirpin,(st<0)? HIGH:LOW); // her bestemmes omløbsretning delaymicroseconds(200); // lille pause efter opsætning st = abs(st); for ( long int i=0; i<st; i++) { digitalwrite(steppin,high); delaymicroseconds(1); // længden af den høje puls digitalwrite(steppin,low); delaymicroseconds(delay); }} // delay afhænger af stepmode void loop () { // Indlæsning // d eller D sætter drejemode true: der drejes det indtastede antal grader regnet med fortegn. // g eller G sætter drejemode false: der drejes til det indtastede gradtal regnet med fortegn. // Rotationsretningen bestemmes af fortegnet int c; while (Serial.available()>0){ c = Serial.peek(); // læs første karakter, bufferen er uændret c=(c<96)?c:c-32; // små bogstaver ændres til store bogstaver switch (c) { case 'D': drejemode = true; vinkel = 0; break; // drejemode, bliv på position case 'G': drejemode = false;vinkel = vinkelold; break; // positionsmode case 'F': mode(8); break; // stepmode Fuld step case 'H': mode(4); break; // stepmode halvstep case 'K': mode(2); break; // stepmode fjerdedelsstep case 'O': mode(1); break; // stepmode ottendedelstep case 9: case 10: case 13: case 32:break; // fjern tab, nl, cr og sp case 43: case 45: case 48: case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: vinkel=serial.parsefloat();break; // læs ønsket vinkel eller drejning hvis tegnet er +, - eller 0-9 default: Serial.println("Fejl i input"); while (Serial.available()>0) c= Serial.read(); // ved fejl i input: tøm buffer break; }
c = Serial.read(); } // fjern det læste tegn fra buffer (bufferlængden nedskrives) if (drejemode==true) vinkel += vinkelold; // beregn den ønskede vinkel rotate(vinkel-vinkelold); // drej vinkeldifferencen vinkelold=vinkel; // opdater vinkelpositionen if (drejemode==true) vinkel=0; // drejning udført }