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.
main.cpp
00001 // Workshop 2 00002 #include "mbed.h" 00003 #include "PM2_Libary.h" 00004 00005 // logical variable main task 00006 bool do_execute_main_task = false; // this variable will be toggled via the user button (blue button) to or not to execute the main task 00007 00008 // user button on nucleo board 00009 Timer user_button_timer; // create Timer object which we use to check if user button was pressed for a certain time (robust against signal bouncing) 00010 InterruptIn user_button(PC_13); // create InterruptIn interface object to evaluate user button falling and rising edge (no blocking code in ISR) 00011 void user_button_pressed_fcn(); // custom functions which gets executed when user button gets pressed and released, definition below 00012 void user_button_released_fcn(); 00013 00014 // while loop gets executed every main_task_period_ms milliseconds 00015 int main_task_period_ms = 50; // define main task period time in ms e.g. 50 ms -> main task runns 20 times per second 00016 Timer main_task_timer; // create Timer object which we use to run the main task every main task period time in ms 00017 00018 // led on nucleo board 00019 DigitalOut user_led(LED1); // create DigitalOut object to command user led 00020 00021 // additional Led 00022 DigitalOut extra_led(PB_9); // create DigitalOut object to command extra led (do add an aditional resistor, e.g. 220...500 Ohm) 00023 00024 // mechanical button 00025 DigitalIn mechanical_button(PC_5); // create DigitalIn object to evaluate extra mechanical button, you need to specify the mode for proper usage, see below 00026 00027 // Sharp GP2Y0A41SK0F, 4-40 cm IR Sensor 00028 float ir_distance_mV = 0.0f; // define variable to store measurement 00029 AnalogIn ir_analog_in(PC_2); // create AnalogIn object to read in infrared distance sensor, 0...3.3V are mapped to 0...1 00030 00031 // 78:1, 100:1, ... Metal Gearmotor 20Dx44L mm 12V CB 00032 DigitalOut enable_motors(PB_15); // create DigitalOut object to enable dc motors 00033 00034 float pwm_period_s = 0.00005f; // define pwm period time in seconds and create FastPWM objects to command dc motors 00035 FastPWM pwm_M1(PB_13); // motor M1 is used open loop 00036 FastPWM pwm_M2(PA_9); // motor M2 is closed-loop speed controlled (angle velocity) 00037 FastPWM pwm_M3(PA_10); // motor M3 is closed-loop position controlled (angle controlled) 00038 00039 EncoderCounter encoder_M1(PA_6, PC_7); // create encoder objects to read in the encoder counter values 00040 EncoderCounter encoder_M2(PB_6, PB_7); 00041 EncoderCounter encoder_M3(PA_0, PA_1); 00042 00043 // create SpeedController and PositionController objects, default parametrization is for 78.125:1 gear box 00044 float max_voltage = 12.0f; // define maximum voltage of battery packs, adjust this to 6.0f V if you only use one batterypack 00045 float counts_per_turn = 20.0f * 78.125f; // define counts per turn at gearbox end: counts/turn * gearratio 00046 float kn = 180.0f / 12.0f; // define motor constant in rpm per V 00047 float k_gear = 100.0f / 78.125f; // define additional ratio in case you are using a dc motor with a different gear box, e.g. 100:1 00048 float kp = 0.1f; // define custom kp, this is the default speed controller gain for gear box 78.125:1 00049 00050 // SpeedController speedController_M2(counts_per_turn, kn, max_voltage, pwm_M2, encoder_M2); // default 78.125:1 gear box with default contoller parameters 00051 SpeedController speedController_M2(counts_per_turn * k_gear, kn / k_gear, max_voltage, pwm_M2, encoder_M2); // parameters adjusted to 100:1 gear 00052 00053 float max_speed_rps = 0.5f; // define maximum speed that the position controller is changig the speed, has to be smaller or equal to kn * max_voltage 00054 // PositionController positionController_M3(counts_per_turn, kn, max_voltage, pwm_M3, encoder_M3); // default 78.125:1 gear with default contoller parameters 00055 PositionController positionController_M3(counts_per_turn * k_gear, kn / k_gear, kp * k_gear, max_voltage, pwm_M3, encoder_M3); // parameters adjusted to 100:1 gear, we need a different speed controller gain here 00056 00057 // Futaba Servo S3001 20mm 3kg Analog 00058 Servo servo_S1(PB_2); // create servo objects 00059 Servo servo_S2(PC_8); 00060 float servo_S1_angle = 0; // servo S1 normalized angle 00061 float servo_S2_angle = 0; // servo S2 normalized angle 00062 int servo_period_mus = 20000; // define servo period time in mus 00063 00064 int servo_counter = 0; // define servo counter, this is an additional variable to make the servos move 00065 int loops_per_seconds = static_cast<int>(ceilf(1.0f/(0.001f*(float)main_task_period_ms))); // define loops per second 00066 00067 // Groove Ultrasonic Ranger V2.0 00068 float us_distance_cm = 0.0f; // define variable to store measurement 00069 RangeFinder us_range_finder(PB_12, 5782.0f, 0.02f, 17500); // create range finder object (ultra sonic distance sensor), 20 Hz parametrization 00070 // RangeFinder us_range_finder(PB_12, 5782.0f, 0.02f, 7000); // create range finder object (ultra sonic distance sensor), 50 Hz parametrization 00071 00072 // LSM9DS1 IMU, carefull: not all PES boards have an imu (chip shortage) 00073 // LSM9DS1 imu(PC_9, PA_8); // create LSM9DS1 comunication object, if you want to be able to use the imu you need to #include "LSM9DS1_i2c.h" 00074 00075 int main() 00076 { 00077 // attach button fall and rise functions to user button object 00078 user_button.fall(&user_button_pressed_fcn); 00079 user_button.rise(&user_button_released_fcn); 00080 00081 // start timer 00082 main_task_timer.start(); 00083 00084 // set pullup mode: add resistor between pin and 3.3 V, so that there is a defined potential 00085 mechanical_button.mode(PullUp); 00086 00087 // enable hardwaredriver dc motors: 0 -> disabled, 1 -> enabled 00088 enable_motors = 1; 00089 00090 // motor M1 is used open-loop, we need to initialize the pwm and set pwm output to zero at the beginning, range: 0...1 -> u_min...u_max: 0.5 -> 0 V 00091 pwm_M1.period(pwm_period_s); 00092 pwm_M1.write(0.5f); 00093 00094 // set the soft pwm period for the servo objects 00095 servo_S1.SetPeriod(servo_period_mus); 00096 servo_S2.SetPeriod(servo_period_mus); 00097 00098 while (true) { // this loop will run forever 00099 00100 main_task_timer.reset(); 00101 00102 if (do_execute_main_task) { 00103 00104 // read analog input 00105 ir_distance_mV = 1.0e3f * ir_analog_in.read() * 3.3f; 00106 00107 // command dc motors if mechanical button is pressed 00108 if (mechanical_button.read()) { 00109 pwm_M1.write(0.75f); // write output voltage to motor M1 00110 speedController_M2.setDesiredSpeedRPS(0.5f); // set a desired speed for speed controlled dc motors M2 00111 positionController_M3.setDesiredRotation(1.5f, max_speed_rps); // set a desired rotation for position controlled dc motors M3 00112 } else { 00113 pwm_M1.write(0.5f); 00114 speedController_M2.setDesiredSpeedRPS(0.0f); 00115 positionController_M3.setDesiredRotation(0.0f, max_speed_rps); 00116 } 00117 00118 // check if servos are enabled 00119 if (!servo_S1.isEnabled()) servo_S1.Enable(); 00120 if (!servo_S2.isEnabled()) servo_S2.Enable(); 00121 // command servo position, this needs to be calibrated 00122 servo_S1.SetPosition(servo_S1_angle); 00123 if (servo_S1_angle < 1.0f & servo_counter%loops_per_seconds == 0 & servo_counter != 0) { 00124 servo_S1_angle += 0.01f; 00125 } 00126 servo_S2.SetPosition(servo_S2_angle); 00127 if (servo_S2_angle < 1.0f & servo_counter%loops_per_seconds == 0 & servo_counter != 0) { 00128 servo_S2_angle += 0.01f; 00129 } 00130 servo_counter++; 00131 00132 // read ultra sonic distance sensor 00133 us_distance_cm = us_range_finder.read_cm(); 00134 00135 // visual feedback that the main task is executed 00136 extra_led = 1; 00137 00138 } else { 00139 00140 ir_distance_mV = 0.0f; 00141 00142 pwm_M1.write(0.5f); 00143 speedController_M2.setDesiredSpeedRPS(0.0f); 00144 positionController_M3.setDesiredRotation(0.0f, max_speed_rps); 00145 00146 servo_S1_angle = 0; 00147 servo_S2_angle = 0; 00148 // servo_S1.SetPosition(servo_S1_angle); 00149 // servo_S2.SetPosition(servo_S2_angle); 00150 if (servo_S1.isEnabled()) servo_S1.Disable(); 00151 if (servo_S2.isEnabled()) servo_S2.Disable(); 00152 00153 us_distance_cm = 0.0f; 00154 00155 extra_led = 0; 00156 } 00157 00158 user_led = !user_led; 00159 00160 // do only output via serial what's really necessary (this makes your code slow) 00161 printf("IR sensor (mV): %3.3f, Encoder M1: %3d, Speed M2 (rps) %3.3f, Position M3 (rot): %3.3f, Servo S1 angle (normalized): %3.3f, Servo S2 angle (normalized): %3.3f, US sensor (cm): %3.3f\r\n", 00162 ir_distance_mV, 00163 encoder_M1.read(), 00164 speedController_M2.getSpeedRPS(), 00165 positionController_M3.getRotation(), 00166 servo_S1_angle, 00167 servo_S2_angle, 00168 us_distance_cm); 00169 00170 // read out the imu, the actual frames of the sensor reading needs to be figured out 00171 // imu.updateGyro(); 00172 // imu.updateAcc(); 00173 // imu.updateMag(); 00174 // printf("%.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f\r\n", imu.readGyroX(), imu.readGyroY(), imu.readGyroZ(), 00175 // imu.readAccX(), imu.readAccY(), imu.readAccZ(), imu.readMagX(), imu.readMagY(), imu.readMagZ()); 00176 00177 // read timer and make the main thread sleep for the remaining time span (non blocking) 00178 int main_task_elapsed_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(main_task_timer.elapsed_time()).count(); 00179 thread_sleep_for(main_task_period_ms - main_task_elapsed_time_ms); 00180 } 00181 } 00182 00183 void user_button_pressed_fcn() 00184 { 00185 user_button_timer.start(); 00186 user_button_timer.reset(); 00187 } 00188 00189 void user_button_released_fcn() 00190 { 00191 // read timer and toggle do_execute_main_task if the button was pressed longer than the below specified time 00192 int user_button_elapsed_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(user_button_timer.elapsed_time()).count(); 00193 user_button_timer.stop(); 00194 if (user_button_elapsed_time_ms > 200) { 00195 do_execute_main_task = !do_execute_main_task; 00196 } 00197 }
Generated on Sun Aug 7 2022 07:30:16 by
