![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Dependencies: RPCInterface mbed
Revision 0:2dbd366be5fd, committed 2012-05-07
- Comitter:
- protodriveev
- Date:
- Mon May 07 16:14:45 2012 +0000
- Commit message:
Changed in this revision
diff -r 000000000000 -r 2dbd366be5fd RPCInterface.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RPCInterface.lib Mon May 07 16:14:45 2012 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/MichaelW/code/RPCInterface/#682c65afe534
diff -r 000000000000 -r 2dbd366be5fd main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon May 07 16:14:45 2012 +0000 @@ -0,0 +1,370 @@ +/****************************************************************************** +*********************** Protodrive *********************** +************* Andrew Botelho & William Price ************* +******************************************************************************/ + +#include "mbed.h" +#include "SerialRPCInterface.h" +#include "RPCVariable.h" + +/***********************************************************/ +/*Constants */ +/***********************************************************/ +#define MATLAB_INTERFACE //matlab used as an interface +//#define SERIAL_INTERFACE //Terminal used as an interface. Mainly for debugging + +#define CURRENT_SENSOR_ON //turn on current sensor +//#define DEBUG +//#define LIGHTS_CURRENT_CONTROL //power flow light control is determined by the current sensor +#define LIGHTS_LOAD_CONTROL //power flow light control is determined by the voltage demand placed on the motors + +/**********************Power sources options***************/ +/*Instruction: There are 3 power source options for the DUT +and two for the load. Uncomment the option that you want to +use and comment options that you do not want to use. The DUT +and load should each only have one option uncommented. +*/ + +//DUT +//1. External supply +//#define DUT_EXTERNAL_POWER_ENABLE + +//2. Just DUT batt enabled +#define DUT_BATT_ENABLE + +//3. DUT batt and cap enabled +//#define DUT_BATT_CAP_ENABLE + +//Load +//1. External Supply +//#define LOAD_EXTERNAL_POWER_ENABLE + +//2. Load batt enabled +#define LOAD_BATT_ENABLE + +/***********************************************************/ +/*Global Variables */ +/***********************************************************/ +float v_DUT_batt, v_load_batt, v_cap, speed, current; +int big_error,regen; +int foo = 1; + +//motor direction and load +float DUT_input = 0; //DUT duty cycle demand variable +float load_input = 0; //Load duty cycle demand variable +float DUT_input_direc = 1; //DUT direction variable. Default to forward +float load_input_direc = 0; //Load direction variable. Default to reverse. This means it will NOT oppose the DUT + +/***********************************************************/ +/*Pin Setup */ +/***********************************************************/ +//mbed LEDS +DigitalOut big_error_led(LED1); //error LED + +//Board LEDs +DigitalOut leftArrow(p29); //setting high turns on green left arrow LEDS +DigitalOut greenLine(p28); //setting high turns on green centerline LEDS +DigitalOut orangeLine(p27); //setting high turns on orange centerline LEDS +DigitalOut rightArrow(p26); //setting high turns on orange right arrow LEDS + +DigitalOut load_batt_green(p25); //setting high will turn on the load batt green LED +DigitalOut load_batt_orange(p24); //setting high will turn on the load batt orange LED +DigitalOut DUT_batt_green(p10); //setting high will turn on the DUT batt green LED +DigitalOut DUT_batt_orange(p11); //setting high will turn on the DUT batt orange LED + +DigitalOut cap_green(p12); //setting high will turn on the cap green LED +DigitalOut cap_orange(p13); //setting high will turn on the cap orange LED + +#ifdef CURRENT_SENSOR_ON +AnalogIn current_sense(p15); //current sensor on p15 +#else +DigitalOut place_holder15(p15); //sets p15 as a DigitalOut that will be set low, to reduce noise on analog in pins +#endif + +//sets p15 and p18 as a DigitalOut that will be set low, to reduce noise on analog in pins +DigitalOut place_holder16(p16); +DigitalOut place_holder18(p18); + +#ifdef LOAD_BATT_ENABLE +AnalogIn v_load_batt_measure(p17); //Analog in from load battery +#endif + +#ifdef DUT_BATT_ENABLE +AnalogIn v_DUT_batt_measure(p20); //Analog in from drive battery +DigitalOut place_holder19(p19); //sets p19 as a DigitalOut that will be set low, to reduce noise on analog in pins +#endif + +#ifdef DUT_BATT_CAP_ENABLE +AnalogIn v_DUT_batt_measure(p20); //Analog in from drive battery +AnalogIn v_cap_measure(p19); //Analog in from super cap +#endif + +DigitalIn kill_switch(p9); //switch to disable running program + +//matlab interface +#ifdef MATLAB_INTERFACE +//tie program variables to RPC variables used in Matlab +RPCVariable<float> RPC_DUT_input(&DUT_input, "DUT_input"); +RPCVariable<float> RPC_load_input(&load_input, "load_input"); +RPCVariable<float> RPC_DUT_input_direc(&DUT_input_direc, "DUT_input_direc"); +RPCVariable<float> RPC_load_input_direc(&load_input_direc,"load_input_direc"); +RPCVariable<float> RPC_current(¤t, "current"); +RPCVariable<float> RPC_speed(&speed, "speed"); +RPCVariable<float> RPC_v_DUT_batt(&v_DUT_batt, "v_DUT_batt"); +RPCVariable<float> RPC_v_load_batt(&v_DUT_batt, "v_load_batt"); +RPCVariable<float> RPC_v_cap(&v_DUT_batt, "v_cap"); +#endif + +/***********************************************************/ +/*Terminals */ +/***********************************************************/ + +#ifdef MATLAB_INTERFACE +SerialRPCInterface SerialInterface(USBTX, USBRX);//establich RPC serial connection +#endif + +#ifdef SERIAL_INTERFACE +Serial pc(USBTX, USBRX); //Establish serial +#endif + +/***********************************************************/ +/*Other Includes */ +/***********************************************************/ + +#include "power_sources.h" +#include "measurement.h" +#include "motor_control.h" + +/***********************************************************/ +/*Subroutines */ +/***********************************************************/ + +//LED control +void all_LEDS_flash() { //a demo program that just switches LEDs between green and orange + if (foo == 0) { + leftArrow = 0; + greenLine = 0; + orangeLine = 1; + rightArrow = 1; + load_batt_green = 0; + load_batt_orange = 1; + DUT_batt_green = 0; + DUT_batt_orange = 1; + cap_green = 0; + cap_orange = 1; + foo = 1; + } else { + leftArrow = 1; + greenLine = 1; + orangeLine = 0; + rightArrow = 0; + load_batt_green = 1; + load_batt_orange = 0; + DUT_batt_green = 1; + DUT_batt_orange = 0; + cap_green = 1; + cap_orange = 0; + foo = 0; + } +} + +//turn all LEDs off +void all_LEDS_off() { + load_batt_green = 1; + load_batt_orange = 1; + leftArrow = 1; + greenLine = 1; + orangeLine = 1; + rightArrow = 1; + DUT_batt_green = 1; + DUT_batt_orange = 1; + cap_green = 1; + cap_orange = 1; +} + +//turns on the green LEDs indicating regen +void regen_LEDS() { + load_batt_green = 1; + load_batt_orange = 0; + leftArrow = 0; + greenLine = 0; + orangeLine = 1; + rightArrow = 1; + if (!relay) { + DUT_batt_green = 0; + DUT_batt_orange = 1; + cap_green = 1; + cap_orange = 1; + } else { + DUT_batt_green = 1; + DUT_batt_orange = 1; + cap_green = 0; + cap_orange = 1; + } +} + +//turns on the orange LEDs indicating drive mode (power flowing out of the vehicle) +void drive_LEDS() { + load_batt_green = 0; + load_batt_orange = 1; + leftArrow = 1; + greenLine = 1; + orangeLine = 0; + rightArrow = 0; + if (!relay) { + DUT_batt_green = 1; + DUT_batt_orange = 0; + cap_green = 1; + cap_orange = 1; + } else { + DUT_batt_green = 1; + DUT_batt_orange = 1; + cap_green = 1; + cap_orange = 0; + } +} +/***********************************************************/ +/*Main program setup */ +/***********************************************************/ + +int main() { + + Timer timer; //create a timer for the main loop + init_pwm(); //initialize PWM + + /***********************************************************/ + /*Main Loop */ + /***********************************************************/ + while (1) { + while (kill_switch ==0) {//run demo while waiting for kill switch to be turned on + all_LEDS_flash(); //switch LEDs between green and orange + wait(.5); //wait 0.5s + } + + // System initializations + DUT_direction.write(1); //set forward + load_direction.write(0); //set reverse. This ensures both motors will apply a torque on the coupler in the same direction + + //initialize system variables to 0 + speed = 0; + current = 0; + big_error = 0; + big_error_led = 0; + relay = 0; //turn on battery by default + + //main loop timer variables + int slow_timer = 0; + int fast_timer = 0; + + timer.start(); //start loop timer + all_LEDS_off(); //turn off LEDs + wait(.5); //wait 0.5s before starting + +#ifdef DEBUG //debugging code + DUT_input = 0.75; + load_input = 0.25; +#endif + +#ifdef DUT_BATT_ENABLE + place_holder19 = 0; //set DigitalOut pin low to reduce noise on adjacent AnalogIn pins +#endif + + //set unused Analog pins to ground +#ifndef CURRENT_SENSOR_ON + place_holder15 = 0; //set DigitalOut pin low to reduce noise on adjacent AnalogIn pins +#endif + place_holder16 = 0; //set DigitalOut pin low to reduce noise on adjacent AnalogIn pins + place_holder18 = 0; //set DigitalOut pin low to reduce noise on adjacent AnalogIn pins + + while (kill_switch == 1 && big_error == 0) {//while the kill switch is on and there are no errors + + // --- SLOW LOOP (1) Hz --- + if (timer.read_ms() - slow_timer >= 1000) { + slow_timer = timer.read_ms(); //read timer value in miliseconds + big_error = checkBattVoltages(); //check batt voltages to ensure they are in the correct voltage range + if (big_error == 1) { + big_error_led = 1; + } + //measure voltages +#ifdef LOAD_BATT_ENABLE + v_load_batt = get_voltage(v_load_batt_measure); //measure load batt voltage +#ifdef SERIAL_INTERFACE + pc.printf("Analog In (p17): %f ", v_load_batt); //print load voltage to terminal +#endif +#endif + +#ifdef DUT_BATT_ENABLE + v_DUT_batt =get_voltage(v_DUT_batt_measure); //measure DUT batt voltage +#ifdef SERIAL_INTERFACE + pc.printf("Analog In (p20): %f ", v_DUT_batt); //print load voltage to terminal +#endif +#endif + + +#ifdef DUT_BATT_CAP_ENABLE + v_cap = get_voltage(v_cap_measure); //measure cap voltage + v_DUT_batt =get_voltage(v_DUT_batt_measure); //measure DUT batt voltage +#ifdef SERIAL_INTERFACE + pc.printf("Analog In (p19): %f Analog In (p20): %f Speed: %f Current: %f\r\n", v_cap, v_DUT_batt, speed, current); //print cap voltage, DUT batt voltage, speed, current to terminal +#endif +#endif + } + + // --- FAST LOOP (100 Hz) --- + if (timer.read_ms() - fast_timer >= 10) { + fast_timer = timer.read_ms(); //read time in ms + set_duty(DUT_input,load_input); //set the duty cycle + get_speed(); //update motor speed + +#ifdef CURRENT_SENSOR_ON + get_current(); //update current +#endif + +#ifdef LIGHTS_LOAD_CONTROL //controls the board LEDs based on the value of the DUT and Load motor duty cycle + //turn on green LEDs if in regen mode, and orange LEDs if in drive mode. + if (DUT_input >= load_input && (DUT_input != 0 || load_input != 0)) {//check if not in regen mode + regen = 0; //set regen flag low + drive_LEDS(); //turn on orange LEDs + } else if (DUT_input < load_input && (DUT_input != 0 || load_input != 0)) {//check if in regen mode + regen = 1; //set regen flag high + regen_LEDS(); //turn on green LEDs + } else {// DUT is niether flowing into or out of DUT + regen = 0; //set regen flag low + all_LEDS_off();// LEDs off + } +#endif + +#ifdef LIGHTS_CURRENT_CONTROL //controls the board LEDs based on the value of the DUT and Load motor currents + //turn on green LEDs if in regen mode, and orange LEDs if in drive mode. + if (current > 0) { + regen = 0; //set regen flag low + drive_LEDS(); //turn on orange LEDs + } else if (current < 0) { + regen = 1; //set regen flag high + regen_LEDS(); //turn on green LEDs + } else { + regen = 0; //set regen flag low + all_LEDS_off(); // LEDs off + } +#endif + +#ifdef DUT_BATT_CAP_ENABLE + superCapControl(); +#endif + } + + // reset timer if 1000 seconds have elapsed + if (timer.read() >= 1000) { + timer.reset(); + slow_timer = 0; + fast_timer = 0; + } + } + //turn off motors + load_motor =0; + DUT_motor = 0; + timer.stop(); + timer.reset(); + } + +}
diff -r 000000000000 -r 2dbd366be5fd mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Mon May 07 16:14:45 2012 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/737756e0b479
diff -r 000000000000 -r 2dbd366be5fd measurement.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/measurement.h Mon May 07 16:14:45 2012 +0000 @@ -0,0 +1,70 @@ +/***********************************************************/ +/*Constants */ +/***********************************************************/ + +#define ISENSOR_SLOPE 23.9 //slope of the current sensor in [A/V] +#define Y_INTERCEPT -60.1563 //sensor voltage at 0 current +#define NUM_HALF_CYCLES 4 //set the number of ticks over which to measure speed +#define WAIT_BEFORE_SPEEDSTOP 7.5 //amount of time to wait before declaring that the motor is not moving. 7.5s corresponds to a speed of 1 rev/min +#define R1 200000//voltage measurement resistor connected to device under measurement [Ohm] +#define R2 100000//voltage measurement resistor connected to ground [Ohm] + +/***********************************************************/ +/*Variables */ +/***********************************************************/ + +float end, begin, current_read; +int current_state; +int count = 0; + +Timer speed_timer; + +/***********************************************************/ +/*Pin setup */ +/***********************************************************/ +//Encoder +DigitalIn speed_yellow(p7); //yellow wire from sinusoidal encoder +DigitalIn speed_green(p8); //green wire from sinusoidal encoder + +/***********************************************************/ +/*Subroutines */ +/***********************************************************/ + +//get the voltage for one of the energy storage devices. Takes pin as a parameter +float get_voltage (AnalogIn& pin) { + float voltage; + voltage = pin.read()*3.3*(R1+R2)/R2; //scaling to account for voltage divider + return voltage; +} + +//returns current in amps +#ifdef CURRENT_SENSOR_ON +void get_current() { + current_read = current_sense.read(); //read raw AnalogIn value of current + current = ISENSOR_SLOPE*current_read*3.3 + Y_INTERCEPT; //scaling to get current in A +} +#endif + +//returns speed in rad/sec +void get_speed() { + current_state = speed_yellow; //get the current state of speed_yellow pin (0 or 1) + speed_timer.start(); + while (speed_yellow == current_state && speed_timer <=WAIT_BEFORE_SPEEDSTOP) {} //wait for value of the speed_yellow to change, indicating the beginning of a new cycle + if (speed_timer < WAIT_BEFORE_SPEEDSTOP) { //check that the timer is less than WAIT_BEFORE_SPEEDSTOP, to make sure it has not been running for too long. This will happen if speed = 0 + speed_timer.reset(); //reset the timer so that it starts timing from the beginning of the new cycle + begin = speed_timer.read(); + for (int i = 1; i <= NUM_HALF_CYCLES; i++) { //loop to allow timing over a set number of encoder cycles + current_state = speed_yellow; + while (speed_yellow == current_state && speed_timer <= WAIT_BEFORE_SPEEDSTOP) {}//wait for speed_yellow pin to change. If it does not change, the loop will exit when speed_timer = WAIT_BEFORE_SPEEDSTOP + } + if (speed_timer < WAIT_BEFORE_SPEEDSTOP) { + end = speed_timer.read(); //time at the end of timing NUM_HALF_CYCLES cycles + speed_timer.stop(); + speed =((3.14159265/8)*NUM_HALF_CYCLES)/(end-begin); //record speed in rad/sec + } else { + speed = 0; //speed = 0 if the timer has exceeded WAIT_BEFORE_SPEEDSTOP + } + } else { + speed = 0; //speed = 0 if the timer has exceeded WAIT_BEFORE_SPEEDSTOP + } +} \ No newline at end of file
diff -r 000000000000 -r 2dbd366be5fd motor_control.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/motor_control.h Mon May 07 16:14:45 2012 +0000 @@ -0,0 +1,89 @@ +/***********************************************************/ +/*Constants */ +/***********************************************************/ + +#define V_MOTOR_RATED 6 //rated motor voltage [V]. this must be set to be less than the voltage of the batteries +#define PERIOD_US 25 //define the PWM period in microseconds, currently set for 40kHz + +/***********************************************************/ +/*Pin setup */ +/***********************************************************/ + +//Enable PWM inout to motorcontroller +PwmOut DUT_motor(p22); +PwmOut load_motor(p21); + +//Motor direction control on motor controller switch 2 +DigitalOut DUT_direction(p5); +DigitalOut load_direction(p6); + +/***********************************************************/ +/*Subroutines */ +/***********************************************************/ + +//initialize PWM +void init_pwm () { + //set the PWM channel periods + DUT_motor.period_us(PERIOD_US); + load_motor.period_us(PERIOD_US); + + //initialize duty cycle to 0 to make sure motors are off + DUT_motor =0; + load_motor =0; +} + +/* +Set PWM duty cycle + - Motors are connected so that they will always oppose each other. + - Duty cycle (a float from 0-1) determines the voltage applied to the motor terminals as a percentage of the rated voltage. eg. if duty is 0.5 and rated voltage is 6V, then terminal voltage will be 3V +*/ +void set_duty (float DUT_demand, float load_demand) { + +//DUT batt and cap enabled +#ifdef DUT_BATT_CAP_ENABLE + if (relay) { + v_DUT_batt = get_voltage(v_DUT_batt_measure); //get voltage of DUT battery + DUT_demand = DUT_demand*(V_MOTOR_RATED/v_DUT_batt); //scale the demand so that the voltage to the motor does not exceed its rated max + } else if (relay == 0) { //if cap is currently being used + v_cap = get_voltage(v_cap_measure); //get voltage of cap + DUT_demand = DUT_demand*(V_MOTOR_RATED/v_cap); //scale the demand so that the voltage to the motor does not exceed its rated max + } else { + big_error = 1; //error flag + big_error_led = 1; //turn on error LED + } + DUT_motor.write(DUT_demand); //write new DUT duty cycle +#endif + +//DUT batt connected +#ifdef DUT_BATT_ENABLE + v_DUT_batt = get_voltage(v_DUT_batt_measure); //get voltage of DUT battery + DUT_demand = DUT_demand*(V_MOTOR_RATED/v_DUT_batt); //scale the demand so that the voltage to the motor does not exceed its rated max + DUT_motor.write(DUT_demand); //change DUT duty cycle based on demand +#endif + +//Load batt connected +#ifdef LOAD_BATT_ENABLE + v_load_batt = get_voltage(v_load_batt_measure); //get voltage of load battery + load_demand = load_demand*(V_MOTOR_RATED/v_load_batt); //scale the demand so that the voltage to the motor does not exceed its rated max + load_motor.write(load_demand); //change load duty cycle based on demand +#endif + +//External Power +#ifdef DUT_EXTERNAL_POWER_ENABLE + DUT_motor.write(DUT_demand); //change DUT duty cycle based on demand +#endif + +#ifdef LOAD_EXTERNAL_POWER_ENABLE + load_motor.write(load_demand); //change load duty cycle based on demand +#endif + +//set motor directions + DUT_direction.write(DUT_input_direc); + load_direction.write(load_input_direc); +} + + + + + +
diff -r 000000000000 -r 2dbd366be5fd power_sources.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/power_sources.h Mon May 07 16:14:45 2012 +0000 @@ -0,0 +1,58 @@ +/*****************************************************************************/ +/*Constants */ +/*****************************************************************************/ + +#define SCAP_MIN_VOLTAGE 0.607 //Switch to batt below this value (supercap) +#define SCAP_MAX_VOLTAGE 0.845 //Switch to batt above this value (supercap) +#define BATT_MIN_VOLTAGE 0.71 //Shutoff below this value (battery) +#define BATT_MAX_VOLTAGE 0.825 //Shutoff above this value (battery) + +/*****************************************************************************/ +/*Pin Setup */ +/*****************************************************************************/ + +DigitalOut relay(p23); //Pin from which the relay coil is triggered + +/*****************************************************************************/ +/*Subroutines */ +/*****************************************************************************/ + +//Checks battery and supercap voltages, returning 1 if the system needs to be shut down. +int checkBattVoltages() { + //Check to see if batteries are out of proper voltage range +#ifdef DUT_BATT_ENABLE + //check DUT batt + if (v_DUT_batt_measure < BATT_MIN_VOLTAGE + || v_DUT_batt_measure> BATT_MAX_VOLTAGE) { //check if voltage out of range + relay = 1; //switch to cap + return 1; + } +#endif + +#ifdef DUT_BATT_CAP_ENABLE + //check DUT batt + if (v_DUT_batt_measure < BATT_MIN_VOLTAGE + || v_DUT_batt_measure> BATT_MAX_VOLTAGE) { //check if voltage out of range + relay = 1; //switch to cap + return 1; + } +#endif + +#ifdef LOAD_BATT_ENABLE + //check load batt + if ( v_load_batt_measure < BATT_MIN_VOLTAGE + || v_load_batt_measure> BATT_MAX_VOLTAGE) { //check if voltage out of range + return 1; + } +#endif + return 0; //return 0 if all batts are in the correct voltage range +} + +#ifdef DUT_BATT_CAP_ENABLE +void superCapControl() { + if (v_cap_measure <= SCAP_MIN_VOLTAGE && !regen + || regen && v_cap_measure >= SCAP_MAX_VOLTAGE) { //if cap is drained, and regen is not engaged, switch back to battery. Or if cap is at its max voltage, and regen is engaged, switch to batt to prevent overcharging of cap. + relay = 0; //switch to battery + } else relay = 1; //switch to cap +} +#endif \ No newline at end of file