Simple program to test a steppermotor. Min/maxspeed, accelleration, distance and steps/m can be changed while the program is running for quick adjustment.

Dependencies:   mbed-rtos mbed

Fork of cmsis_rtos_queue by mbed official

Files at this revision

API Documentation at this revision

Comitter:
tuxic
Date:
Tue Jun 17 13:02:17 2014 +0000
Parent:
5:63fe92075b71
Commit message:
working version with minimal documentation

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
diff -r 63fe92075b71 -r cfbef7079a6f main.cpp
--- a/main.cpp	Mon Jun 16 05:25:02 2014 +0000
+++ b/main.cpp	Tue Jun 17 13:02:17 2014 +0000
@@ -1,16 +1,21 @@
 #include "mbed.h"
-#include "cmsis_os.h"
+#include <math.h>
+#include "cmsis_os.h" // https://mbed.org/handbook/CMSIS-RTOS
+// http://mbed.org/users/AjK/notebook/regarding-interrupts-use-and-blocking/
 
 DigitalOut StepLED(LED1);
 DigitalOut CmdLED(LED2);
 DigitalOut DirLED(LED3);
+DigitalOut TestLED(LED4);
+DigitalOut xDir(p22);
+DigitalOut xStep(p24);
+DigitalIn xHome(p8);
 
 typedef struct {
-    int steps;  // number of steps to take
-    int speed;  // speed in steps/sec
-    int accel;  // accelleration in steps/sec^2
-    int maxspeed; // maximum speed in steps/sec
-    int minspeed; // minimum speed in steps/sec
+    float steps;  // number of steps to take
+    float accel;  // accelleration in steps/sec^2
+    float maxspeed; // maximum speed in steps/sec
+    float minspeed; // minimum speed in steps/sec
     bool dir;    // direction
 } stepcmd;
 
@@ -19,56 +24,246 @@
 
 osMessageQDef(queue, 16, stepcmd);
 osMessageQId  queue;
-int qcnt = 0;
-Timeout timer;
+unsigned int qcnt = 0;
+Timeout timer,steptimer;
+Timer counter;
+
+void decelmove();
+void accelmove();
+void flatmove();
+void stepper();
+void stepdown();
+
+const bool xStepHigh = 1;
+const float pulseTime = 5; // pulse time in microseconds
+bool N_ESTOP = 1;
+float asteps, lsteps, dsteps, speed, accel, maxspeed, minspeed, ttime, dtime, wtime , etime, rtime, tsteps;
+char output[256];
+
+Serial pc(USBTX, USBRX); // tx, rx
+
+void stepdown()
+{
+    xStep = !xStepHigh;
+    tsteps++;
+}
 
-void read_isr()
+void decelmove()
+{
+    if (N_ESTOP && (dsteps-- > 0)) {
+        wtime = 1000000 / (speed - accel * (dtime/1000000));
+        timer.attach_us(decelmove, wtime);
+        xStep = xStepHigh;
+        steptimer.attach_us(stepdown, pulseTime);
+        dtime += wtime;
+    } else {
+        ttime += dtime;
+        etime = ttime;
+        counter.stop();
+        rtime = counter.read_us();
+        timer.attach_us(stepper, wtime);
+    }
+}
+
+void flatmove()
+{
+    if (N_ESTOP && (lsteps-- > 0)) {
+        timer.attach_us(flatmove, wtime);
+        xStep = xStepHigh;
+        steptimer.attach_us(stepdown, pulseTime);
+        ttime += wtime;
+        dtime = 0;
+    } else {
+        // ttime was only accelleration, not flatmove!
+        // after calculating wtime, set to 0 for use in decelmove
+        speed = 1000000.0 / wtime;
+        timer.attach_us(decelmove, wtime);
+    }
+}
+
+void accelmove()
 {
-        StepLED = !StepLED;
-        osEvent evt = osMessageGet(queue, 0);
-        if (evt.status == osEventMessage) {
-            stepcmd *cmd = (stepcmd*)evt.value.p;
-            DirLED = cmd->dir;
-            osPoolFree(cmdpool, cmd);
-            qcnt--;
-        } 
-        timer.attach(read_isr, 2);
+    TestLED = 1;
+    if (N_ESTOP && (asteps-- > 0)) {
+        wtime = 1000000 / (speed + accel * (ttime/1000000));
+        if (wtime < pulseTime) wtime = pulseTime;
+        timer.attach_us(accelmove, wtime);
+        xStep = xStepHigh;
+        steptimer.attach_us(stepdown, pulseTime);
+        ttime += wtime;
+
+
+    } else {
+        timer.attach_us(flatmove, wtime);
+    }
+}
+
+void stepper()
+{
+    osEvent evt = osMessageGet(queue, 0);
+    if (evt.status == osEventMessage) {
+        stepcmd *cmd = (stepcmd*)evt.value.p;
+        xDir = DirLED = cmd->dir;
+        accel = cmd->accel;
+        speed = cmd->minspeed;
+        lsteps = cmd->steps;
+        ttime = 0;
+        tsteps = 0;
+        wtime = 1000000 / speed;
+        float atime = 0;
+        if (accel == 0) { // linear move
+            asteps = dsteps = 0;
+        } else {
+            // calculate time to reach max speed:
+            // speed = startspeed + accel * time;
+            atime = (cmd->maxspeed - cmd->minspeed) / cmd->accel;
+            asteps = speed * atime + 0.5 * accel * pow(atime,2);
+            if ((lsteps /2) > asteps) {
+                // Accellerate to max speed, then flat, then decellerate
+                dsteps = asteps;
+                lsteps -= 2 * asteps;
+            } else {
+                // Accellerate to half of the space, then decellerate
+                asteps = lsteps/ 2;
+                dsteps = lsteps-asteps;
+                lsteps = 0;
+            }
+        }
+        sprintf(output, "atime: %2.6f steps: %f, %f, %f wtime: %f\n\r", atime, asteps, lsteps, dsteps, wtime);
+        counter.reset();
+        counter.start();
+        timer.attach_us(accelmove, wtime);
+        osPoolFree(cmdpool, cmd);
+        qcnt--;
+    } else {
+        timer.attach(stepper, 2);
+    }
+}
+void home(float speed)
+{
+    int wtime = int(1000000.0/speed);
+    xDir = 1;
+    while (! xHome) {
+        xStep = 1;
+        wait_us(5);
+        xStep = 0;
+        wait_us(wtime);
+    }
+    xDir = 0;
+    for (int x=0; x<1000; x++) {
+        xStep = 1;
+        wait_us(5);
+        xStep = 0;
+        wait_us(wtime);
+    }
 }
 
 int main (void)
 {
+    printf("Keys:\n\r");
+    printf("0-1: Adjust minimum speed (m/s)\n\r");
+    printf("3-4: Adjust maximum speed (m/s)\n\r");
+    printf("5-6: Adjust Accelleration (m/s^2)\n\r");
+    printf("7-8: Adjust total distance (m)\n\r");
+    printf("9-0: Steps per meter\n\r");
+    printf("h = home, p = print result, q = E_STOP, t=toggle direction\n\r");
+    printf("SPACE = move\n\r");
+    printf("CTRL-Break = reset\n\r\n\r");
+    TestLED = 0;
     cmdpool = osPoolCreate(osPool(cmdpool));
     queue = osMessageCreate(osMessageQ(queue), NULL);
-
-    timer.attach(read_isr, 2);
-    bool mydir = true;
-
+    timer.attach(stepper, 2);
+    bool mydir = false;
+    etime = 0;
+    // 902.51 met kleine motor: 0.25/0.8/1.1/80000 = 12.5 micron
+    float startspeed = 0.25;  // speed in m/s
+    float maxspeed = 0.8; // speed in m/s
+    float accel = 1.1; // accelleration in m/s^2
+    float distance = 1.26; // maximum distance on the rod in m
+    float steps = 80000; // steps per meter
+    float precision = 1000000 / steps;
+    pc.printf("Settings: min: %3.2f, max %3.2f, accel %3.2f, dist %3.2f, steps %ld\n\r",
+              startspeed, maxspeed, accel, distance, steps);
     while (true) {
-        const float startspeed = 0.05;  // speed in m/s
-        const float maxspeed = 2; // speed in m/s
-        const float accel = 2; // accelleration in m/s^2
-        const float distance = 1.26; // maximum distance on the rod in m
-        const int steps = 36000; // steps per meter
-        if (qcnt < 15) {
-            stepcmd *cmd = (stepcmd*)osPoolAlloc(cmdpool);
-            cmd -> minspeed = int(startspeed * steps);
-            cmd -> maxspeed = int(maxspeed * steps);
-            cmd -> accel = int(accel * steps);
-            cmd -> steps = int(distance * steps);
-            cmd -> speed = cmd -> minspeed;
-            cmd -> dir = mydir;
-            mydir = !mydir;
+        if (pc.readable()) {
+            char c = pc.getc();
+            switch (c) {
+                case 'h':
+                    home(startspeed * steps);
+                    break;
+                case '1':
+                    if (startspeed > 0) startspeed -= 0.01;
+                    break;
+                case '2':
+                    startspeed += 0.01;
+                    break;
+                case '3':
+                    if (maxspeed > startspeed) maxspeed -=0.01;
+                    break;
+                case '4':
+                    maxspeed += 0.01;
+                    break;
+                case '5':
+                    if (accel > 0) accel -= 0.01;
+                    break;
+                case '6':
+                    accel += 0.01;
+                    break;
+                case '7':
+                    if (distance > 0) distance -= 0.01;
+                    break;
+                case '8':
+                    distance += 0.01;
+                    break;
+                case '9':
+                    if (steps > 0) steps -= 100;
+                    break;
+                case '0':
+                    steps += 100;
+                    break;
+                case 't':
+                    mydir = !mydir;
+                    break;
+                case 'p':
+                    pc.printf("Etime: %2.3f, Rtime: %2.3f a,l,d,steps: %f,%f,%f,%f\n\r", (float)(etime/1000000.0), rtime/1000000, asteps, lsteps, dsteps, tsteps);
+                    break;
+                case 'q':
+                    N_ESTOP = ! N_ESTOP;
+                    break;
+                case ' ':
+                    if (qcnt < 15) {
+                        stepcmd *cmd = (stepcmd*)osPoolAlloc(cmdpool);
+                        cmd -> minspeed = startspeed *steps;
+                        cmd -> maxspeed = maxspeed * steps;
+                        cmd -> accel = accel * steps;
+                        cmd -> steps = distance * steps;
 
-            osStatus res = osMessagePut(queue, (uint32_t)cmd, 0);
-            while (res != osOK) {
-                osDelay(500);
-                res = osMessagePut(queue, (uint32_t)cmd, 0);
+                        pc.printf("Stepsettings: min: %f, max %f, accel %f, distance: %f\n\r",
+                                  cmd->minspeed, cmd->maxspeed, cmd->accel, cmd->steps, precision);
+                        cmd -> dir = mydir;
+                        osStatus res = osMessagePut(queue, (uint32_t)cmd, 0);
+                        while (res != osOK) {
+                            osDelay(500);
+                            res = osMessagePut(queue, (uint32_t)cmd, 0);
+                        }
+                        pc.printf("Command sent\n\r", ++qcnt);
+                        mydir = !mydir;
+                        osDelay(100);
+                    } else {
+                        // pc.printf("Storage full\n\r");
+                    }
+                    break;
             }
-            printf("Storage succeeded %d\n\r", ++qcnt);
+            precision = 1000000 / steps;
+            pc.printf("Settings: min: %3.2f, max %3.2f, accel %3.2f, dist %3.2f, steps %7.0f DIR: %d, precision: %2.3f\n\r",
+                      startspeed, maxspeed, accel, distance, steps, mydir, precision);
         } else {
-            printf("Storage full\n\r");
+            osDelay(2000);
         }
-        osDelay(1000);
         CmdLED = ! CmdLED;
+        if (strlen(output)>0) {
+            pc.printf("%s\n\r", output);
+            sprintf(output, "");
+        }
     }
-}
+}
\ No newline at end of file