From ce6e7019e2bb9450906cf91009c6f3145b0aa160 Mon Sep 17 00:00:00 2001 From: Geir Ola Tvinnereim Date: Sun, 12 Jul 2026 13:46:03 +0200 Subject: [PATCH 1/6] add constants Formalizing radio protocol --- src/constants.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/constants.h diff --git a/src/constants.h b/src/constants.h new file mode 100644 index 0000000..b0f7248 --- /dev/null +++ b/src/constants.h @@ -0,0 +1,14 @@ +#pragma once + +struct RadioPacketChars { + char Armed; + char Pitch; + char Roll; + char Throttle; + char Yaw; + + constexpr RadioPacketChars() + : Armed('A'), Pitch('P'), Roll('R'), Throttle('T'), Yaw('Y') {} +}; + +constexpr RadioPacketChars DefaultRadioPacketChars{}; \ No newline at end of file From 5ca00efd8b4d2b956bafb0d75753b91151cf3b5e Mon Sep 17 00:00:00 2001 From: Geir Ola Tvinnereim Date: Sun, 12 Jul 2026 13:48:01 +0200 Subject: [PATCH 2/6] hand-controller: utilize radio protocol chore: update radio pkg doc --- src/hand-controller/README.md | 17 +++++++++++++++++ src/hand-controller/transmitter.cpp | 20 ++++++++++++-------- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/hand-controller/README.md b/src/hand-controller/README.md index c1a5dcd..dda3ca8 100644 --- a/src/hand-controller/README.md +++ b/src/hand-controller/README.md @@ -102,3 +102,20 @@ $$ ![img/display.jpg](../../img/display.jpg) +#### Radio communication + +We use a radio channel to send packets between the hand controller and flight controller. These packets contains control variables and setpoints. + +Packet Spec per byte: +| 0 | 1 ... 4 | 5 ... 8 | 9 ... 28 +---------------------------------------------------------------- +| packet type | system time | serial number | payload + +- Packet type = 1 is the first byte +- The following four bytes (int size) is the system time +- The following four bytes (int size) is the serial number, which is set to 0 + +The Payload is divided in two: +- The first four payload bytes (9, 10, 11, 12) is the integer value sent +- The following payload byte (13) is the name length +- The following payload byte (14) is the identifying char ('P', 'A', 'R', 'T' 'Y') \ No newline at end of file diff --git a/src/hand-controller/transmitter.cpp b/src/hand-controller/transmitter.cpp index e44a327..3798d43 100644 --- a/src/hand-controller/transmitter.cpp +++ b/src/hand-controller/transmitter.cpp @@ -1,10 +1,13 @@ #include "transmitter.h" +#include "../constants.h" #include "buttons.h" #include "handController.h" #include "orientation.h" #include "pins.h" #include +static RadioPacketChars radioPacketChars = DefaultRadioPacketChars; + /* // Packet Spec: // | 0 | 1 ... 4 | 5 ... 8 | 9 ... 28 @@ -30,7 +33,7 @@ static void sendValue(char name, int value) { uint8_t buf[32]; int i = 0; - // Packet type value + // Packet type value (first byte) buf[i++] = 0x01; // Timestamp (4 bytes) @@ -48,8 +51,9 @@ static void sendValue(char name, int value) { i += 4; // Name length - buf[i++] = 1; - memcpy(&buf[i], &name, 1); + buf[i++] = 1; // 13th byte + // Name + memcpy(&buf[i], &name, 1); // 14th byte i += 1; // Send the packet @@ -57,9 +61,9 @@ static void sendValue(char name, int value) { } void TransmittData() { - sendValue('P', GetPitch()); - sendValue('A', IsArmed()); - sendValue('R', GetRoll()); - sendValue('T', GetThrottle()); - sendValue('Y', GetYaw()); + sendValue(radioPacketChars.Pitch, GetPitch()); + sendValue(radioPacketChars.Armed, IsArmed()); + sendValue(radioPacketChars.Roll, GetRoll()); + sendValue(radioPacketChars.Throttle, GetThrottle()); + sendValue(radioPacketChars.Yaw, GetYaw()); } From e20e996a2be62a8db7cc4f9749d08144ee5c03da Mon Sep 17 00:00:00 2001 From: Geir Ola Tvinnereim Date: Sun, 12 Jul 2026 13:48:36 +0200 Subject: [PATCH 3/6] utilities: Share Armed visualization between modules --- src/flight-controller/view.cpp | 3 +++ src/hand-controller/view.cpp | 24 ++---------------------- src/utilites.cpp | 23 +++++++++++++++++++++++ src/utilities.h | 4 ++++ 4 files changed, 32 insertions(+), 22 deletions(-) create mode 100644 src/utilites.cpp create mode 100644 src/utilities.h diff --git a/src/flight-controller/view.cpp b/src/flight-controller/view.cpp index 4b5d64c..ff02954 100644 --- a/src/flight-controller/view.cpp +++ b/src/flight-controller/view.cpp @@ -1,5 +1,7 @@ #include "view.h" +#include "../utilities.h" #include "flightController.h" +#include "receiver.h" #include #include @@ -44,5 +46,6 @@ void UpdateView() { Image ledDisplay = Image(LED_DISPLAY_SIZE, LED_DISPLAY_SIZE); viewBatteryLevel(ledDisplay); + DisplayArmed(IsDroneArmed(), ledDisplay); uBit.display.print(ledDisplay); } diff --git a/src/hand-controller/view.cpp b/src/hand-controller/view.cpp index be83df1..d90cab2 100644 --- a/src/hand-controller/view.cpp +++ b/src/hand-controller/view.cpp @@ -1,4 +1,5 @@ #include "view.h" +#include "../utilities.h" #include "buttons.h" #include "handController.h" #include "orientation.h" @@ -8,27 +9,6 @@ // MicroBit display const uint16_t LED_DISPLAY_SIZE = 5; const int LED_ON = 255; -int pulseDirection = 15; -int armedPulse = 0; - -static void updatePulse() { - armedPulse += pulseDirection; - - if (armedPulse == 255) { - pulseDirection = -15; - } else if (armedPulse == 0) { - pulseDirection = 15; - } -} - -static void displayArmed(Image &ledDisplay) { - if (IsArmed()) { - updatePulse(); - ledDisplay.setPixelValue(0, 0, armedPulse); - } else { - armedPulse = 0; - } -} static void displayThrottle(Image &ledDisplay) { int throttle = GetThrottle(); @@ -59,7 +39,7 @@ void UpdateDisplay() { uBit.display.clear(); Image ledDisplay = Image(LED_DISPLAY_SIZE, LED_DISPLAY_SIZE); - displayArmed(ledDisplay); + DisplayArmed(IsArmed(), ledDisplay); displayThrottle(ledDisplay); displayPitchRoll(ledDisplay); displayYaw(ledDisplay); diff --git a/src/utilites.cpp b/src/utilites.cpp new file mode 100644 index 0000000..aaf9934 --- /dev/null +++ b/src/utilites.cpp @@ -0,0 +1,23 @@ +#include "utilities.h" + +static int pulseDirection = 15; +static int armedPulse = 0; + +static void updatePulse() { + armedPulse += pulseDirection; + + if (armedPulse == 255) { + pulseDirection = -15; + } else if (armedPulse == 0) { + pulseDirection = 15; + } +} + +void DisplayArmed(bool isArmed, Image &ledDisplay) { + if (isArmed) { + updatePulse(); + ledDisplay.setPixelValue(0, 0, armedPulse); + } else { + armedPulse = 0; + } +} \ No newline at end of file diff --git a/src/utilities.h b/src/utilities.h new file mode 100644 index 0000000..6cf22f5 --- /dev/null +++ b/src/utilities.h @@ -0,0 +1,4 @@ +#pragma once +#include + +void DisplayArmed(bool isArmed, Image &ledDisplay); \ No newline at end of file From a5964760ba678c886f5906cc51d4b4dfab8e479e Mon Sep 17 00:00:00 2001 From: Geir Ola Tvinnereim Date: Sun, 12 Jul 2026 13:49:26 +0200 Subject: [PATCH 4/6] flight-controller: add receiver module --- src/flight-controller/receiver.cpp | 46 ++++++++++++++++++++++++++++++ src/flight-controller/receiver.h | 4 +++ 2 files changed, 50 insertions(+) create mode 100644 src/flight-controller/receiver.cpp create mode 100644 src/flight-controller/receiver.h diff --git a/src/flight-controller/receiver.cpp b/src/flight-controller/receiver.cpp new file mode 100644 index 0000000..5d5e873 --- /dev/null +++ b/src/flight-controller/receiver.cpp @@ -0,0 +1,46 @@ +#include "receiver.h" +#include "../constants.h" +#include "flightController.h" + +#include + +static RadioPacketChars radioPacketChars = DefaultRadioPacketChars; +const uint8_t PACKET_CHAR_INDEX = 14; +const uint8_t PACKET_VALUE_INDEX = 9; + +static uint8_t packet[32]; + +// Reference variables +static int pitch = 0; +static int roll = 0; +static int throttle = 0; +static int yaw = 0; +static bool armed = false; + +static void readRadioPacket() { + uBit.radio.datagram.recv(packet, sizeof(packet)); + char packetChar = packet[PACKET_CHAR_INDEX]; + + if (packetChar == radioPacketChars.Pitch) { + memcpy(&pitch, &packet[PACKET_VALUE_INDEX], 4); + } else if (packetChar == radioPacketChars.Armed) { + int32_t value = 0; + memcpy(&value, &packet[PACKET_VALUE_INDEX], 4); + armed = value != 0; + } else if (packetChar == radioPacketChars.Roll) { + memcpy(&roll, &packet[PACKET_VALUE_INDEX], 4); + } else if (packetChar == radioPacketChars.Throttle) { + memcpy(&throttle, &packet[PACKET_VALUE_INDEX], 4); + } else if (packetChar == radioPacketChars.Yaw) { + memcpy(&yaw, &packet[PACKET_VALUE_INDEX], 4); + } +} + +void FlushRadioBuffer() { + // sizeof returns the byte size of struct + for (unsigned int i = 0; i < sizeof(radioPacketChars); i++) { + readRadioPacket(); + } +} + +bool IsDroneArmed() { return armed; } diff --git a/src/flight-controller/receiver.h b/src/flight-controller/receiver.h new file mode 100644 index 0000000..e69c41a --- /dev/null +++ b/src/flight-controller/receiver.h @@ -0,0 +1,4 @@ +#pragma once + +bool IsDroneArmed(); +void FlushRadioBuffer(); \ No newline at end of file From 1aa6bd2862fe5562146396c6d0629cde6422ef97 Mon Sep 17 00:00:00 2001 From: Geir Ola Tvinnereim Date: Sun, 12 Jul 2026 13:49:31 +0200 Subject: [PATCH 5/6] Update main.cpp --- src/main.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index d1335a9..9a27852 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -25,8 +25,9 @@ static void FlightController() { while (true) { SetBatteryInfo(); + FlushRadioBuffer(); UpdateView(); - uBit.sleep(1000); + uBit.sleep(100); } } @@ -47,6 +48,6 @@ static void HandController() { int main() { uBit.init(); initRadio(); - HandController(); + FlightController(); return 0; } \ No newline at end of file From 10931d2505f93cc5926090e4018196436fbce750 Mon Sep 17 00:00:00 2001 From: Geir Ola Tvinnereim Date: Sun, 12 Jul 2026 13:54:55 +0200 Subject: [PATCH 6/6] Update flightController.h --- src/flight-controller/flightController.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/flight-controller/flightController.h b/src/flight-controller/flightController.h index c83d2d8..85e02e7 100644 --- a/src/flight-controller/flightController.h +++ b/src/flight-controller/flightController.h @@ -1,5 +1,6 @@ #pragma once #include "battery.h" +#include "receiver.h" #include "servoController.h" #include "ultrasonicSensor.h" #include "view.h" @@ -15,7 +16,7 @@ #define MICROBIT_UBIT_AS_STATIC_OBJECT -enum class State : uint16_t { CALIBRATING, CHARGING, DISARMED, ARMED, PANIC }; +enum class State : uint8_t { CALIBRATING, CHARGING, DISARMED, ARMED, PANIC }; struct FlightState { int altitude;