Instantly share code, notes, and snippets.
Created
March 29, 2018 21:40
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save NSBum/461908892287fe338755c6a088b1b39e to your computer and use it in GitHub Desktop.
Trigger relay remotely using nRF24L01+ modules
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 <EEPROM.h> | |
/* Hardware connections from Arduino Nano to nRF24L01 | |
* CE -> D9 | |
* CSN -> D10 | |
* SCK -> D13 | |
* MOSI -> D11 | |
* MISO -> D12 | |
* IRQ -> N/C | |
* | |
* Set up both Nano + RF24 the same way. Make the transmitter radio 1 and the receiver radio 0 | |
* On the receiver, setup a relay driven by D8 | |
*/ | |
// **************** User configuration *************** | |
// set this as radio 0 or 1 | |
bool radioNumber = 1; | |
/* Hardware configuration */ | |
RF24 radio(9,10); | |
// Network topology | |
uint8_t addresses[][6] = {"1Node","2Node"}; | |
// Role management | |
typedef enum { role_xmit = 1, role_recv=0 } role_e; | |
const char* role_friendly_name[] = { "Receive", "Transmit" }; | |
role_e role = role_recv; | |
// State management | |
typedef enum { state_free_serial = 0, state_obtain_code = 1, state_idle = 2 } state_t; | |
state_t currentState = state_free_serial; | |
// EEPROM | |
#define ID_WAS_WRITTEN 0x1D | |
#define ID_ADDR 1 | |
#define TRANSMITTER_ID 0x74 // 't' | |
#define RECEIVER_ID 0x72 // 'r' | |
#define RELAY_PIN 8 | |
#define RELAY_SET_CMD 0x666 // code the transmitter sends to toggle relay | |
#define RELAY_SET_RESPONSE 0x333 // success code returned by receiver | |
#define RELAY_NOT_SET_RESPONSE 0x111 // no success code returned by receiver | |
// "Button" - we're not using a physical button here | |
// instead we are looking for a "B" on the serial input | |
// to the transmitter | |
bool buttonPressed = false; | |
void setup() { | |
Serial.begin(9600); | |
Serial.println( F("RF24 remote relay test") ); | |
// read the EEPROM first and see if we have a hardware ID | |
if( EEPROM.read(0) == ID_WAS_WRITTEN ) { | |
// we can extract the ID and set a default role | |
radioNumber = (EEPROM.read(ID_ADDR) == TRANSMITTER_ID)?1:0; | |
role = (radioNumber == 1 )?role_xmit:role_recv; | |
Serial.print( F("EEPROM Radio # ") ); | |
Serial.println(radioNumber); | |
} | |
else { | |
Serial.println( F("*** PRESS 'T' to begin transmitting to the other node") ); | |
} | |
// configure our radio | |
radio.begin(); | |
radio.setPALevel(RF24_PA_MIN); | |
if( radioNumber ) { | |
radio.openWritingPipe(addresses[1]); | |
radio.openReadingPipe(1,addresses[0]); | |
} | |
else { | |
radio.openWritingPipe(addresses[0]); | |
radio.openReadingPipe(1,addresses[1]); | |
} | |
if( role == role_recv ) { | |
digitalWrite(RELAY_PIN, LOW); | |
pinMode(RELAY_PIN, OUTPUT); | |
} | |
radio.startListening(); | |
} | |
void loop() { | |
if( role == role_xmit ) { | |
uint16_t start_time = micros(); | |
radio.stopListening(); | |
if( buttonPressed ) { | |
buttonPressed = false; | |
uint16_t sendData = RELAY_SET_CMD; | |
Serial.println(F("Now sending button press")); | |
if (!radio.write( &sendData, sizeof(uint16_t) )){ | |
Serial.println(F("*** ERROR: failed to send")); | |
} | |
radio.startListening(); | |
unsigned long started_waiting_at = micros(); // Set up a timeout period, get the current microseconds | |
boolean timeout = false; | |
while( !radio.available() ) { | |
if (micros() - started_waiting_at > 200000 ){ // If waited longer than 200ms, indicate timeout and exit while loop | |
timeout = true; | |
break; | |
} | |
} | |
if( timeout ) { | |
Serial.println(F("*** WARN: response timed out")); | |
} | |
else { | |
uint16_t response; | |
radio.read( &response, sizeof(uint16_t)); | |
Serial.print(F("Received response: 0x")); | |
Serial.println(response, HEX); | |
} | |
} | |
} // xmit role | |
// if we are the receiver | |
else { | |
uint16_t code; | |
if( radio.available() ) { | |
while( radio.available() ) { | |
radio.read( &code, sizeof(uint16_t) ); | |
} | |
radio.stopListening(); | |
if(code == RELAY_SET_CMD ) { | |
digitalWrite(RELAY_PIN, !digitalRead(RELAY_PIN)); | |
code = RELAY_SET_RESPONSE; | |
} | |
else { | |
code = RELAY_NOT_SET_RESPONSE; | |
} | |
radio.write( &code, sizeof(uint16_t) ); | |
radio.startListening(); | |
Serial.print(F("Sent response ")); | |
Serial.println(code,HEX); | |
} | |
} // rcv role | |
// each pass check if user wants to switch | |
if( Serial.available() ) { | |
if( currentState == state_obtain_code ) { | |
uint8_t code = Serial.read(); | |
// mark that we've written an ID | |
EEPROM.write(0,0x1D); | |
EEPROM.write(ID_ADDR, code); | |
currentState == state_idle; | |
} | |
else { | |
char c = toupper(Serial.read()); | |
if( c == 'T' && role == role_recv ) { | |
Serial.println(F("*** CHANGING TO XMIT ROLE ***")); | |
role = role_xmit; | |
} | |
else if( c== 'R' && role == role_xmit ) { | |
Serial.println(F("*** CHANGING TO RCV ROLE ***")); | |
role = role_recv; | |
radio.startListening(); | |
} | |
else if( c == 'B' && role == role_xmit ) { | |
Serial.println(F("*** BUTTON PRESSED ***")); | |
buttonPressed = true; | |
} | |
else if( c == 'S' ) { | |
// next pass through serial read loop will | |
// obtain the code to use | |
Serial.println("Type 't' for radio1/xmit or 'r' for radio0/receive"); | |
currentState = state_obtain_code; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment