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:
- 0:59fcbfc00e50
- Child:
- 1:8134c43fdb08
File content as of revision 0:59fcbfc00e50:
#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,27);
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();
}
}
