Repository navigation
Expand file tree
/
Copy pathmain_servo.cpp
More file actions
141 lines (111 loc) · 5.6 KB
/
Copy pathmain_servo.cpp
File metadata and controls
141 lines (111 loc) · 5.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include "mbed.h"
// pes board pin map
#include "PESBoardPinMap.h"
// drivers
#include "DebounceIn.h"
#include "Servo.h"
bool do_execute_main_task = false; // this variable will be toggled via the user button (blue button) and
// decides whether to execute the main task or not
bool do_reset_all_once = false; // this variable is used to reset certain variables and objects and
// shows how you can run a code segment only once
// objects for user button (blue button) handling on nucleo board
DebounceIn user_button(BUTTON1); // create DebounceIn to evaluate the user button
void toggle_do_execute_main_fcn(); // custom function which is getting executed when user
// button gets pressed, definition at the end
// main runs as an own thread
int main()
{
// attach button fall function address to user button object
user_button.fall(&toggle_do_execute_main_fcn);
// while loop gets executed every main_task_period_ms milliseconds, this is a
// simple approach to repeatedly execute main
const int main_task_period_ms = 20; // define main task period time in ms e.g. 20 ms, therefore
// the main task will run 50 times per second
Timer main_task_timer; // create Timer object which we use to run the main task
// every main_task_period_ms
// led on nucleo board
DigitalOut user_led(LED1);
// additional led
// create DigitalOut object to command extra led, you need to add an additional resistor, e.g. 220...500 Ohm
// a led has an anode (+) and a cathode (-), the cathode needs to be connected to ground via the resistor
DigitalOut led1(PB_9);
// --- adding variables and objects and applying functions starts here ---
// servo
Servo servo_D0(PB_D0);
Servo servo_D1(PB_D1);
// minimal pulse width and maximal pulse width obtained from the servo calibration process
// futuba S3001
float servo_D0_ang_min = 0.0150f; // carefull, these values might differ from servo to servo
float servo_D0_ang_max = 0.1150f;
// reely S0090
float servo_D1_ang_min = 0.0325f;
float servo_D1_ang_max = 0.1175f;
// servo.setPulseWidth: before calibration (0,1) -> (min pwm, max pwm)
// servo.setPulseWidth: after calibration (0,1) -> (servo_D0_ang_min, servo_D0_ang_max)
servo_D0.calibratePulseMinMax(servo_D0_ang_min, servo_D0_ang_max);
servo_D1.calibratePulseMinMax(servo_D1_ang_min, servo_D1_ang_max);
// default acceleration of the servo motion profile is 1.0e6f
servo_D0.setMaxAcceleration(0.3f);
servo_D1.setMaxAcceleration(0.3f);
// variables to move the servo, this is just an example
float servo_input = 0.0f;
int servo_counter = 0; // define servo counter, this is an additional variable
// used to command the servo
const int loops_per_seconds = static_cast<int>(ceilf(1.0f / (0.001f * static_cast<float>(main_task_period_ms))));
// start timer
main_task_timer.start();
// this loop will run forever
while (true) {
main_task_timer.reset();
// --- code that runs every cycle at the start goes here ---
if (do_execute_main_task) {
// --- code that runs when the blue button was pressed goes here ---
// visual feedback that the main task is executed, setting this once would actually be enough
led1 = 1;
// enable the servos
if (!servo_D0.isEnabled())
servo_D0.enable();
if (!servo_D1.isEnabled())
servo_D1.enable();
// command the servos
servo_D0.setPulseWidth(servo_input);
servo_D1.setPulseWidth(servo_input);
// calculate inputs for the servos for the next cycle
if ((servo_input < 1.0f) && // constrain servo_input to be < 1.0f
(servo_counter % loops_per_seconds == 0) && // true if servo_counter is a multiple of loops_per_second
(servo_counter != 0)) // avoid servo_counter = 0
servo_input += 0.005f;
servo_counter++;
} else {
// the following code block gets executed only once
if (do_reset_all_once) {
do_reset_all_once = false;
// --- variables and objects that should be reset go here ---
// reset variables and objects
led1 = 0;
servo_D0.disable();
servo_D1.disable();
servo_input = 0.0f;
}
}
// toggling the user led
user_led = !user_led;
// --- code that runs every cycle at the end goes here ---
// print to the serial terminal
printf("Pulse width: %f \n", servo_input);
// read timer and make the main thread sleep for the remaining time span (non blocking)
int main_task_elapsed_time_ms = duration_cast<milliseconds>(main_task_timer.elapsed_time()).count();
if (main_task_period_ms - main_task_elapsed_time_ms < 0)
printf("Warning: Main task took longer than main_task_period_ms\n");
else
thread_sleep_for(main_task_period_ms - main_task_elapsed_time_ms);
}
}
void toggle_do_execute_main_fcn()
{
// toggle do_execute_main_task if the button was pressed
do_execute_main_task = !do_execute_main_task;
// set do_reset_all_once to true if do_execute_main_task changed from false to true
if (do_execute_main_task)
do_reset_all_once = true;
}