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: HIDScope MODSERIAL QEI biquadFilter mbed
Revision 43:a6fbcada47aa, committed 2017-11-03
- Comitter:
- ralphg_92
- Date:
- Fri Nov 03 08:38:14 2017 +0000
- Parent:
- 42:3aa03b5cefb0
- Commit message:
- revisiting old memories
Changed in this revision
| PID.lib | Show diff for this revision Revisions of this file |
| main.cpp | Show annotated file Show diff for this revision Revisions of this file |
diff -r 3aa03b5cefb0 -r a6fbcada47aa PID.lib --- a/PID.lib Fri Nov 03 03:52:30 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -https://os.mbed.com/users/aberk/code/PID/#6e12a3e5af19
diff -r 3aa03b5cefb0 -r a6fbcada47aa main.cpp
--- a/main.cpp Fri Nov 03 03:52:30 2017 +0000
+++ b/main.cpp Fri Nov 03 08:38:14 2017 +0000
@@ -2,7 +2,7 @@
#include "HIDScope.h"
#include "MODSERIAL.h"
#include "BiQuad.h"
-#include "QEI.h"
+//#include "QEI.h"
//Define Objects
AnalogIn emg1_in( A0 ); // Read Out The Signal
@@ -16,21 +16,21 @@
PwmOut motor1pwm( D5);
PwmOut motor2pwm( D6 );
DigitalOut motor2direction( D7 );
- QEI Encoder1(D10, D11, NC, 64); // Encoder
- QEI Encoder2(D12, D13, NC, 64);
+ //QEI Encoder1(D10, D11, NC, 32); // Encoder
+ //QEI Encoder2(D12, D13, NC, 32);
Ticker main_timer;
Ticker max_read1;
Ticker max_read3;
Ticker Motorcontrol;
- Ticker tencoder;
- HIDScope scope( 4 );
+ HIDScope scope( 6 );
DigitalOut red(LED_RED);
DigitalOut blue(LED_BLUE);
DigitalOut green(LED_GREEN);
- Serial pc(USBTX, USBRX);
+ MODSERIAL pc(USBTX, USBRX);
-// EMG Variables & Constants
+
+// EMG Variables
//Right Biceps
double emg1;
double emg1highfilter;
@@ -63,7 +63,7 @@
double emg4lowfilter;
double max4;
double maxpart4;
- // Moving Average Floats
+// Moving Average Floats
// Right Biceps Movavg
float RB0, RB1, RB2, RB3, RB4, RB5, RB6, RB7, RB8, RB9, RB10, RB11, RB12,
RB13, RB14, RB15, RB16, RB17, RB18, RB19, RB20, RB21, RB22, RB23, RB24,
@@ -102,48 +102,10 @@
RL85, RL86, RL87, MOVAVG_RL;
float AV = 0.02; //multiplication value for adding each movavg value
// This value also adds a very slight gain to every value
-
-// RKI Variables & Constants
- double setpoint1 = 2.35;
- double setpoint2 = 0.785;
- double x = 10.77;
- double y = 15.73;
- float pi = 3.14159265359;
- float a = 22.25; //originally 22.25, makes for xinitial=10.766874 // length of arm 1
- float b = 26.5; //originally 16.48 makes for yinitial=15.733 // length of arm 2
- double alpha_old = 2.35; //INITIAL ANGLES IN RADIANS
- double beta_old = 0.785;
- float delta1;
- float delta2;
- float diffmotor_a;
- float diffmotor_b;
-
-// PID Variables & Constants
- double Kp = 0.5;// you can set these constants however you like depending on trial & error
- double Ki = 0.1;
- double Kd = 0.1;
-
- float last_error1 = 0;
- float new_error1 = 0;
- float change_error1 = 0;
- float total_error1 = 0;
- float pid_term1 = 0;
- float pid_term_scaled1 = 0;
- float last_error2 = 0;
- float new_error2 = 0;
- float change_error2 = 0;
- float total_error2 = 0;
- float pid_term2 = 0;
- float pid_term_scaled2 = 0;
-
-// Motor Variables & Constants
- //float MV1 = 0;
- //float MV2 = 0;
- double count1 = 0;
- double count2 = 0;
- double angle1 = 2.35;
- double angle2 = 0.785;
+// Motor Variables
+ float MV1 = 0;
+ float MV2 = 0;
// BiQuad Filter Settings
// Right Biceps
@@ -164,32 +126,9 @@
BiQuad filterlow4(1.368e-03,2.737e-03,1.369e-03,-1.9219,9.274e-01);
//
-// RKI Calculations
-//
-//
+// Finding max values for correct motor switch if the button is pressed
+// calibration of both biceps
-float inversekinematics1(float x, float y){
- // cosine law:
- float c = sqrtf(x*x + y*y); // here comes the relevant math, see my inverse kinematics explaination using cosine law
- float alpha1 = acosf((a*a + c*c - b*b)/(2*a*c));
-
- // remaining parts of alpha:
- float alpha2 = atan2f(y,x);
- float alpha = alpha1 + alpha2;
- return alpha;
-}
-
-float inversekinematics2(float x, float y){
- // cosine law:
- float c = sqrtf(x*x + y*y); // here comes the relevant math, see my inverse kinematics explaination using cosine law
- float beta = acosf((a*a + b*b - c*c)/(2*a*b));
- return beta;
-}
-
-// Finding max values for correct motor switch if the button is pressed
-//
-//
-// calibration of both biceps
void get_max1(){
if (max_reader12==0){
green = !green;
@@ -279,6 +218,7 @@
}
// calibration of both lower arms
+
void get_max3(){
if (max_reader34==0){
green = 1;
@@ -367,10 +307,8 @@
maxpart4 = 0.17*max4; // set cut off voltage at 15% of max for right lower arm
}
-// EMG Filtering & Scope
-//
-//
-void filter(/*double setpoint1, double setpoint2*/) {
+// Filtering & Scope
+void filter() {
// Right Biceps
emg1 = emg1_in.read();
emg1highfilter = filterhigh1.step(emg1);
@@ -508,117 +446,81 @@
// Compare measurement to the calibrated value to decide actions
// more options could be added if the callibration is well defined enough
// This part checks for right biceps contractions only
-/* if (maxpart1<MOVAVG_RB || maxpart2<MOVAVG_LB || maxpart3<MOVAVG_LL || maxpart4<MOVAVG_RL){
- wait(0.15f);*/
- if (maxpart1<MOVAVG_RB && maxpart2>MOVAVG_LB && maxpart3>MOVAVG_LL && maxpart4>MOVAVG_RL){
+ if (maxpart1<MOVAVG_RB || maxpart2<MOVAVG_LB || maxpart3<MOVAVG_LL || maxpart4<MOVAVG_RL){
+
+ if (maxpart1<MOVAVG_RB && maxpart2>MOVAVG_LB && maxpart3>MOVAVG_LL && maxpart4>MOVAVG_RL){
red = 1;
blue = 1;
green = 0;
- //MV1 = 0.5;
- //MV2 = 0;
- x = x + 0.1;
- if (x > 16) {
- x = 16;
- }
- double alpha = inversekinematics1(x,y); //calculate alpha and beta for current x,y
- double beta = inversekinematics2(x,y);
- setpoint1 = alpha;
- setpoint2 = beta;
- wait(0.1f);
-
- }
- // This part checks for left biceps contractions only
- else if (maxpart1>MOVAVG_RB && maxpart2<MOVAVG_LB && maxpart3>MOVAVG_LL && maxpart4>MOVAVG_RL){
+ MV1 = 0.08;
+ MV2 = 0;
+ }
+ // This part checks for left biceps contractions only
+ else if (maxpart1>MOVAVG_RB && maxpart2<MOVAVG_LB && maxpart3>MOVAVG_LL && maxpart4>MOVAVG_RL){
red = 0;
blue = 1;
green = 1;
- //MV1 = -0.5;
- //MV2 = 0;
- x = x - 0.1;
- if (x < 10.77){
- x = 10.87;
- }
- double alpha = inversekinematics1(x,y);
- double beta = inversekinematics2(x,y);
- setpoint1 = alpha;
- setpoint2 = beta;
- wait(0.1f);
- }
- // This part checks for left lower arm contractions only
- else if (maxpart1>MOVAVG_RB && maxpart2>MOVAVG_LB && maxpart3<MOVAVG_LL && maxpart4>MOVAVG_RL){
+ MV1 = -0.08;
+ MV2 = 0;
+ }
+ // This part checks for left lower arm contractions only
+ else if (maxpart1>MOVAVG_RB && maxpart2>MOVAVG_LB && maxpart3<MOVAVG_LL && maxpart4>MOVAVG_RL){
red = 1;
blue = 0;
green = 1;
- //MV1 = 0;
- //MV2 = 0.5;
- y = y + 0.1;
- if (y > 19.5) {
- y = 19.5;
- }
- double alpha = inversekinematics1(x,y);
- double beta = inversekinematics2(x,y);
- setpoint1 = alpha;
- setpoint2 = beta;
- wait(0.1f);
- }
- // This part checks for right lower arm contractions only
- else if (maxpart1>MOVAVG_RB && maxpart2>MOVAVG_LB && maxpart3>MOVAVG_LL && maxpart4<MOVAVG_RL){
+ MV1 = 0;
+ MV2 = 0.08;
+ }
+ // This part checks for right lower arm contractions only
+ else if (maxpart1>MOVAVG_RB && maxpart2>MOVAVG_LB && maxpart3>MOVAVG_LL && maxpart4<MOVAVG_RL){
red = 0;
blue = 1;
green = 0;
- //MV1 = 0;
- //MV2 = -0.5;
- y = y - 0.1;
- if (y < 15.73) {
- y = 15.83;
- }
- double alpha = inversekinematics1(x,y);
- double beta = inversekinematics2(x,y);
- setpoint1 = alpha;
- setpoint2 = beta;
- wait(0.1f);
- }
-/* // This part checks for both lower arm contractions only
- else if (maxpart1>MOVAVG_RB && maxpart2>MOVAVG_LB && maxpart3<MOVAVG_LL && maxpart4<MOVAVG_RL){
+ MV1 = 0;
+ MV2 = -0.08;
+ }
+ // This part checks for both lower arm contractions only
+ else if (maxpart1>MOVAVG_RB && maxpart2>MOVAVG_LB && maxpart3<MOVAVG_LL && maxpart4<MOVAVG_RL){
+ red = 0;
+ blue = 0;
+ green = 0;
+ MV1 = -0.08;
+ MV2 = -0.08;
+ }
+ // This part checks for both biceps contractions only
+ else if (maxpart1<MOVAVG_RB && maxpart2<MOVAVG_LB && maxpart3>MOVAVG_LL && maxpart4>MOVAVG_RL){
red = 0;
blue = 0;
green = 0;
- //MV1 = -0.5;
- //MV2 = -0.5;
- }
- // This part checks for both biceps contractions only
- else if (maxpart1<MOVAVG_RB && maxpart2<MOVAVG_LB && maxpart3>MOVAVG_LL && maxpart4>MOVAVG_RL){
- red = 0;
- blue = 0;
- green = 0;
- //MV1 = 0.5;
- //MV2 = 0.5;
- }
- // This part checks for right lower arm & left biceps contractions only
- else if (maxpart1>MOVAVG_RB && maxpart2<MOVAVG_LB && maxpart3>MOVAVG_LL && maxpart4<MOVAVG_RL){
+ MV1 = 0.08;
+ MV2 = 0.08;
+ }
+ // This part checks for right lower arm & left biceps contractions only
+ else if (maxpart1>MOVAVG_RB && maxpart2<MOVAVG_LB && maxpart3>MOVAVG_LL && maxpart4<MOVAVG_RL){
red = 0;
blue = 0;
green = 0;
- //MV1 = 0.5;
- //MV2 = -0.5;
- }
- // This part checks for left lower arm & right biceps contractions only
- else if (maxpart1<MOVAVG_RB && maxpart2>MOVAVG_LB && maxpart3<MOVAVG_LL && maxpart4>MOVAVG_RL){
+ MV1 = 0.08;
+ MV2 = -0.08;
+ }
+ // This part checks for left lower arm & right biceps contractions only
+ else if (maxpart1<MOVAVG_RB && maxpart2>MOVAVG_LB && maxpart3<MOVAVG_LL && maxpart4>MOVAVG_RL){
red = 0;
blue = 0;
green = 0;
- //MV1 = -0.5;
- //MV2 = 0.5;
- }*/
- //}
- else {
- red = 1; // Shut down all led colors if no movement is registered
- blue = 1;
- green = 1;
- //MV1 = 0;
- //MV2 = 0;
- }
-
+ MV1 = -0.08;
+ MV2 = 0.08;
+ }
+ }
+ else {
+ red = 1; // Shut down all led colors if no movement is registered
+ blue = 1;
+ green = 1;
+ MV1 = 0;
+ MV2 = 0;
+ //pc.printf( "No contraction registered\n");
+ }
+
// Set the sampled emg values in channel 0 (the first channel) and 1 (the second channel) in the 'HIDScope' instance named 'scope'
scope.set(0, MOVAVG_RB ); // plot Right biceps voltage
scope.set(1, MOVAVG_LB ); // Plot Left biceps voltage
@@ -628,141 +530,42 @@
}
-void encoders(){
- count1 = Encoder1.getPulses();
- count2 = Encoder2.getPulses();
-}
-
-/*
-
-// PID calculations
-//
-//
-void PIDcalculation1() {
-//PID calculation for motor 1
- filter();
- count1 = Encoder1.getPulses();
- angle1 += (0.000748 * count1);
- new_error1 = setpoint1 - angle1;
-
- change_error1 = new_error1 - last_error1;
- total_error1 += new_error1;
- pid_term1 = (Kp * new_error1) + (Ki * total_error1) + (Kd * change_error1);
- if (pid_term1<-255) {
- pid_term1 = -255;
- }
- if (pid_term1>255) {
- pid_term1 = 255;
- }
- pid_term_scaled1 = abs(pid_term1);
-
- last_error1 = new_error1;
-}
-void PIDcalculation2() {
-//PID calculation for motor 2
- filter();
- count2 = Encoder2.getPulses();
- angle2 += (0.000748 * count2);
- new_error2 = setpoint2 - angle2;
-
- change_error2 = new_error2 - last_error2;
- total_error2 += new_error2;
- pid_term2 = (Kp * new_error2) + (Ki * total_error2) + (Kd * change_error2);
- if (pid_term2<-255) {
- pid_term2 = -255;
- }
- if (pid_term2>255) {
- pid_term2 = 255;
+// check MV1 to see if motor1 needs to be activated
+void SetMotor1(float MV1) {
+ motor1pwm = fabs(MV1); // motor speed
+ if (MV1 >=0) {
+ motor1direction = 1; // clockwise rotation
}
- pid_term_scaled2 = abs(pid_term2);
-
- last_error2 = new_error2;
-}
- */
-// Motor control
-//
-//
-// check to see if motor1 needs to be activated
-void SetMotor1() {
- //PIDcalculation1();
- //filter();
- while (angle1<setpoint1 || angle1>setpoint1 || angle2<setpoint2 || angle2>setpoint2) {
- encoders();
- float count1;
- float count2;
- angle1 += (0.0981 * count1);
- angle2 += (0.0981 * count2);
- if (angle1<setpoint1 && angle2<setpoint2) {
- motor1direction = 1; // counterclockwise rotation
- motor2direction = 1;
- }
- else if (angle1>setpoint1 && angle2<setpoint2) {
- motor1direction = 0; // clockwise rotation
- motor2direction = 1;
- }
- else if (angle1<setpoint1 && angle2>setpoint2) {
- motor1direction = 1;
- motor2direction = 0;
- }
- else if (angle1>setpoint1 && angle2>setpoint2) {
- motor1direction = 0;
- motor2direction = 0;
- }
- if ((angle1<setpoint1 || angle1>setpoint1) && (angle2<setpoint2 || angle2>setpoint2)) {
- motor1pwm = 0.2;
- motor2pwm = 0.2;
- }
- else if ((angle1<setpoint1 || angle1>setpoint1) && (angle2 == setpoint2)) {
- motor1pwm = 0.2;
- motor2pwm = 0;
- }
- else if ((angle1 == setpoint1) && (angle2<setpoint2 || angle2>setpoint2)) {
- motor1pwm = 0;
- motor2pwm = 0.2;
- }
- else if ((angle1 == setpoint1) && (angle2 == setpoint2)){
- motor1pwm = 0;
- motor2pwm = 0;
- }
+ else {
+ motor1direction = 0; // counterclockwise rotation
}
}
-/*
-// check if motor1 needs to be activated
-void SetMotor2() {
- filter();
- //PIDcalculation2();
- while (angle2<setpoint2 || angle2>setpoint2) {
- count2 = Encoder2.getPulses();
- angle2 += (0.0981 * count2);
- if (angle2<setpoint2){
- motor1direction = 0; // counterclockwise rotation
- }
- else if (angle2>setpoint2){
- motor1direction = 1; // clockwise rotation
- }
- if (angle2<setpoint2 || angle2>setpoint2) {
- motor2pwm = 0.5;
- }
- else if (angle2 == setpoint2){
- motor2pwm = 0;
- }
+// check MV2 if motor1 needs to be activated
+void SetMotor2(float MV2) {
+ motor2pwm = fabs(MV2); // motor speed
+ if (MV2 >=0) {
+ motor2direction = 1; // clockwise rotation
+ }
+ else {
+ motor2direction = 0; // counterclockwise rotation
}
}
-void MeasureAndControl(void) {
- SetMotor1();
- //SetMotor2();
+void MeasureAndControl(void)
+{
+ // This function measures the potmeter position, extracts a
+ // reference velocity from it, and controls the motor with
+ // a simple FeedForward controller. Call this from a Ticker.
+ SetMotor1(MV1);
+ SetMotor2(MV2);
}
-*/
+
int main(){
- pc.baud(115200);
+
main_timer.attach(&filter, 0.001); // set frequency for the filters at 1000Hz
max_read1.attach(&get_max1, 2); // set the frequency of the calibration loop at 0.5Hz
max_read3.attach(&get_max3, 2);
- tencoder.attach(&encoders, 0.001);
- Motorcontrol.attach(&SetMotor1,0.1);
- //PIDtimer.attach(&PIDcalculation1, 0.005);
- //PIDtimer.attach(&PIDcalculation2, 0.005);
+ Motorcontrol.attach(&MeasureAndControl,0.5);
while(1) {}
}
\ No newline at end of file