Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed mbed-rtos Linear_Stepper_Motor_Nema17
Fork of Sliding_Camera_Rail by
main.cpp
- Committer:
- mikermarza
- Date:
- 2020-04-28
- Revision:
- 1:8134c43fdb08
- Parent:
- 0:59fcbfc00e50
- Child:
- 2:7facfc9e53ff
File content as of revision 1:8134c43fdb08:
/* Written by Michael Marzano ECE 4180 Final Project Sliding Camera Rail Souce code for the camera rail */ #include "mbed.h" #include "rtos.h" #include "lin_step_mtr.h" /********** * Defines * **********/ #define ABSOLUTE_MIN 0 // minimum rev for software stop #define ABSOLUTE_MAX 49.5 // maximum rev for software stop #define MAX_SPEED 400 // maximum speed in RPM #define MIN_SPEED 200 // minimum speed in RPM // range over all possible speeds, used in calculating the rotation input to // LinStepMtr::rotate() for smooth operation #define SPEED_RNG MAX_SPEED - MIN_SPEED /*********** * Hardware * ***********/ LinStepMtr mtr(p19, p20, p17, p18); // for linear motor, coresponds t0 A,A',B,B' BusOut lights (LED4,LED3,LED2,LED1); Serial xbee(p28,p27); //Serial xbee(USBTX,USBRX); /******** * Enums * ********/ typedef enum { OFF = 0b0000, ALL = 0b1111, L2 = 0b1100, R2 = 0b0011, AH1 = 0b1010, AH2 = 0b0101 } LightPattern; typedef enum { STOP = 0, MV_L, MV_R, } RailState; typedef enum { NORMAL = 0, LOCK_N, // LOCK for normal mode CALIBRATE, GO_HOME, RESET, OVERRIDE } RailMode; typedef enum { GOOD = 0, START, HOME, AWAY } CalibrateStatus; /*********************** * Flag/State Variables * ***********************/ volatile RailState rail_state; // the state of rail movement volatile RailMode rail_mode; // rail mode, described in RailMode enum volatile CalibrateStatus cal_stat; // status of calibration volatile double home; // rev count for rail's "home", initialized to ABSOLUTE_MIN volatile double away; // rev count for rail's farthest movement point initialized to ABSOLUTE_MAX; volatile char speed; // current speed setting from inputs volatile float rot; // number of revolutions to rotate based on speed volatile bool going_home; // flag for if rail is headed back to "home" volatile bool home_set; // flag for if home has been set volatile bool away_set; // flag for if away has been set volatile bool cal_done; // flag for if calibration is complete volatile bool toggle; /*************************** * General Static Functions * ***************************/ static inline void send_ack() { xbee.printf("!A"); } /******************* * Thread Functions * *******************/ // reads the input from the serial com port void read_input(void const *arg) { char input; while(1) { if(!xbee.readable()){ Thread::yield(); } else { input = xbee.getc(); if (input != '!'){ Thread::yield(); }else { while(!xbee.readable()) Thread::yield(); input = xbee.getc(); switch(input){ case '0': // no movement rail_state = STOP; while(!xbee.readable()) Thread::yield(); input = xbee.getc(); break; case '1': case '2': case '3': case '4': case '5': // handle speed if(speed != input) { speed = input; rot = ((float)input - 49) * .0125 + .2; mtr.set_speed(((float) input - 49)*50 + 200); } while(!xbee.readable()) Thread::yield(); input = xbee.getc(); xbee.printf("DIR: %c\n",input); switch(input){ case 'L': // move left rail_state = MV_L; break; case 'R': // move right rail_state = MV_R; break; default: break; } break; case 'S': // stop movement rail_state = STOP; break; case 'F': // Lock or Unlock rail switch(rail_mode) { case NORMAL: rail_mode = LOCK_N; break; case LOCK_N: rail_mode = NORMAL; rail_state = STOP; break; default: break; // do nothing } break; case 'C': switch(rail_mode){ case NORMAL: case LOCK_N: case CALIBRATE: switch(cal_stat){ case GOOD: rail_state = STOP; home_set = false; away_set = false; cal_done = false; cal_stat = START; rail_mode = CALIBRATE; Thread::wait(600); break; case START: case HOME: home = mtr.get_rev(); rail_state = STOP; home_set = true; send_ack(); cal_stat = AWAY; Thread::wait(600); break; case AWAY: away = mtr.get_rev(); rail_state = STOP; away_set = true; send_ack(); cal_stat = GOOD; Thread::wait(600); break; } break; default: break; } break; case 'H': // send rail to home switch(rail_mode){ case NORMAL: case LOCK_N: rail_state = STOP; going_home = true; rail_mode = GO_HOME; break; } break; default: break; // do nothing because invalid input } Thread::yield(); // hopefully makes this thread run a little faster } } } } // blinks leds a set number of times with a wait time of w static inline void blink_leds(int t, int w, LightPattern p) { for(int i=0; i < t; ++i){ lights = OFF; Thread::wait(w); lights = p; Thread::wait(w); } lights = OFF; Thread::wait(w); } // reads flag variables to control LED status lights void status_lights(void const *arg) { while(1) { switch(rail_mode){ case LOCK_N: lights = ALL; Thread::yield(); break; case CALIBRATE: //blink twice blink_leds(2,150,ALL); toggle = true; while(!home_set){ if(toggle) lights = L2; else lights = OFF; toggle = !toggle; Thread::wait(500); } blink_leds(2,150,L2); toggle = true; while(!away_set){ if(toggle) lights = R2; else lights = OFF; toggle = !toggle; Thread::wait(500); } blink_leds(2,150,R2); Thread::wait(500); while(!cal_done); blink_leds(2,150,ALL); break; case GO_HOME: // blink thrice blink_leds(3,150,ALL); toggle = true; while(going_home){ if(toggle) lights = ALL; else lights = OFF; toggle = !toggle; Thread::wait(600); } // blink thrice for complete blink_leds(3,150,ALL); break; case NORMAL: // no lights for normal opperation default: lights = OFF; Thread::yield(); break; } } } /**************** * Main Function * ****************/ int main() { // Variables double cur_loc; // current location in revolutions. used for GO_HOME //set defaults for global variables rail_state = STOP; rail_mode = NORMAL; cal_stat = GOOD; home = ABSOLUTE_MIN; away = ABSOLUTE_MAX; speed = '5'; rot = .25; going_home = false; home_set = true; away_set = true; cal_done = true; toggle = true; // Start Threads Thread input(read_input); Thread lights(status_lights); wait(.001);; // set up motor mtr.set_min_rev_cnt(home); mtr.set_max_rev_cnt(away); while(1) { switch(rail_mode) { case NORMAL: switch(rail_state) { case MV_L: mtr.rotate(LinStepMtr::CW,rot); break; case MV_R: mtr.rotate(LinStepMtr::CCW,rot); break; case STOP: default: break; } break; case LOCK_N: // do nothing break; case CALIBRATE: switch(cal_stat) { case START: // reset stats mtr.RESET_rev_cnts(); cal_stat = HOME; break; case GOOD: // save software bounds to rotation library if(away < home) { //away is right of home mtr.set_min_rev_cnt(away); mtr.set_max_rev_cnt(home); } else { // away is left of home mtr.set_min_rev_cnt(home); mtr.set_max_rev_cnt(away); } cal_done = true; send_ack(); rail_mode = NORMAL; break; default: break; } switch(rail_state) { case MV_L: mtr.rotate(LinStepMtr::CW,rot); break; case MV_R: mtr.rotate(LinStepMtr::CCW,rot); break; case STOP: default: break; } break; case GO_HOME: Thread::wait(1000); // get currecnt location cur_loc = mtr.get_rev(); mtr.set_speed(MAX_SPEED); speed = '0'; if(home < cur_loc) { // home is right of current location mtr.rotate(LinStepMtr::CCW,cur_loc - home); } else { // home is to the left of current location mtr.rotate(LinStepMtr::CW, home - cur_loc); } going_home = false; rail_state = STOP; rail_mode = NORMAL; send_ack(); Thread::wait(500); break; default: break; } Thread::yield(); } }