diff options
author | UnavailableDev <69792062+UnavailableDev@users.noreply.github.com> | 2023-05-20 22:08:08 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-20 22:08:08 +0200 |
commit | ac1884bec264d08dc5cc58d1cda24e20734c9205 (patch) | |
tree | 6c71a74d2b3d4af7d183b0823b15bba601a37bb5 /zumo | |
parent | 7a18524a8b97deaafcd93be14e56ce308fe4583c (diff) | |
parent | ba026d8229744a01818d38552ec7271e689d19eb (diff) |
Merge branch 'lonkaars:master' into master
Diffstat (limited to 'zumo')
-rw-r--r-- | zumo/.gitignore | 1 | ||||
-rw-r--r-- | zumo/main.cpp | 13 | ||||
-rw-r--r-- | zumo/makefile | 43 | ||||
-rw-r--r-- | zumo/pid.cpp | 52 | ||||
-rw-r--r-- | zumo/pid.h | 21 | ||||
-rw-r--r-- | zumo/pidtest.cpp | 18 | ||||
-rw-r--r-- | zumo/pidtest.mk | 21 | ||||
-rw-r--r-- | zumo/protocol.cpp | 39 | ||||
-rw-r--r-- | zumo/protocol.h | 35 | ||||
-rw-r--r-- | zumo/zumo.ino | 34 | ||||
-rw-r--r-- | zumo/zumo.mk | 78 |
11 files changed, 298 insertions, 57 deletions
diff --git a/zumo/.gitignore b/zumo/.gitignore index d3e1535..888e905 100644 --- a/zumo/.gitignore +++ b/zumo/.gitignore @@ -3,3 +3,4 @@ main *.hex compile_commands.json .cache +pidtest diff --git a/zumo/main.cpp b/zumo/main.cpp deleted file mode 100644 index 23d13db..0000000 --- a/zumo/main.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include <Zumo32U4.h> -#include <Arduino.h> -#include <Wire.h> - -void setup() { -} - -void loop() { - ledRed(1); - delay(1000); - ledRed(0); - delay(1000); -} diff --git a/zumo/makefile b/zumo/makefile index c388a28..08c01d7 100644 --- a/zumo/makefile +++ b/zumo/makefile @@ -2,33 +2,58 @@ PORT = /dev/ttyUSB0 C++ = avr-g++ CC = avr-gcc -LD = avr-ld +LD = avr-gcc RM = rm -f MCU = atmega32u4 TARGET = main SRCS += main.cpp -CFLAGS += -mcall-prologues -CFLAGS += -mmcu=$(MCU) -CFLAGS += -Os -CFLAGS += -g -CFLAGS += -Wl,-gc-sections -CFLAGS += -Wl,-relax +C_CPP_FLAGS += -mmcu=$(MCU) +C_CPP_FLAGS += -Wl,-gc-sections +SHARED_FLAGS += -Os + +C_CPP_FLAGS += -mcall-prologues +C_CPP_FLAGS += -g +C_CPP_FLAGS += -Wl,-relax +C_CPP_FLAGS += -MMD +C_CPP_FLAGS += -ffunction-sections +C_CPP_FLAGS += -fdata-sections + +LFLAGS += -flto +LFLAGS += -fuse-linker-plugin +LFLAGS += -lc -lm +# LFLAGS += -L/usr/avr/lib/avr5/ -L/usr/lib/gcc/avr/12.2.0/avr5 -lgcc -lm -lc -latmega32u4 +# LFLAGS += -flto -fuse-linker-plugin -mmcu=atmega32u4 -Wl,--gc-sections -Os -lc -lm + + +CFLAGS += -fno-fat-lto-objects +# CFLAGS += -std=gnu11 + +CPPFLAGS += -fpermissive +CPPFLAGS += -fno-exceptions +CPPFLAGS += -fno-threadsafe-statics +CPPFLAGS += -fno-devirtualize +# CPPFLAGS += -std=gnu++11 + + +LFLAGS += $(SHARED_FLAGS) +CFLAGS += $(C_CPP_FLAGS) $(SHARED_FLAGS) +CPPFLAGS += $(C_CPP_FLAGS) $(SHARED_FLAGS) include zumo.mk OBJS := $(patsubst %.c,%.o, $(SRCS)) OBJS := $(patsubst %.cpp,%.o, $(OBJS)) -MAKEFLAGS += -j4 +MAKEFLAGS += -j .PHONY: all clean flash all: $(TARGET).hex %.o: %.cpp - $(C++) $(CFLAGS) -o $@ -c $< + $(C++) $(CPPFLAGS) -o $@ -c $< %.o: %.c $(CC) $(CFLAGS) -o $@ -c $< diff --git a/zumo/pid.cpp b/zumo/pid.cpp new file mode 100644 index 0000000..7c1cbda --- /dev/null +++ b/zumo/pid.cpp @@ -0,0 +1,52 @@ +#include "pid.h" + +PID::PID(float P, float I, float D) { + A0 = P + I * dt; + A1 = -P; + A0d = D / dt; + A1d = -2 * D / dt; + A2d = D / dt; + tau = D / (P * N); + alpha = dt / (2 * tau); + reset(0.0); +} + +// https://en.wikipedia.org/wiki/PID_controller#Pseudocode +float PID::iter(float target) { + error[2] = error[1]; + error[1] = error[0]; + error[0] = target - output; + + output = output + A0 * error[0] + A1 * error[1]; + + d1 = d0; + d0 = A0d * error[0] + A1d * error[1] + A2d * error[2]; + fd1 = fd0; + fd0 = ((alpha) / (alpha + 1)) * (d0 + d1) - ((alpha - 1) / (alpha + 1)) * fd1; + output = output + fd0; + + if (output < -1) output = -1; + if (output > 1) output = 1; + return output; +} + +void PID::reset(float value) { + error[0] = 0.0; + error[1] = 0.0; + error[2] = 0.0; + d0 = 0; + d1 = 0; + fd0 = 0; + fd1 = 0; + output = value; +} + +PID speed_pid = PID(); +PID steer_pid = PID(); +PID speed_mod_pid = PID(); +void apply_pid(dui_state_t* target, dui_state_t* current) { + current->speed = speed_pid.iter(target->speed); + current->steer = steer_pid.iter(target->steer); + current->speed_mod = speed_mod_pid.iter(target->speed_mod); +} + diff --git a/zumo/pid.h b/zumo/pid.h new file mode 100644 index 0000000..beb73ac --- /dev/null +++ b/zumo/pid.h @@ -0,0 +1,21 @@ +#pragma once + +#include "protocol.h" + +class PID { +private: + float A0, A1, A0d, A1d, A2d, tau, alpha, d0, d1, fd0, fd1; + float error[3]; + float output; + const float dt = 1.0; + const float N = 10.0; + +public: + PID(float P = -0.02, float I = 0.13, float D = -300.0); + float iter(float target); + void reset(float value); +}; + +/** @brief edit `current` to be closer to `target` using PID controllers */ +void apply_pid(dui_state_t* target, dui_state_t* current); + diff --git a/zumo/pidtest.cpp b/zumo/pidtest.cpp new file mode 100644 index 0000000..b9ce50b --- /dev/null +++ b/zumo/pidtest.cpp @@ -0,0 +1,18 @@ +#include <cstdio> +#include <random> + +#include "pid.h" + +int main() { + float P, I, D; + P = -0.02; + I = 0.13; + D = -300; + PID test(P, I, D); + test.reset(0.0); + + fprintf(stderr, "P: %.3f :: I: %.3f :: D: %.3f\n", P, I, D); + for (unsigned int i = 0; i < 100; i++) { + printf("%2.8f\n", test.iter(i < 50 ? 1.0 : 0.0)); + } +} diff --git a/zumo/pidtest.mk b/zumo/pidtest.mk new file mode 100644 index 0000000..5ffe1e1 --- /dev/null +++ b/zumo/pidtest.mk @@ -0,0 +1,21 @@ +CPP = g++ +LD = g++ +RM = rm -f +CFLAGS = +LFLAGS = +TARGET = pidtest + +SRCS := pidtest.cpp pid.cpp +OBJS := pidtest.o pid.o + +all: pidtest + +%.o: %.cpp + $(CPP) -c $(CFLAGS) $< -o $@ + +$(TARGET): $(OBJS) + $(LD) $^ $(LFLAGS) -o $@ + +clean: + $(RM) $(TARGET) $(OBJS) + diff --git a/zumo/protocol.cpp b/zumo/protocol.cpp new file mode 100644 index 0000000..fea8a00 --- /dev/null +++ b/zumo/protocol.cpp @@ -0,0 +1,39 @@ +#include <Zumo32U4Motors.h> + +#include "protocol.h" + +#define DUI_SPEED_MOD 96.0f +#define DUI_MOTOR_DIFF 0.6f + +#define DUI_CMD_NULL 0x00 +#define DUI_CMD_SIGN_START 0x01 +#define DUI_CMD_SIGN_END 0x0f +#define DUI_CMD_STEER_START 0x10 +#define DUI_CMD_STEER_END 0x1f +#define DUI_CMD_SPEED_START 0x20 +#define DUI_CMD_SPEED_END 0xff + +void handle_cmd(unsigned char cmd, dui_state_t *state) { + if (cmd == DUI_CMD_NULL) return; + else if (DUI_CMD_SIGN_START <= cmd && cmd <= DUI_CMD_SIGN_END) { + state->current_sign = (dui_e_sign) (cmd - DUI_CMD_SIGN_START); + } else if (DUI_CMD_STEER_START <= cmd && cmd <= DUI_CMD_STEER_END) { + state->steer = (float) (cmd - DUI_CMD_STEER_START) / (float) (DUI_CMD_STEER_END - DUI_CMD_STEER_START); + } else if (DUI_CMD_SPEED_START <= cmd && cmd <= DUI_CMD_SPEED_END) { + state->speed = ((float) (cmd - DUI_CMD_SPEED_START) / (float) (DUI_CMD_SPEED_START - DUI_CMD_SPEED_END) * (float) 2 - (float) 1); + } +} + +void apply_state(dui_state_t *state) { + float motor_l = 0.5f * state->speed * (+1.f * state->steer * DUI_MOTOR_DIFF - DUI_MOTOR_DIFF + 2) * state->speed_mod * DUI_SPEED_MOD; + float motor_r = 0.5f * state->speed * (-1.f * state->steer * DUI_MOTOR_DIFF - DUI_MOTOR_DIFF + 2) * state->speed_mod * DUI_SPEED_MOD; + + Zumo32U4Motors::setLeftSpeed((int16_t) motor_l); + Zumo32U4Motors::setRightSpeed((int16_t) motor_r); + + // TODO: print sign on OLED screen +} + +unsigned char uart_read() { + return 0x00; +} diff --git a/zumo/protocol.h b/zumo/protocol.h new file mode 100644 index 0000000..662a5ce --- /dev/null +++ b/zumo/protocol.h @@ -0,0 +1,35 @@ +#pragma once + +typedef enum { + DUI_CMD_NULL, + DUI_CMD_SIGN, + DUI_CMD_SPEED, + DUI_CMD_STEER, +} dui_e_cmd; + +typedef enum { + DUI_SIGN_NONE, /** @brief no sign */ + DUI_SIGN_STOP, /** @brief stop (set speed to 0) */ + DUI_SIGN_LEFT, /** @brief turn left (set steer to -1) */ + DUI_SIGN_RIGHT, /** @brief turn right (set steer to +1) */ + DUI_SIGN_SPEED_LIMIT_LOW, /** @brief slow down (speed limit 0.5) */ + DUI_SIGN_SPEED_LIMIT_HIGH, /** @brief full speed (speed limit 1.0) */ + DUI_SIGN_LIGHT_STOP, /** @brief traffic light red (set speed to 0) */ + DUI_SIGN_LIGHT_FLOOR_IT, /** @brief traffic light orange (set speed to 2 temporarily) */ + DUI_SIGN_LIGHT_GO, /** @brief traffic light green (keep current speed) */ +} dui_e_sign; + +typedef struct { + float steer; /** @brief steer value (-1 is left, +1 is right) */ + float speed; /** @brief speed (0-15) */ + dui_e_sign current_sign; /** @brief last seen sign */ + float speed_mod; /** @brief global speed multiplier */ +} dui_state_t; + +/** @brief non blocking read byte */ +unsigned char uart_read(); +/** @brief read and apply cmd to state */ +void handle_cmd(unsigned char cmd, dui_state_t *state); +/** @brief apply state to motors */ +void apply_state(dui_state_t* state); + diff --git a/zumo/zumo.ino b/zumo/zumo.ino new file mode 100644 index 0000000..f59bd36 --- /dev/null +++ b/zumo/zumo.ino @@ -0,0 +1,34 @@ +#include <Zumo32U4.h> +#include <Arduino.h> +#include <Wire.h> + +#include "protocol.h" +#include "pid.h" + +dui_state_t g_dui_target_state = { + .steer = 1.0f, + .speed = 1.0f, + .current_sign = DUI_SIGN_NONE, + .speed_mod = 1.f, +}; +dui_state_t g_dui_current_state = { + .steer = 0.f, + .speed = 1.f, + .current_sign = DUI_SIGN_NONE, + .speed_mod = 1.f, +}; + +void setup() { +} + +void loop() { + unsigned char cmd = 0x00; + while ((cmd = uart_read())) + handle_cmd(cmd, &g_dui_target_state); + + apply_pid(&g_dui_target_state, &g_dui_current_state); + + apply_state(&g_dui_current_state); + + delay(10); +} diff --git a/zumo/zumo.mk b/zumo/zumo.mk index 3645513..f5ab84b 100644 --- a/zumo/zumo.mk +++ b/zumo/zumo.mk @@ -1,31 +1,39 @@ -CFLAGS += -DF_CPU=16000000 -CFLAGS += -I./lib/zumo-32u4-arduino-library/src -CFLAGS += -I./lib/fastgpio-arduino -CFLAGS += -I./lib/pushbutton-arduino -CFLAGS += -I./lib/usb-pause-arduino -CFLAGS += -I./lib/pololu-buzzer-arduino/src -CFLAGS += -I./lib/pololu-hd44780-arduino -CFLAGS += -I./lib/pololu-menu-arduino/src -CFLAGS += -I./lib/pololu-oled-arduino/src -CFLAGS += -I./lib/ArduinoCore-avr/cores/arduino -CFLAGS += -I./lib/ArduinoCore-avr/libraries/HID/src -CFLAGS += -I./lib/ArduinoCore-avr/libraries/SoftwareSerial/src -CFLAGS += -I./lib/ArduinoCore-avr/libraries/SPI/src -CFLAGS += -I./lib/ArduinoCore-avr/libraries/EEPROM/src -CFLAGS += -I./lib/ArduinoCore-avr/libraries/Wire/src -CFLAGS += -I./lib/ArduinoCore-avr/variants/circuitplay32u4 +C_CPP_FLAGS += -DF_CPU=16000000L +C_CPP_FLAGS += -D__PROG_TYPES_COMPAT__ +C_CPP_FLAGS += -DARDUINO=1819 +C_CPP_FLAGS += -DARDUINO_AVR_LEONARDO +C_CPP_FLAGS += -DARDUINO_ARCH_AVR +C_CPP_FLAGS += -DARDUINO_BOARD='"AVR_LEONARDO"' +C_CPP_FLAGS += -DARDUINO_VARIANT='"leonardo"' +C_CPP_FLAGS += -DUSB_VID=0x2341 +C_CPP_FLAGS += -DUSB_PID=0x8036 +C_CPP_FLAGS += -DUSB_PRODUCT='"Arduino Leonardo"' +C_CPP_FLAGS += -DUSB_MANUFACTURER='"Unknown"' -CFLAGS += -L/usr/avr/lib/avr5/ -L/usr/lib/gcc/avr/12.2.0/avr5 -lgcc -lm -lc -latmega32u4 -LFLAGS += -L/usr/avr/lib/avr5/ -L/usr/lib/gcc/avr/12.2.0/avr5 -lgcc -lm -lc -latmega32u4 +C_CPP_FLAGS += -I./lib/zumo-32u4-arduino-library/src +C_CPP_FLAGS += -I./lib/fastgpio-arduino +C_CPP_FLAGS += -I./lib/pushbutton-arduino +C_CPP_FLAGS += -I./lib/usb-pause-arduino +C_CPP_FLAGS += -I./lib/pololu-buzzer-arduino/src +C_CPP_FLAGS += -I./lib/pololu-hd44780-arduino +C_CPP_FLAGS += -I./lib/pololu-menu-arduino/src +C_CPP_FLAGS += -I./lib/pololu-oled-arduino/src +C_CPP_FLAGS += -I./lib/ArduinoCore-avr/cores/arduino +C_CPP_FLAGS += -I./lib/ArduinoCore-avr/libraries/HID/src +C_CPP_FLAGS += -I./lib/ArduinoCore-avr/libraries/SoftwareSerial/src +C_CPP_FLAGS += -I./lib/ArduinoCore-avr/libraries/SPI/src +C_CPP_FLAGS += -I./lib/ArduinoCore-avr/libraries/EEPROM/src +C_CPP_FLAGS += -I./lib/ArduinoCore-avr/libraries/Wire/src +C_CPP_FLAGS += -I./lib/ArduinoCore-avr/variants/leonardo -LIBS += lib/ArduinoCore-avr/cores/arduino/PluggableUSB.cpp +# LIBS += lib/ArduinoCore-avr/cores/arduino/PluggableUSB.cpp LIBS += lib/ArduinoCore-avr/cores/arduino/CDC.cpp LIBS += lib/ArduinoCore-avr/cores/arduino/HardwareSerial.cpp LIBS += lib/ArduinoCore-avr/cores/arduino/USBCore.cpp -# LIBS += lib/ArduinoCore-avr/cores/arduino/HardwareSerial0.cpp -# LIBS += lib/ArduinoCore-avr/cores/arduino/HardwareSerial1.cpp -# LIBS += lib/ArduinoCore-avr/cores/arduino/HardwareSerial2.cpp -# LIBS += lib/ArduinoCore-avr/cores/arduino/HardwareSerial3.cpp +LIBS += lib/ArduinoCore-avr/cores/arduino/HardwareSerial0.cpp +LIBS += lib/ArduinoCore-avr/cores/arduino/HardwareSerial1.cpp +LIBS += lib/ArduinoCore-avr/cores/arduino/HardwareSerial2.cpp +LIBS += lib/ArduinoCore-avr/cores/arduino/HardwareSerial3.cpp LIBS += lib/ArduinoCore-avr/cores/arduino/IPAddress.cpp LIBS += lib/ArduinoCore-avr/cores/arduino/Print.cpp LIBS += lib/ArduinoCore-avr/cores/arduino/Stream.cpp @@ -34,10 +42,20 @@ LIBS += lib/ArduinoCore-avr/cores/arduino/WString.cpp LIBS += lib/ArduinoCore-avr/cores/arduino/abi.cpp LIBS += lib/ArduinoCore-avr/cores/arduino/main.cpp LIBS += lib/ArduinoCore-avr/cores/arduino/new.cpp -LIBS += lib/ArduinoCore-avr/libraries/HID/src/HID.cpp -LIBS += lib/ArduinoCore-avr/libraries/SPI/src/SPI.cpp +# LIBS += lib/ArduinoCore-avr/libraries/HID/src/HID.cpp +# LIBS += lib/ArduinoCore-avr/libraries/SPI/src/SPI.cpp # LIBS += lib/ArduinoCore-avr/libraries/SoftwareSerial/src/SoftwareSerial.cpp LIBS += lib/ArduinoCore-avr/libraries/Wire/src/Wire.cpp +LIBS += lib/ArduinoCore-avr/cores/arduino/WInterrupts.c +LIBS += lib/ArduinoCore-avr/cores/arduino/hooks.c +LIBS += lib/ArduinoCore-avr/cores/arduino/wiring_shift.c +LIBS += lib/ArduinoCore-avr/cores/arduino/wiring_digital.c +LIBS += lib/ArduinoCore-avr/cores/arduino/wiring_analog.c +LIBS += lib/ArduinoCore-avr/cores/arduino/wiring_pulse.c +LIBS += lib/ArduinoCore-avr/cores/arduino/wiring.c +LIBS += lib/ArduinoCore-avr/cores/arduino/Tone.cpp +# LIBS += lib/ArduinoCore-avr/libraries/Wire/src/utility/twi.c + LIBS += lib/pololu-buzzer-arduino/src/PololuBuzzer.cpp LIBS += lib/pushbutton-arduino/Pushbutton.cpp LIBS += lib/zumo-32u4-arduino-library/src/QTRSensors.cpp @@ -50,16 +68,6 @@ LIBS += lib/usb-pause-arduino/USBPause.cpp LIBS += lib/pololu-hd44780-arduino/PololuHD44780.cpp LIBS += lib/fastgpio-arduino/FastGPIO.cpp LIBS += lib/pololu-oled-arduino/src/font.cpp -# LIBS += lib/ArduinoCore-avr/cores/arduino/Tone.cpp -# LIBS += lib/ArduinoCore-avr/libraries/Wire/src/utility/twi.c - -LIBS += lib/ArduinoCore-avr/cores/arduino/WInterrupts.c -LIBS += lib/ArduinoCore-avr/cores/arduino/hooks.c -LIBS += lib/ArduinoCore-avr/cores/arduino/wiring_shift.c -LIBS += lib/ArduinoCore-avr/cores/arduino/wiring_digital.c -LIBS += lib/ArduinoCore-avr/cores/arduino/wiring_analog.c -# LIBS += lib/ArduinoCore-avr/cores/arduino/wiring_pulse.c -LIBS += lib/ArduinoCore-avr/cores/arduino/wiring.c SRCS += $(LIBS) |