-
-
Save philhartung/6f196e49c2e8889c3bbf31b081bc6574 to your computer and use it in GitHub Desktop.
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
/* | |
* See documentation at https://nRF24.github.io/RF24 | |
* See License information at root directory of this library | |
* Author: Brendan Doherty (2bndy5), Tom Clement (tjclement) | |
*/ | |
/** | |
* A modified example from the NRF24 library, that enables control of levels of GL25B and many more Neweer light panels. | |
*/ | |
#include <SPI.h> | |
#include "printf.h" | |
#include "RF24.h" | |
// Instantiate an object for the nRF24L01 transceiver. | |
// CE pin is wired to pin 15, CSN pin is wired to pin 17 on the Pi Pico. | |
RF24 radio(15, 17); | |
/* | |
Pi Pico Pinout: | |
nRF24 | Color | Pico Pin | Pico GPIO | | |
============================================ | |
GND | black | 38 | N/A | | |
VCC (3.3V) | red | 36 | N/A | | |
CE | orange | 20 | 15 | | |
CSN | yellow | 22 | 17 | | |
SCK | green | 24 | 18 | | |
MOSI | violet | 25 | 19 | | |
MISO | blue | 21 | 16 | | |
*/ | |
// Define the address used for TX/RX communication. | |
// In this use case, we only do transmissions. | |
uint8_t address[] = {0xD3, 0x5C, 0x6E}; | |
// This struct represents the packet sent to the receiving device. | |
// It contains command bytes relevant to brightness and color temperature. | |
typedef struct { | |
uint8_t header; | |
uint8_t target_channel; | |
uint8_t unknown1; | |
uint8_t command_type; // e.g. 0x82 for brightness, 0x83 for color temperature | |
uint8_t command1; // main value (brightness or color temperature) | |
uint8_t command2; // offset value to accompany command1 | |
uint8_t tail1; | |
uint8_t tail2; | |
uint8_t zeroes[24]; // not used, just padded with zero | |
} packet; | |
// Initialize the packet with default values. | |
packet payload = { | |
.header = 0x77, | |
.target_channel = 0x58, | |
.unknown1 = 0x01, | |
.command_type = 0x82, // default to brightness command | |
.command1 = 0x00, | |
.command2 = 0x52, | |
.tail1 = 0x00, | |
.tail2 = 0x00 | |
}; | |
// This buffer is used to print each byte of the payload in hexadecimal format. | |
char hexChar[3]; // 2 chars + null terminator | |
void setup() { | |
Serial.begin(115200); | |
while (!Serial) { | |
// Some boards need to wait to ensure access to serial over USB | |
} | |
// Initialize the transceiver on the SPI bus | |
if (!radio.begin()) { | |
Serial.println(F("Radio hardware is not responding!")); | |
while (1) {} // Hold in an infinite loop if radio is not found | |
} | |
// Set the power amplifier level | |
radio.setPALevel(RF24_PA_HIGH); | |
// We only send 32 bytes in each payload | |
radio.setPayloadSize(32); | |
// Configure other radio options | |
radio.setAutoAck(false); | |
radio.setAddressWidth(3); | |
radio.setChannel(10); | |
radio.setDataRate(RF24_250KBPS); | |
radio.setCRCLength(RF24_CRC_16); | |
// Open a writing pipe on the specified address. | |
// We only need pipe 0 for writing. | |
radio.openWritingPipe(address); | |
// We will not receive in this script, so stop listening. | |
radio.stopListening(); | |
// For debugging info (optional): | |
// printf_begin(); | |
// radio.printDetails(); | |
// radio.printPrettyDetails(); | |
Serial.println(F("=== Setup complete. Enter commands to adjust brightness or color temperature. ===")); | |
Serial.println(F("Usage: 'brightness <0-100>', 'color <29-70>' or 'power'")); | |
} | |
void loop() { | |
// Check if there is any serial input to parse | |
if (Serial.available()) { | |
// Read the entire line from the serial buffer | |
String input = Serial.readStringUntil('\n'); | |
input.trim(); // Remove any leading/trailing whitespace | |
// If the user typed nothing, skip | |
if (input.length() == 0) return; | |
// Convert input to lowercase for easy comparison | |
String lowerInput = input; | |
lowerInput.toLowerCase(); | |
// Parse commands | |
if (lowerInput.startsWith("brightness")) { | |
// Extract the numeric value after "brightness" | |
int value = parseValue(input, "brightness"); | |
// Constrain brightness between 0 and 100 to avoid invalid values | |
value = constrain(value, 0, 100); | |
// Prepare the payload for brightness | |
payload.command_type = 0x82; | |
payload.command1 = value; | |
// The second byte for brightness uses offset 0x52 | |
payload.command2 = 0x52 + value; | |
// Transmit the packet | |
transmitPacket(); | |
} else if (lowerInput.startsWith("color")) { | |
// Extract the numeric value after "color" | |
int value = parseValue(input, "color"); | |
// Constrain color temperature between 29 and 70 | |
value = constrain(value, 29, 70); | |
// Prepare the payload for color temperature | |
payload.command_type = 0x83; | |
payload.command1 = value; | |
// The second byte for color uses offset 0xBA | |
payload.command2 = 0xBA + value; | |
// Transmit the packet | |
transmitPacket(); | |
} else if (lowerInput.startsWith("power")) { | |
payload.command_type = 0x85; | |
payload.command1 = 0x01; | |
payload.command2 = 0x00; | |
transmitPacket(); | |
} else { | |
// Unrecognized command | |
Serial.println(F("Unknown command. Valid commands: 'brightness <0-100>', 'color <29-70>' or 'power'.")); | |
} | |
} | |
} | |
/** | |
* Helper function to parse the numeric value from a command like: | |
* "brightness 50" or "color 32". | |
* It returns -1 if the parse fails. | |
*/ | |
int parseValue(const String &input, const String &command) { | |
// Erstelle eine lokale Kopie von 'input' | |
String tmp = input; | |
// Wandelt die Kopie in Kleinbuchstaben um | |
tmp.toLowerCase(); | |
// Nun kann man 'indexOf(command)' gefahrlos aufrufen | |
int index = tmp.indexOf(command); | |
if (index == -1) { | |
return -1; | |
} | |
// Extrahiere den Teil nach 'command' | |
String numericPart = tmp.substring(index + command.length()); | |
numericPart.trim(); | |
// Wandle den extrahierten Teil in eine Zahl um | |
return numericPart.toInt(); | |
} | |
/** | |
* Transmits the current payload packet via the nRF24 radio and prints info to Serial. | |
*/ | |
void transmitPacket() { | |
// Start timer for diagnostics | |
unsigned long startTimer = micros(); | |
// Perform the write operation | |
bool report = radio.write(&payload, sizeof(payload)); | |
// End timer | |
unsigned long endTimer = micros(); | |
// Print the entire payload in hex | |
uint8_t* castPayload = (uint8_t*) &payload; | |
for(int i = 0; i < sizeof(payload); i++) { | |
sprintf(hexChar, "%02X", castPayload[i]); | |
Serial.print(hexChar); | |
} | |
Serial.println(); | |
// Check if the transmission was successful | |
if (report) { | |
Serial.print(F("Transmission successful! Time to transmit = ")); | |
Serial.print(endTimer - startTimer); | |
Serial.println(F(" us.")); | |
} else { | |
Serial.println(F("Transmission failed or timed out.")); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment