Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions examples/CPU_Temp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# CPU Temperature Example

This is the simplest example and a good starting point for a new node. It reads the STM32's internal temperature sensor and ADC pins, then broadcasts a DroneCAN `BatteryInfo` message at 10Hz containing:

- `voltage` — raw ADC reading from PA1
- `current` — raw ADC reading from PA0
- `temperature` — MCU core temperature in degrees Celsius

It also demonstrates reading and writing parameters via `dronecan.getParameter()` and `dronecan.setParameter()`.

## Dependencies

No extra libraries required. Uses the STM32 internal ADC (`AVREF`, `ATEMP`) which is available on all supported boards.
38 changes: 1 addition & 37 deletions examples/CPU_Temp/main.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@

/*
API version v1.3
*/

#include <Arduino.h>
#include <dronecan.h>
#include <IWatchdog.h>
#include <app.h>
#include <vector>
#include <simple_dronecanmessages.h>

// set up your parameters here with default values. NODEID should be kept
std::vector<DroneCAN::parameter> custom_parameters = {
Expand All @@ -20,40 +11,13 @@ DroneCAN dronecan;

uint32_t looptime = 0;

/*
This function is called when we receive a CAN message, and it's accepted by the shouldAcceptTransfer function.
We need to do boiler plate code in here to handle parameter updates and so on, but you can also write code to interact with sent messages here.
*/
static void onTransferReceived(CanardInstance *ins, CanardRxTransfer *transfer)
{
DroneCANonTransferReceived(dronecan, ins, transfer);
}

/*
For this function, we need to make sure any messages we want to receive follow the following format with
UAVCAN_EQUIPMENT_AHRS_MAGNETICFIELDSTRENGTH_ID as an example
*/
static bool shouldAcceptTransfer(const CanardInstance *ins,
uint64_t *out_data_type_signature,
uint16_t data_type_id,
CanardTransferType transfer_type,
uint8_t source_node_id)

{
return false || DroneCANshouldAcceptTransfer(ins, out_data_type_signature, data_type_id, transfer_type, source_node_id);
}

void setup()
{
// the following block of code should always run first. Adjust it at your own peril!
app_setup();
IWatchdog.begin(2000000);
IWatchdog.begin(2000000);
Serial.begin(115200);
dronecan.version_major = 1;
dronecan.version_minor = 0;
dronecan.init(
onTransferReceived,
shouldAcceptTransfer,
custom_parameters,
"Beyond Robotix Node"
);
Expand Down
14 changes: 12 additions & 2 deletions examples/HC_SR04/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
# HC SR04 Rangefinder
# HC-SR04 Rangefinder

Uses this library:
Reads distance from an HC-SR04 ultrasonic sensor and broadcasts it as a DroneCAN `RangeSensor` measurement at 10Hz.

The sensor is wired to:
- Trigger: PA8
- Echo: PA9

## Dependencies

Install the HC-SR04 Arduino library by Martinsos:
https://github.com/Martinsos/arduino-lib-hc-sr04

Download the zip and place the unzipped folder in the `lib` directory of your project. Make sure there are no nested folders inside (this can happen when unzipping from GitHub).

Alternatively, install it via the PlatformIO library manager.
37 changes: 1 addition & 36 deletions examples/HC_SR04/main.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@

/*
API version v1.3
*/

#include <Arduino.h>
#include <dronecan.h>
#include <IWatchdog.h>
#include <app.h>
#include <vector>
#include <HCSR04.h>

std::vector<DroneCAN::parameter> custom_parameters = {
Expand All @@ -18,29 +10,6 @@ DroneCAN dronecan;

uint32_t looptime = 0;

/*
This function is called when we receive a CAN message, and it's accepted by the shouldAcceptTransfer function.
We need to do boiler plate code in here to handle parameter updates and so on, but you can also write code to interact with sent messages here.
*/
static void onTransferReceived(CanardInstance *ins, CanardRxTransfer *transfer)
{
DroneCANonTransferReceived(dronecan, ins, transfer);
}

/*
For this function, we need to make sure any messages we want to receive follow the following format with
UAVCAN_EQUIPMENT_AHRS_MAGNETICFIELDSTRENGTH_ID as an example
*/
static bool shouldAcceptTransfer(const CanardInstance *ins,
uint64_t *out_data_type_signature,
uint16_t data_type_id,
CanardTransferType transfer_type,
uint8_t source_node_id)

{
return false || DroneCANshouldAcceptTransfer(ins, out_data_type_signature, data_type_id, transfer_type, source_node_id);
}

const byte triggerPin = PA8;
const byte echoPin = PA9;
UltraSonicDistanceSensor distanceSensor(triggerPin, echoPin);
Expand All @@ -50,13 +19,9 @@ void setup()
{
// the following block of code should always run first. Adjust it at your own peril!
app_setup();
IWatchdog.begin(2000000);
IWatchdog.begin(2000000);
Serial.begin(115200);
dronecan.version_major = 1;
dronecan.version_minor = 0;
dronecan.init(
onTransferReceived,
shouldAcceptTransfer,
custom_parameters,
"Beyond Robotix Node"
);
Expand Down
17 changes: 14 additions & 3 deletions examples/INA_current_sensor/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# INA current sensor example
# INA239 Current Sensor

This example illustrates how an already availible library can be used to easily integrate a new sensor into dronecan.
Reads voltage, current, and temperature from an INA239 SPI current/power monitor and broadcasts them as a DroneCAN `BatteryInfo` message at 10Hz.

**this is untested code currently** I'll be able to test it at some point when I get an INA to hand.
The INA239 is initialised with a 10A max current range and a 15mΩ shunt resistor — adjust the `INA.setMaxCurrentShunt()` call in `main.cpp` to match your hardware.

> **Note:** This example is untested. It is provided as an illustration of how to integrate an SPI sensor with the DroneCAN library.

## Dependencies

Install the INA239 library by RobTillaart:
https://github.com/RobTillaart/INA239

Download the zip and place the unzipped folder in the `lib` directory of your project. Make sure there are no nested folders inside (this can happen when unzipping from GitHub).

Alternatively, install it via the PlatformIO library manager.
25 changes: 1 addition & 24 deletions examples/INA_current_sensor/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@

#include <Arduino.h>
#include <dronecan.h>
#include <IWatchdog.h>
#include <app.h>
#include <vector>
#include "INA239.h"
#include <simple_dronecanmessages.h>

INA239 INA(5, &SPI);

Expand All @@ -22,32 +18,13 @@ DroneCAN dronecan;

uint32_t looptime = 0;

static void onTransferReceived(CanardInstance *ins, CanardRxTransfer *transfer)
{
DroneCANonTransferReceived(dronecan, ins, transfer);
}

static bool shouldAcceptTransfer(const CanardInstance *ins,
uint64_t *out_data_type_signature,
uint16_t data_type_id,
CanardTransferType transfer_type,
uint8_t source_node_id)

{
return false || DroneCANshouldAcceptTransfer(ins, out_data_type_signature, data_type_id, transfer_type, source_node_id);
}

void setup()
{
// the following block of code should always run first. Adjust it at your own peril!
app_setup();
IWatchdog.begin(2000000);
IWatchdog.begin(2000000);
Serial.begin(115200);
dronecan.version_major = 1;
dronecan.version_minor = 0;
dronecan.init(
onTransferReceived,
shouldAcceptTransfer,
custom_parameters,
"Beyond Robotix Node"
);
Expand Down
15 changes: 15 additions & 0 deletions examples/Magnetometer_listener/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Magnetometer Listener

Demonstrates how to receive DroneCAN messages using the full callback API (`onTransferReceived` / `shouldAcceptTransfer`).

Listens for `MagneticFieldStrength` broadcast messages on the bus and prints the X, Y, Z field values in Gauss to Serial.

Use this as a template when you need to receive any DroneCAN message type — copy the pattern in `onTransferReceived` and `shouldAcceptTransfer`, substituting the message ID, signature, struct, and decode call for your target message.

## When to use the callback API

The simplified `dronecan.init(parameters, name)` used in most examples handles everything internally. Use the 4-argument form shown here when your node needs to **receive** messages from other nodes on the bus.

## Dependencies

No extra libraries required.
84 changes: 84 additions & 0 deletions examples/Magnetometer_listener/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
Demonstrates receiving DroneCAN messages using the full callback API.

Listens for MagneticFieldStrength broadcast messages and prints the X, Y, Z
field values (in Gauss) to Serial at whatever rate the sender transmits them.

Use this as a template when you need to receive any DroneCAN message type —
copy the pattern in onTransferReceived and shouldAcceptTransfer, substituting
the message ID, signature, struct, and decode call for your target message.
*/

#include <Arduino.h>
#include <dronecan.h>

std::vector<DroneCAN::parameter> custom_parameters = {
{ "NODEID", DroneCAN::INT, 100, 0, 127 },
};

DroneCAN dronecan;

static void onTransferReceived(CanardInstance *ins, CanardRxTransfer *transfer)
{
switch (transfer->data_type_id)
{
case UAVCAN_EQUIPMENT_AHRS_MAGNETICFIELDSTRENGTH_ID:
{
uavcan_equipment_ahrs_MagneticFieldStrength pkt{};
uavcan_equipment_ahrs_MagneticFieldStrength_decode(transfer, &pkt);

Serial.print("Mag X: "); Serial.print(pkt.magnetic_field_ga[0]);
Serial.print(" Y: "); Serial.print(pkt.magnetic_field_ga[1]);
Serial.print(" Z: "); Serial.println(pkt.magnetic_field_ga[2]);
break;
}
}

DroneCANonTransferReceived(dronecan, ins, transfer);
}

static bool shouldAcceptTransfer(const CanardInstance *ins,
uint64_t *out_data_type_signature,
uint16_t data_type_id,
CanardTransferType transfer_type,
uint8_t source_node_id)
{
if (transfer_type == CanardTransferTypeBroadcast)
{
switch (data_type_id)
{
case UAVCAN_EQUIPMENT_AHRS_MAGNETICFIELDSTRENGTH_ID:
*out_data_type_signature = UAVCAN_EQUIPMENT_AHRS_MAGNETICFIELDSTRENGTH_SIGNATURE;
return true;
}
}

return false || DroneCANshouldAcceptTransfer(ins, out_data_type_signature, data_type_id, transfer_type, source_node_id);
}

void setup()
{
// the following block of code should always run first. Adjust it at your own peril!
app_setup();
IWatchdog.begin(2000000);
Serial.begin(115200);
dronecan.init(
onTransferReceived,
shouldAcceptTransfer,
custom_parameters,
"Beyond Robotix Listener"
);
// end of important starting code

// we use a while true loop instead of the arduino "loop" function since that causes issues.
while (true)
{
dronecan.cycle();
IWatchdog.reload();
}
}

void loop()
{
// Doesn't work coming from bootloader ? use while loop in setup
}
11 changes: 11 additions & 0 deletions examples/Servo_test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Servo Test

Listens for DroneCAN `ArrayCommand` messages and drives a servo on PA8 to the commanded position. This also demonstrates how to use the callback API (`onTransferReceived` / `shouldAcceptTransfer`) to receive DroneCAN messages.

The actuator ID this node responds to is configured via the `ACTUATOR_ID` parameter (default `0`), which can be changed at runtime via a ground station.

`command_value` is expected in the range `-1.0` to `1.0`, which maps to `0`–`180` degrees. This matches the range sent by ArduPilot for servo outputs over DroneCAN.

## Dependencies

No extra libraries required. The `Servo` library is included with the STM32 Arduino core.
Loading