Skip to content

Instantly share code, notes, and snippets.

@jones2126
Created December 18, 2024 13:57
Show Gist options
  • Save jones2126/53447a2062fec87c4d61bd1754ce6c8e to your computer and use it in GitHub Desktop.
Save jones2126/53447a2062fec87c4d61bd1754ce6c8e to your computer and use it in GitHub Desktop.
Test code that provides a shell to integrate a NRF24 transceiver, through hole, PL9823 RGB LEDs for status reporting and SDPT toggle switch to track 3 states. The code runs on a Teensy 3.2 and uses Teensy specific elapsedMillis for loop timing control. The NRF24 uses an SPI interface. It also implements a two-way communication approach with ackn…
#include <SPI.h>
#include <RF24.h>
#include <Adafruit_NeoPixel.h>
// LED Definitions
#define NUM_LEDS 3
#define DATA_PIN 2
#define SWITCH_PIN1 3
#define SWITCH_PIN2 4
// Timing control using elapsedMillis
elapsedMillis radioLedTimer; // LED0: Radio status update timer (100ms/10Hz)
elapsedMillis switchLedTimer; // LED1: Switch status update timer (100ms/10Hz)
elapsedMillis blinkLedTimer; // LED2: Simple blink timer (1000ms/1Hz)
elapsedMillis switchReadTimer; // Switch reading timer (50ms/20Hz)
elapsedMillis rateCalcTimer; // Radio rate calculation timer (10s)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, DATA_PIN, NEO_RGB + NEO_KHZ800);
// RF24 Configuration
RF24 radio(7, 8);
// Data structures for communication
struct RadioControlStruct {
float steering_val;
float throttle_val;
float voltage;
byte estop;
byte control_mode;
unsigned long counter;
uint32_t dummy;
};
struct AckPayloadStruct {
unsigned long counter;
uint32_t dummy[4];
};
RadioControlStruct radioData;
AckPayloadStruct ackPayload;
const uint8_t address[][6] = {"RCTRL", "TRACT"};
// Counters and state variables
unsigned long ackCount = 0;
unsigned long shortTermAckCount = 0;
bool led2State = false;
void setup() {
Serial.begin(115200);
Serial.println("Starting up...");
// Initialize LEDs
strip.begin();
strip.setBrightness(128);
strip.show();
// Initialize switch pins
pinMode(SWITCH_PIN1, INPUT_PULLUP);
pinMode(SWITCH_PIN2, INPUT_PULLUP);
// Initialize SPI and Radio
SPI.begin();
delay(100);
// Try to initialize the radio
bool initialized = false;
for (int i = 0; i < 5; i++) {
if (radio.begin()) {
initialized = true;
Serial.println("Radio initialized!");
break;
}
delay(1000);
}
if (!initialized) {
Serial.println("Radio hardware not responding!");
while (1) {
strip.setPixelColor(0, 255, 0, 0);
strip.show();
delay(500);
strip.setPixelColor(0, 0, 0, 0);
strip.show();
delay(500);
}
}
// Configure radio
radio.setPALevel(RF24_PA_HIGH);
radio.setDataRate(RF24_250KBPS);
radio.setChannel(124);
radio.openWritingPipe(address[1]);
radio.openReadingPipe(1, address[0]);
radio.enableAckPayload();
radio.startListening();
radio.printDetails();
// Initialize acknowledgment payload
ackPayload.counter = 0;
for (int i = 0; i < 4; i++) {
ackPayload.dummy[i] = 0xDEADBEEF;
}
Serial.println("Setup complete");
}
void updateRadioLED() {
if (radioLedTimer >= 100) { // 10Hz update
float rate = (float)shortTermAckCount * 10.0; // Convert to Hz
// Set LED0 color based on radio rate
if (rate < 2.0) {
strip.setPixelColor(0, 255, 0, 0); // Red: poor connection
} else if (rate >= 2.0 && rate <= 5.0) {
strip.setPixelColor(0, 255, 255, 0); // Yellow: marginal
} else {
strip.setPixelColor(0, 0, 255, 0); // Green: good connection
}
shortTermAckCount = 0;
radioLedTimer = 0;
strip.show();
}
}
void updateSwitchLED() {
if (switchLedTimer >= 100) { // 10Hz update
bool state1 = digitalRead(SWITCH_PIN1);
bool state2 = digitalRead(SWITCH_PIN2);
// Set LED1 color based on switch states
if (state1 == LOW && state2 == LOW) {
strip.setPixelColor(1, 255, 0, 0); // Red
} else if (state1 == LOW && state2 == HIGH) {
strip.setPixelColor(1, 0, 0, 255); // Blue
} else if (state1 == HIGH && state2 == LOW) {
strip.setPixelColor(1, 0, 255, 0); // Green
} else {
strip.setPixelColor(1, 0, 0, 0); // Off
}
switchLedTimer = 0;
strip.show();
}
}
void updateBlinkLED() {
if (blinkLedTimer >= 1000) { // 1Hz blink
led2State = !led2State;
strip.setPixelColor(2, 0, 0, led2State ? 128 : 0); // Blue blink
blinkLedTimer = 0;
strip.show();
}
}
void readRadio() {
if (radio.available()) {
uint8_t bytes = radio.getDynamicPayloadSize();
if (bytes == sizeof(RadioControlStruct)) {
radio.read(&radioData, sizeof(RadioControlStruct));
ackPayload.counter++;
radio.writeAckPayload(1, &ackPayload, sizeof(AckPayloadStruct));
ackCount++;
shortTermAckCount++;
} else {
radio.flush_rx();
}
}
}
void printRadioStats() {
if (rateCalcTimer >= 10000) { // Print stats every 10 seconds
float rate = (float)ackCount / 10.0; // Convert to Hz
Serial.print("ACK Rate (Receiver): ");
Serial.print(rate);
Serial.println(" Hz");
ackCount = 0;
rateCalcTimer = 0;
}
}
void loop() {
readRadio();
updateRadioLED();
updateSwitchLED();
updateBlinkLED();
printRadioStats();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment