Created
December 18, 2024 13:57
-
-
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…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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