/*
Nov 2017 - morse tranceiver by ppenguin
Based on below described.
Simple morse code transceiver using 2 nodes consisting of NRF24 transceiver, a push button
and a RGB led connected to an Arduino Nano.
Nice for 2 kids to each sit in a room and experiment with "the old days" morse code communication.
The LED will light green for outgoing code and red for incoming code (to have better feedback)
Removed most serial code (except debugging) to enable stand alone operation
Dec 2014 - TMRh20 - Updated
Derived from examples by J. Coliz <maniacbug@ymail.com>
*/
/**
* Example for efficient call-response using ack-payloads
*
* This example continues to make use of all the normal functionality of the radios including
* the auto-ack and auto-retry features, but allows ack-payloads to be written optionlly as well.
* This allows very fast call-response communication, with the responding radio never having to
* switch out of Primary Receiver mode to send back a payload, but having the option to switch to
* primary transmitter if wanting to initiate communication instead of respond to a commmunication.
*/
#include <SPI.h>
#include "RF24.h"
/****************** User Config ***************************/
/*** Set this radio as radio number 0 or 1 ***/
bool radioNumber = 1;
/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 7 & 8 */
RF24 radio(9,10); // use mysensor default pins since I'm used to that
/**********************************************************/
// Topology
byte addresses[][6] = {"1Node","2Node"}; // Radio pipe addresses for the 2 nodes to communicate.
// Role management: Set up role. This sketch uses the same software for all the nodes
// in this system. Doing so greatly simplifies testing.
typedef enum { role_ping_out = 1, role_pong_back } role_e; // The various roles supported by this sketch
const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"}; // The debug-friendly names of those roles
role_e role = role_pong_back; // The role of the current running sketch
#define LONG 2 // value of morse long _
#define SHORT 1 // value of morse short .
#define ACK 3 // value of ACK payload (necessary?)
#define DELAY 10 // loop delay
#define TLONG 250 // 250ms or longer is considered long
#define TLONGE 800 // max long period
#define TSHORT 170 // 170ms or shorter is considered short
#define MAXFAIL 10
#define PINBT 2 // digital input push button
#define PINL1 3 // digital output LED1
#define PINL2 4 // digital output LED2
byte payload = 0; // A single byte as payload
byte ackByte = ACK;
bool btpressed = false;
unsigned long lastpressed = 0;
byte fail = 0;
void setup(){
Serial.begin(115200);
Serial.println(F("RF24/examples/GettingStarted_CallResponse"));
/*
Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));
*/
// Setup and configure radio
radio.begin();
radio.enableAckPayload(); // Allow optional ack payloads
radio.enableDynamicPayloads(); // Ack payloads are dynamic payloads
if(radioNumber){
radio.openWritingPipe(addresses[1]); // Both radios listen on the same pipes by default, but opposite addresses
radio.openReadingPipe(1,addresses[0]); // Open a reading pipe on address 0, pipe 1
}else{
radio.openWritingPipe(addresses[0]);
radio.openReadingPipe(1,addresses[1]);
}
radio.startListening(); // Start listening
radio.writeAckPayload(1,&ackByte,1); // Pre-load an ack-paylod into the FIFO buffer for pipe 1
//radio.printDetails();
pinMode(PINBT, INPUT_PULLUP); // high == off, but now de don't need an external resistor for the button
pinMode(PINL1, OUTPUT);
pinMode(PINL2, OUTPUT);
}
void loop(void) {
/* loop initial/primary function is
(1) poll push button
(2) check whether msg received
If the push button was pushed and we have a result (either short or long) it is sent (role change)
*/
btpressed = !digitalRead(PINBT); // invert because we use internal pullup
if (btpressed && lastpressed == 0) {
lastpressed = millis(); // button first pressed after last release
Serial.print("Button down");
digitalWrite(PINL1, 1);
}
if (!btpressed && lastpressed != 0) { // button release
Serial.print("Button release");
digitalWrite(PINL1, 0);
if (millis() - lastpressed <= TSHORT) {
payload = SHORT;
Serial.print("Set payload SHORT");
} else if ((millis() - lastpressed >= TLONG) && (millis() - lastpressed <= TLONGE)) {
payload = LONG;
Serial.print("Set payload LONG");
} else {
payload = 0;
}
lastpressed = 0;
// role = role_ping_out; // we have data now, so we send it
}
/****************** Ping Out Role ***************************/
//if (role == role_ping_out){ // Radio is in ping mode
if (payload > 0) { // we only need to send if we have a payload
byte gotByte; // Initialize a variable for the incoming response (only for ACK)
radio.stopListening(); // First, stop listening so we can talk.
Serial.print(F("Now sending ")); // Use a simple byte counter as payload
Serial.println(payload);
unsigned long time = millis(); // Record the current millisecond count
if ( radio.write(&payload,1) ) { // Send payload to the other radio
/* if(!radio.available()){ // If nothing in the buffer, we got an ack but it is blank
Serial.print(F("Got blank response. round-trip delay: "));
Serial.print(millis()-time);
Serial.println(F(" milliseconds"));
}else{ */
while(radio.available() ){ // If an ack with payload was received
radio.read( &gotByte, 1 ); // Read it, and display the response time
unsigned long timer = millis();
if (gotByte == ACK) { // only interested in ACK now
Serial.print(F("Got ACK response "));
Serial.print(gotByte);
Serial.print(F(" round-trip delay: "));
Serial.print(timer - time);
Serial.println(F(" milliseconds"));
break; // one ACK is enough, now continue listening
}
}
//}
payload = 0; // reset payload after sucessfuly sending
} else {
fail++;
if (fail >= MAXFAIL) {
fail = 0;
payload = 0; // give up and start listening
}
}
delay(DELAY); // Try again later
}
/****************** Pong Back Role ***************************/
// if ( role == role_pong_back ) {
if (payload == 0) { // nothing to send, so listen
radio.startListening();
byte pipeNo, gotByte; // Declare variables for the pipe and the byte received
while( radio.available(&pipeNo)){ // Read all available payloads
digitalWrite(PINL2, 0); // default LED off
radio.read( &gotByte, 1 );
// Since this is a call-response. Respond directly with an ack payload.
// Ack payloads are much more efficient than switching to transmit mode to respond to a call
radio.writeAckPayload(pipeNo,&ackByte, 1 ); // This can be commented out to send empty payloads.
Serial.print(F("sent ACK"));
// handle user output for received byte
Serial.println(gotByte);
unsigned long ttime = 0;
if (gotByte == LONG) ttime = millis() + TLONG;
else if (gotByte == SHORT) ttime = millis() + int(TSHORT/3);
while (millis() < ttime) {
digitalWrite(PINL2, 1);
}
digitalWrite(PINL2, 0);
}
}
}
Comments
Please log in or sign up to comment.