2.007 PulleyInterface mbed code. Biomimetics robotics lab. Sangbae Kim. Ben Katz. For use with PulleyInterface.mlapp
Diff: main.cpp
- Revision:
- 12:6e13c34c4295
- Parent:
- 11:e563823d3c94
- Child:
- 13:d9d0eb9103d3
--- a/main.cpp Wed Mar 01 03:10:29 2017 +0000 +++ b/main.cpp Sat Apr 15 13:44:24 2017 +0000 @@ -1,4 +1,21 @@ -///setup code for encoder on pins PA0 and PA1 (A0 and A1)/// + + +/*** +Basic Program Flow: +mbed turns on. initializes. +enters main while loop then first sub while loop where it listens for a go command +mbed recieves go commmand, initializes for data collection, breaks out of first sub while + enters second sub while. starts collecting and publishing data, listening for stop +mbed hears stop, breaks out of second while loop, returns back to first while loop + + +Keep in Mind: +Serial communication between mbed matlab sometimes sucks, and often breaks down +Most of the things in this program (and the corresponding matlab one) are meant +to minimize the amount of bad data that gets passed over serial and maintain the +connection. +***/ + #include "mbed.h" #include "time.h" @@ -7,22 +24,36 @@ #define PI 3.14159265358979323846 + +//Just for basic debugging +//User button controls motor speed +//Green LED should turn on while listening to pc for input before starting run InterruptIn button(USER_BUTTON); -PwmOut pwm(D5);//do not use D3 -DigitalOut a(D2); -DigitalOut b(D4); - -AnalogIn currentSense(A5); //hook up to Vout on current sensor -Serial pc(USBTX, USBRX, 115200); DigitalOut green(LED2); -const int CPR = 900*4; // Encoder counts per revolution. Change to match your encoder. x4 for quadrature! -const double VREF = 3; //Microcontroller reference voltage -const float currentSensorOutputRatio = 0.185; // Volts/Amp. Divide Voltage by cSenseOutput to get current -const float PSupply_Voltage = 12.0; -const float Output_Voltage = 6.0; +// Pololu VNH5019 Motor Driver Carrier. https://www.pololu.com/product/1451 +PwmOut pwm(D5); //pwm input on motor controller. do not use D3 +DigitalOut a(D2); //IN_A input on motor controller +DigitalOut b(D4); //IN_B input on motor controller + +//Hook up to Vout on current sensor +//SparkFun Hall-Effect Current Sensor Breakout - ACS712 +//https://www.sparkfun.com/products/8882 +AnalogIn currentSense(A5); + +//For communication with pc through matlab +//Make sure baud rates are equal +Serial pc(USBTX, USBRX, 115200); + +const int CPR = 900*4; // Encoder counts per revolution (900). Change to match your encoder. x4 for quadrature +const double VREF = 3; // Microcontroller reference voltage +const float currentSensorOutputRatio = 0.185; // Volts/Amp specified by current sensor. Divide Voltage by cSenseOutput to get current +const float PSupply_Voltage = 12.0; // Voltage input from powersupply +const float Output_Voltage = 6.0; // Maximum output voltage desired const float pwm_pulley = Output_Voltage/PSupply_Voltage; + +///setup code for encoder on ***** pins PA0 and PA1 (A0 and A1) ****** /// void EncoderInitialise(void) { // configure GPIO PA0 & PA1 as inputs for Encoder RCC->AHB1ENR |= 0x00000001; // Enable clock for GPIOA @@ -77,20 +108,27 @@ int main() { - int endcount, startcount; - double time_between_readings; - double velocity; + int endcount, startcount; // encoder counts + double time_between_readings; // between encoder readings + double velocity; // radians/time double currentSensed = 0; clock_t start, end, absoluteStart; - int ticks; - a=1; b=0; pwm.write(0); - button.fall(&pressed); - double updatePeriod = 0.01; /* must select carefully */ - double publishFrequency = 0.05; /* seconds. rate to publish to matlab */ - double samplesPerPublish = (int)(publishFrequency/updatePeriod); /*this improves time response of filter and maintains smoothness*/ + int ticks; // ticks counted on encoder + a=1; b=0; pwm.write(0); // this is forward. you can change a and b on a rig if it's turning the wrong way! + button.fall(&pressed); //adds pressed callback upon button push + + /* we don't send all the information to matlab all the time. some collection and smoothing is done + here in order to not overload matlab with input making it slow. And to take a lot of data so we + can do smoothing quickly on this side */ + double updatePeriod = 0.01; /* must select carefully. too fast and you don't get enough encoder ticks*/ + double publishFrequency = 0.05; /* seconds. rate to publish to matlab. no need to overload matlab with input*/ + double samplesPerPublish = (int)(publishFrequency/updatePeriod); int publishCounter = 1; - double filterRatio = 0.1; - double currentFilterRatio = 0.035; + + double filterRatio = 0.1; // on the speed data + double currentFilterRatio = 0.035; // on the current data + + /* the current sensor has some resting value. record and subtract that out */ float currentSensorOffset = 0; int i; for(i=1;i<301;i++){ currentSensorOffset += currentSense.read(); } currentSensorOffset = currentSensorOffset*VREF/300; @@ -101,7 +139,7 @@ while(1) { - while(1) { + while(1) { // listen for pc go command green = true; if(pc.readable()) { @@ -115,8 +153,17 @@ startcount = 0; endcount = 0; currentSensed = 0; - pwm.write(pwm_pulley); - break; + pwm.write(pwm_pulley); + break; + // note: it's really easy to change this if we want to include + // variable speed input from the command in the future. + // it's easiest to just pass chars as serial input when the + // mbed is listening (I find it's the most reliable) + // so an easy way would just be to pass a 1 2 3 ... 9 0 + // corresponding to some percentage of the max output voltage + // as the start value for the run + // ask me for previous pulley interface mbed and matlab code + // where I have that implimented } } @@ -125,7 +172,7 @@ } - while(1) { + while(1) { //start collecting and publishing data green = false; wait(updatePeriod); @@ -137,9 +184,11 @@ ticks = endcount-startcount; if(abs(ticks)>CPR/2) /***** for rollover case: *****/ { ticks = ((ticks<0)-(ticks>0))*(CPR-abs(ticks)); } + velocity = filterRatio*((double)ticks)/CPR*2*PI/time_between_readings + (1-filterRatio)*velocity; /* with filtering*/ currentSensed = currentFilterRatio*((double)currentSense.read()*VREF-currentSensorOffset) + (1-currentFilterRatio)*currentSensed; - if(pc.readable()) + + if(pc.readable()) //pc will send r (reset) when run is finished { char charIn = pc.getc(); if(charIn == 'r'){ @@ -148,9 +197,9 @@ break; } } - if(publishCounter == samplesPerPublish) { + if(publishCounter == samplesPerPublish) { //only publish onece every samplesPerPublish printf("%+9.5f,%+8.4f,%+9.4f,%+8.2f\n", currentSensed/currentSensorOutputRatio, pwm.read(), velocity, ((double)(end-absoluteStart)/CLOCKS_PER_SEC)); - publishCounter = 1; // good for 1000 seconds. and room to grow one power of 10 on all other inputs. //just changed velocity to 4 precision to give it extra room for no load? bug maybe? + publishCounter = 1; //output formatting very important. running a simple string length checksum on matlab side to discard bad data } publishCounter++;