Skip to content

Commit 79c39f2

Browse files
author
Gonzalo de Pedro
committed
Changes to add IMU to andino firmware
Signed-off-by: Gonzalo de Pedro <[email protected]>
1 parent 9f7793d commit 79c39f2

File tree

8 files changed

+369
-139
lines changed

8 files changed

+369
-139
lines changed

Diff for: andino_firmware/README.md

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ Check `encoder_driver.h` and `motor_driver.h` files to check the expected pins f
88

99
## Installation
1010

11+
In Arduino IDE, go to `tools->Manage Libraries ...` and install:
12+
- "Adafruit BNO055"
13+
1114
Verify and Upload `andino_firmware.ino` to your arduino board.
1215

1316
## Description

Diff for: andino_firmware/platformio.ini

+6-5
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@
1313
platform = atmelavr
1414
framework = arduino
1515
monitor_speed = 57600
16-
17-
; Base configuration for build tools.
18-
[base_build]
19-
build_flags =
20-
-Wall -Wextra
16+
lib_deps =
17+
Wire
18+
SPI
19+
adafruit/Adafruit BNO055
20+
adafruit/Adafruit BusIO
21+
adafruit/Adafruit Unified Sensor
2122

2223
; Environment for Arduino Uno.
2324
[env:uno]

Diff for: andino_firmware/src/app.cpp

+111-101
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,13 @@
7171
#include "hw.h"
7272
#include "motor.h"
7373
#include "pid.h"
74+
#include "shell.h"
75+
76+
/*BNO055 Imu */
77+
#include <Wire.h>
78+
#include <Adafruit_Sensor.h>
79+
#include <Adafruit_BNO055.h>
80+
#include <utility/imumaths.h>
7481

7582
// TODO(jballoffet): Move this variables to a different module.
7683

@@ -79,22 +86,12 @@ unsigned long nextPID = andino::Constants::kPidPeriod;
7986

8087
long lastMotorCommand = andino::Constants::kAutoStopWindow;
8188

82-
// A pair of varibles to help parse serial commands
83-
int arg = 0;
84-
int index = 0;
85-
86-
// Variable to hold an input character
87-
char chr;
88-
89-
// Variable to hold the current single-character command
90-
char cmd;
91-
92-
// Character arrays to hold the first and second arguments
93-
char argv1[16];
94-
char argv2[16];
89+
bool HAS_IMU = true;
9590

9691
namespace andino {
9792

93+
Shell App::shell_;
94+
9895
Motor App::left_motor_(Hw::kLeftMotorEnableGpioPin, Hw::kLeftMotorForwardGpioPin,
9996
Hw::kLeftMotorBackwardGpioPin);
10097
Motor App::right_motor_(Hw::kRightMotorEnableGpioPin, Hw::kRightMotorForwardGpioPin,
@@ -108,6 +105,8 @@ PID App::left_pid_controller_(Constants::kPidKp, Constants::kPidKd, Constants::k
108105
PID App::right_pid_controller_(Constants::kPidKp, Constants::kPidKd, Constants::kPidKi,
109106
Constants::kPidKo, -Constants::kPwmMax, Constants::kPwmMax);
110107

108+
Adafruit_BNO055 App::bno_{55, BNO055_ADDRESS_A, &Wire};
109+
111110
void App::setup() {
112111
// Required by Arduino libraries to work.
113112
init();
@@ -123,47 +122,32 @@ void App::setup() {
123122

124123
left_pid_controller_.reset(left_encoder_.read());
125124
right_pid_controller_.reset(right_encoder_.read());
125+
126+
// Initialize command shell.
127+
shell_.init(Serial);
128+
shell_.set_default_callback(cmd_unknown_cb);
129+
shell_.register_command(Commands::kReadAnalogGpio, cmd_read_analog_gpio_cb);
130+
shell_.register_command(Commands::kReadDigitalGpio, cmd_read_digital_gpio_cb);
131+
shell_.register_command(Commands::kReadEncoders, cmd_read_encoders_cb);
132+
shell_.register_command(Commands::kReadHasImu, cmd_read_has_imu_cb);
133+
shell_.register_command(Commands::kReadEncodersAndImu, cmd_read_encoders_and_imu_cb);
134+
shell_.register_command(Commands::kResetEncoders, cmd_reset_encoders_cb);
135+
shell_.register_command(Commands::kSetMotorsSpeed, cmd_set_motors_speed_cb);
136+
shell_.register_command(Commands::kSetMotorsPwm, cmd_set_motors_pwm_cb);
137+
shell_.register_command(Commands::kSetPidsTuningGains, cmd_set_pid_tuning_gains_cb);
138+
/* Initialise the IMU sensor */
139+
if(!bno_.begin())
140+
{
141+
/* There was a problem detecting the BNO055 ... check your connections */
142+
Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
143+
HAS_IMU = false;
144+
}
145+
bno_.setExtCrystalUse(true);
126146
}
127147

128148
void App::loop() {
129-
while (Serial.available() > 0) {
130-
// Read the next character
131-
chr = Serial.read();
132-
133-
// Terminate a command with a CR
134-
if (chr == 13) {
135-
if (arg == 1)
136-
argv1[index] = 0;
137-
else if (arg == 2)
138-
argv2[index] = 0;
139-
run_command();
140-
reset_command();
141-
}
142-
// Use spaces to delimit parts of the command
143-
else if (chr == ' ') {
144-
// Step through the arguments
145-
if (arg == 0)
146-
arg = 1;
147-
else if (arg == 1) {
148-
argv1[index] = 0;
149-
arg = 2;
150-
index = 0;
151-
}
152-
continue;
153-
} else {
154-
if (arg == 0) {
155-
// The first arg is the single-letter command
156-
cmd = chr;
157-
} else if (arg == 1) {
158-
// Subsequent arguments can be more than one character
159-
argv1[index] = chr;
160-
index++;
161-
} else if (arg == 2) {
162-
argv2[index] = chr;
163-
index++;
164-
}
165-
}
166-
}
149+
// Process command prompt input.
150+
shell_.process_input();
167151

168152
// Run a PID calculation at the appropriate intervals
169153
if (millis() > nextPID) {
@@ -191,72 +175,89 @@ void App::loop() {
191175
}
192176
}
193177

194-
void App::reset_command() {
195-
cmd = 0;
196-
memset(argv1, 0, sizeof(argv1));
197-
memset(argv2, 0, sizeof(argv2));
198-
arg = 0;
199-
index = 0;
200-
}
178+
void App::cmd_unknown_cb(int, char**) { Serial.println("Unknown command."); }
201179

202-
void App::run_command() {
203-
switch (cmd) {
204-
case Commands::kReadAnalogGpio:
205-
cmd_read_analog_gpio(argv1, argv2);
206-
break;
207-
case Commands::kReadDigitalGpio:
208-
cmd_read_digital_gpio(argv1, argv2);
209-
break;
210-
case Commands::kReadEncoders:
211-
cmd_read_encoders(argv1, argv2);
212-
break;
213-
case Commands::kResetEncoders:
214-
cmd_reset_encoders(argv1, argv2);
215-
break;
216-
case Commands::kSetMotorsSpeed:
217-
cmd_set_motors_speed(argv1, argv2);
218-
break;
219-
case Commands::kSetMotorsPwm:
220-
cmd_set_motors_pwm(argv1, argv2);
221-
break;
222-
case Commands::kSetPidsTuningGains:
223-
cmd_set_pid_tuning_gains(argv1, argv2);
224-
break;
225-
default:
226-
cmd_unknown(argv1, argv2);
227-
break;
180+
void App::cmd_read_analog_gpio_cb(int argc, char** argv) {
181+
if (argc < 2) {
182+
return;
228183
}
229-
}
230-
231-
void App::cmd_unknown(const char*, const char*) { Serial.println("Unknown command."); }
232184

233-
void App::cmd_read_analog_gpio(const char* arg1, const char*) {
234-
const int pin = atoi(arg1);
185+
const int pin = atoi(argv[1]);
235186
Serial.println(analogRead(pin));
236187
}
237188

238-
void App::cmd_read_digital_gpio(const char* arg1, const char*) {
239-
const int pin = atoi(arg1);
189+
void App::cmd_read_digital_gpio_cb(int argc, char** argv) {
190+
if (argc < 2) {
191+
return;
192+
}
193+
194+
const int pin = atoi(argv[1]);
240195
Serial.println(digitalRead(pin));
241196
}
242197

243-
void App::cmd_read_encoders(const char*, const char*) {
198+
void App::cmd_read_encoders_cb(int, char**) {
244199
Serial.print(left_encoder_.read());
245200
Serial.print(" ");
246201
Serial.println(right_encoder_.read());
247202
}
248203

249-
void App::cmd_reset_encoders(const char*, const char*) {
204+
void App::cmd_read_has_imu_cb(int argc, char** argv) {
205+
Serial.println(HAS_IMU);
206+
}
207+
208+
void App::cmd_read_encoders_and_imu_cb(int argc, char** argv) {
209+
Serial.print(left_encoder_.read());
210+
Serial.print(" ");
211+
Serial.print(right_encoder_.read());
212+
Serial.print(" ");
213+
214+
// Quaternion data
215+
imu::Quaternion quat = bno_.getQuat();
216+
Serial.print(quat.x(), 4);
217+
Serial.print(" ");
218+
Serial.print(quat.y(), 4);
219+
Serial.print(" ");
220+
Serial.print(quat.z(), 4);
221+
Serial.print(" ");
222+
Serial.print(quat.w(), 4);
223+
Serial.print(" ");
224+
225+
/* Display the floating point data */
226+
imu::Vector<3> euler_angvel = bno_.getVector(Adafruit_BNO055::VECTOR_GYROSCOPE);
227+
Serial.print(euler_angvel.x());
228+
Serial.print(" ");
229+
Serial.print(euler_angvel.y());
230+
Serial.print(" ");
231+
Serial.print(euler_angvel.z());
232+
Serial.print(" ");
233+
234+
/* Display the floating point data */
235+
imu::Vector<3> euler_linearaccel = bno_.getVector(Adafruit_BNO055::VECTOR_LINEARACCEL);
236+
Serial.print(euler_linearaccel.x());
237+
Serial.print(" ");
238+
Serial.print(euler_linearaccel.y());
239+
Serial.print(" ");
240+
Serial.print(euler_linearaccel.z());
241+
Serial.print("\t\t");
242+
243+
Serial.println("OK");
244+
}
245+
246+
void App::cmd_reset_encoders_cb(int, char**) {
250247
left_encoder_.reset();
251248
right_encoder_.reset();
252249
left_pid_controller_.reset(left_encoder_.read());
253250
right_pid_controller_.reset(right_encoder_.read());
254251
Serial.println("OK");
255252
}
256253

257-
void App::cmd_set_motors_speed(const char* arg1, const char* arg2) {
258-
const int left_motor_speed = atoi(arg1);
259-
const int right_motor_speed = atoi(arg2);
254+
void App::cmd_set_motors_speed_cb(int argc, char** argv) {
255+
if (argc < 3) {
256+
return;
257+
}
258+
259+
const int left_motor_speed = atoi(argv[1]);
260+
const int right_motor_speed = atoi(argv[2]);
260261

261262
// Reset the auto stop timer.
262263
lastMotorCommand = millis();
@@ -279,9 +280,13 @@ void App::cmd_set_motors_speed(const char* arg1, const char* arg2) {
279280
Serial.println("OK");
280281
}
281282

282-
void App::cmd_set_motors_pwm(const char* arg1, const char* arg2) {
283-
const int left_motor_pwm = atoi(arg1);
284-
const int right_motor_pwm = atoi(arg2);
283+
void App::cmd_set_motors_pwm_cb(int argc, char** argv) {
284+
if (argc < 3) {
285+
return;
286+
}
287+
288+
const int left_motor_pwm = atoi(argv[1]);
289+
const int right_motor_pwm = atoi(argv[2]);
285290

286291
// Reset the auto stop timer.
287292
lastMotorCommand = millis();
@@ -295,15 +300,20 @@ void App::cmd_set_motors_pwm(const char* arg1, const char* arg2) {
295300
Serial.println("OK");
296301
}
297302

298-
void App::cmd_set_pid_tuning_gains(const char* arg1, const char*) {
303+
void App::cmd_set_pid_tuning_gains_cb(int argc, char** argv) {
304+
// TODO(jballoffet): Refactor to expect command multiple arguments.
305+
if (argc < 2) {
306+
return;
307+
}
308+
299309
static constexpr int kSizePidArgs{4};
300310
int i = 0;
301311
char arg[20];
302312
char* str;
303313
int pid_args[kSizePidArgs]{0, 0, 0, 0};
304314

305315
// Example: "u 30:20:10:50".
306-
strcpy(arg, arg1);
316+
strcpy(arg, argv[1]);
307317
char* p = arg;
308318
while ((str = strtok_r(p, ":", &p)) != NULL && i < kSizePidArgs) {
309319
pid_args[i] = atoi(str);

0 commit comments

Comments
 (0)