Init fork from Stuart Robinson's repo
This commit is contained in:
@ -0,0 +1,306 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 19/03/20
|
||||
|
||||
This program is supplied as is, it is up to the user of the program to decide if the program is
|
||||
suitable for the intended purpose and free from errors.
|
||||
*******************************************************************************************************/
|
||||
|
||||
/*******************************************************************************************************
|
||||
Program Operation - This program is a remote control transmitter. When one of four switches are made
|
||||
(shorted to ground) a packet is transmitted with single byte indicating the state of Switch0 as bit 0,
|
||||
Switch1 as bit 1 and Switch2 as bit 2. To prevent false triggering at the receiver the packet contains a
|
||||
32 bit number called the TXIdentity which in this example is set to 1234554321. The receiver will only
|
||||
act on, change the state of the outputs, if the identity set in the receiver matches that of the
|
||||
transmitter. The chance of a false trigger is fairly remote.
|
||||
|
||||
Between switch presses the LoRa device and Atmel microcontroller are put to sleep. A switch press wakes
|
||||
up the processor from sleep, the switches are read and a packet sent. On a 'bare bones' Arduino setup
|
||||
the transmitter has a sleep current of approx 2.2uA, so it's ideal for a battery powered remote control
|
||||
with a potential range of many kilometres.
|
||||
|
||||
The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file. These settings
|
||||
are not necessarily optimised for long range.
|
||||
|
||||
Serial monitor baud rate is set at 9600.
|
||||
*******************************************************************************************************/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <SX128XLT.h>
|
||||
#include "Settings.h"
|
||||
#include <ProgramLT_Definitions.h>
|
||||
|
||||
#include <avr/wdt.h> //watchdog timer library, integral to Arduino IDE
|
||||
#include <avr/sleep.h> //watchdog timer library, integral to Arduino IDE
|
||||
#include "PinChangeInterrupt.h" //get the library here; https://github.com/NicoHood/PinChangeInterrupt
|
||||
|
||||
SX128XLT LT;
|
||||
|
||||
uint32_t TXpacketCount;
|
||||
uint8_t TXPacketL;
|
||||
|
||||
volatile bool switch0flag = false;
|
||||
volatile bool switch1flag = false;
|
||||
volatile bool switch2flag = false;
|
||||
volatile bool switch3flag = false;
|
||||
|
||||
void loop()
|
||||
{
|
||||
uint8_t switches;
|
||||
|
||||
digitalWrite(LED1, LOW); //turn off indicator LED
|
||||
Serial.print(F("Sleeping zzzz"));
|
||||
Serial.flush(); //make sure all serial output has gone
|
||||
|
||||
LT.setSleep(CONFIGURATION_RETENTION); //sleep LoRa device, keeping register settings in sleep.
|
||||
sleep_permanent(); //sleep Atmel processor permanently for switch wakeup only
|
||||
LT.wake(); //wake up the lora device - nicely
|
||||
|
||||
digitalWrite(LED1, HIGH);
|
||||
|
||||
Serial.println(F(" - Awake !!")); //the processor has woken up
|
||||
switches = readSwitches(); //read the state of the switches
|
||||
|
||||
TXpacketCount++;
|
||||
Serial.print(TXpacketCount); //print the numbers of sends
|
||||
Serial.print(F(" Sending > "));
|
||||
|
||||
Serial.print(switches, BIN);
|
||||
|
||||
if (sendSwitchPacket(switches))
|
||||
{
|
||||
Serial.println(F(" SentOK"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(F("Send Error - IRQreg,"));
|
||||
Serial.print(LT.readIrqStatus(), HEX);
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
delay(500);
|
||||
}
|
||||
|
||||
|
||||
uint8_t sendSwitchPacket(uint8_t switches)
|
||||
{
|
||||
//The SX12XX buffer is filled with variables of a known type and in a known sequence. Make sure the
|
||||
//receiver uses the same variable types and sequence to read variables out of the receive buffer.
|
||||
uint8_t len;
|
||||
|
||||
LT.startWriteSXBuffer(0); //start the write packet to buffer process
|
||||
LT.writeUint8(RControl1); //this byte identifies the type of packet
|
||||
LT.writeUint32(TXIdentity); //this 32bit integer defines the Identity of the transmiter
|
||||
LT.writeUint8(switches); //this byte contains the 8 switch values to be sent
|
||||
len = LT.endWriteSXBuffer(); //close the packet, get the length of data to be sent
|
||||
|
||||
//now transmit the packet, 10 second timeout, and wait for it to complete sending
|
||||
TXPacketL = LT.transmitSXBuffer(0, len, 10000, TXpower, WAIT_TX);
|
||||
|
||||
return TXPacketL; //TXPacketL will be 0 if there was an error sending
|
||||
}
|
||||
|
||||
|
||||
void sleep_permanent()
|
||||
{
|
||||
attachInterrupts();
|
||||
|
||||
ADCSRA = 0; //disable ADC
|
||||
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
|
||||
noInterrupts (); //timed sequence follows
|
||||
sleep_enable();
|
||||
|
||||
// turn off brown-out enable in software
|
||||
MCUCR = bit (BODS) | bit (BODSE); //turn on brown-out enable select
|
||||
MCUCR = bit (BODS); //this must be done within 4 clock cycles of above
|
||||
interrupts (); //guarantees next instruction executed
|
||||
|
||||
sleep_cpu (); //sleep within 3 clock cycles of above
|
||||
|
||||
/* wake up here */
|
||||
|
||||
sleep_disable();
|
||||
|
||||
detachInterrupts();
|
||||
}
|
||||
|
||||
|
||||
void attachInterrupts()
|
||||
{
|
||||
if (SWITCH0 >= 0)
|
||||
{
|
||||
attachPCINT(digitalPinToPCINT(SWITCH0), wake0, FALLING);
|
||||
switch0flag = false;
|
||||
}
|
||||
|
||||
if (SWITCH1 >= 0)
|
||||
{
|
||||
attachPCINT(digitalPinToPCINT(SWITCH1), wake1, FALLING);
|
||||
switch1flag = false;
|
||||
}
|
||||
|
||||
if (SWITCH2 >= 0)
|
||||
{
|
||||
attachPCINT(digitalPinToPCINT(SWITCH2), wake2, FALLING);
|
||||
switch2flag = false;
|
||||
}
|
||||
|
||||
if (SWITCH3 >= 0)
|
||||
{
|
||||
attachPCINT(digitalPinToPCINT(SWITCH3), wake3, FALLING);
|
||||
switch3flag = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void detachInterrupts()
|
||||
{
|
||||
if (SWITCH0 >= 0)
|
||||
{
|
||||
detachPCINT(digitalPinToPCINT(SWITCH0));
|
||||
}
|
||||
|
||||
if (SWITCH1 >= 0)
|
||||
{
|
||||
detachPCINT(digitalPinToPCINT(SWITCH1));
|
||||
}
|
||||
|
||||
if (SWITCH2 >= 0)
|
||||
{
|
||||
detachPCINT(digitalPinToPCINT(SWITCH2));
|
||||
}
|
||||
|
||||
if (SWITCH3 >= 0)
|
||||
{
|
||||
detachPCINT(digitalPinToPCINT(SWITCH3));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void wake0()
|
||||
{
|
||||
switch0flag = true;
|
||||
}
|
||||
|
||||
|
||||
void wake1()
|
||||
{
|
||||
switch1flag = true;
|
||||
}
|
||||
|
||||
|
||||
void wake2()
|
||||
{
|
||||
switch2flag = true;
|
||||
}
|
||||
|
||||
|
||||
void wake3()
|
||||
{
|
||||
switch3flag = true;
|
||||
}
|
||||
|
||||
|
||||
uint8_t readSwitches()
|
||||
{
|
||||
uint8_t switchByte = 0xFF; //start assuming all switches off
|
||||
|
||||
if (switch0flag)
|
||||
{
|
||||
bitClear(switchByte, 0); //if the flag is set clear the bit
|
||||
Serial.println(F("SWITCH0 pressed"));
|
||||
}
|
||||
|
||||
if (switch1flag)
|
||||
{
|
||||
bitClear(switchByte, 1); //if the flag is set clear the bit
|
||||
Serial.println(F("SWITCH1 pressed"));
|
||||
}
|
||||
|
||||
if (switch2flag)
|
||||
{
|
||||
bitClear(switchByte, 2); //if the flag is set clear the bit
|
||||
Serial.println(F("SWITCH2 pressed"));
|
||||
}
|
||||
|
||||
|
||||
if (switch3flag)
|
||||
{
|
||||
bitClear(switchByte, 3); //if the flag is set clear the bit
|
||||
Serial.println(F("SWITCH3 pressed"));
|
||||
}
|
||||
|
||||
return switchByte;
|
||||
}
|
||||
|
||||
|
||||
void led_Flash(uint16_t flashes, uint16_t delaymS)
|
||||
{
|
||||
uint16_t index;
|
||||
for (index = 1; index <= flashes; index++)
|
||||
{
|
||||
digitalWrite(LED1, HIGH);
|
||||
delay(delaymS);
|
||||
digitalWrite(LED1, LOW);
|
||||
delay(delaymS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setupSwitches()
|
||||
{
|
||||
if (SWITCH0 >= 0)
|
||||
{
|
||||
pinMode(SWITCH0, INPUT_PULLUP);
|
||||
}
|
||||
|
||||
if (SWITCH1 >= 0)
|
||||
{
|
||||
pinMode(SWITCH1, INPUT_PULLUP);
|
||||
}
|
||||
|
||||
if (SWITCH2 >= 0)
|
||||
{
|
||||
pinMode(SWITCH2, INPUT_PULLUP);
|
||||
}
|
||||
|
||||
if (SWITCH3 >= 0)
|
||||
{
|
||||
pinMode(SWITCH3, INPUT_PULLUP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
pinMode(LED1, OUTPUT);
|
||||
led_Flash(2, 125);
|
||||
|
||||
setupSwitches();
|
||||
|
||||
Serial.begin(9600);
|
||||
|
||||
SPI.begin();
|
||||
|
||||
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
|
||||
{
|
||||
led_Flash(2, 125);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("Device error"));
|
||||
while (1)
|
||||
{
|
||||
led_Flash(50, 50); //long fast speed flash indicates LoRa device error
|
||||
}
|
||||
}
|
||||
|
||||
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate);
|
||||
|
||||
Serial.println(F("Transmitter ready"));
|
||||
Serial.println();
|
||||
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 19/03/20
|
||||
|
||||
This program is supplied as is, it is up to the user of the program to decide if the program is
|
||||
suitable for the intended purpose and free from errors.
|
||||
*******************************************************************************************************/
|
||||
|
||||
|
||||
//******* Setup hardware pin definitions here ! ***************
|
||||
|
||||
//These are the pin definitions for one of my own boards, the Easy Pro Mini,
|
||||
//be sure to change the definitions to match your own setup.
|
||||
|
||||
const int8_t NSS = 10; //select on LoRa device
|
||||
const int8_t NRESET = 9; //reset on LoRa device
|
||||
const int8_t RFBUSY = 7; //RF busy on LoRa device
|
||||
const int8_t DIO1 = 3; //DIO1 on LoRa device, used for RX and TX done
|
||||
|
||||
const int8_t LED1 = 8; //On board LED, logic high is on
|
||||
|
||||
#define LORA_DEVICE DEVICE_SX1280 //this is the device we are using
|
||||
|
||||
const int8_t SWITCH0 = 2;
|
||||
const int8_t SWITCH1 = 4;
|
||||
const int8_t SWITCH2 = A3;
|
||||
const int8_t SWITCH3 = A2;
|
||||
|
||||
const uint32_t TXIdentity = 1234554321; //define an identity number, the receiver must use the same number
|
||||
//range is 0 to 4294967296
|
||||
|
||||
|
||||
|
||||
//******* Setup LoRa Test Parameters Here ! ***************
|
||||
|
||||
//LoRa Modem Parameters
|
||||
#define Frequency 2445000000 //frequency of transmissions
|
||||
#define Offset 0 //offset frequency for calibration purposes
|
||||
#define Bandwidth LORA_BW_0400 //LoRa bandwidth
|
||||
#define SpreadingFactor LORA_SF7 //LoRa spreading factor
|
||||
#define CodeRate LORA_CR_4_5 //LoRa coding rate
|
||||
|
||||
#define TXpower 10 //power for transmissions in dBm
|
||||
@ -0,0 +1,272 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 19/03/20
|
||||
|
||||
This program is supplied as is, it is up to the user of the program to decide if the program is
|
||||
suitable for the intended purpose and free from errors.
|
||||
*******************************************************************************************************/
|
||||
|
||||
/*******************************************************************************************************
|
||||
Program Operation - This program is a remote control receiver. When a packet is received an 8 bit byte
|
||||
(SwitchByte) is read and the four outputs (defined in Settings.h) are toggled according to the bits
|
||||
set in this byte. If the Switch1 byte has bit 0 cleared, then OUTPUT0 is toggled. If the Switch1 byte
|
||||
has bit 1 cleared, then OUTPUT1 is toggled. If the Switch1 byte has bit 2 cleared, then OUTPUT2 is toggled.
|
||||
|
||||
To prevent false triggering at the receiver the packet contains also contains a 32 bit number called the
|
||||
TXIdentity which in this example is set to 1234554321. The receiver will only act on, change the state
|
||||
of the outputs, if the identity set in the receiver matches that of the transmitter. The chance of a
|
||||
false trigger is fairly remote.
|
||||
|
||||
The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file.
|
||||
|
||||
Serial monitor baud rate is set at 9600.
|
||||
*******************************************************************************************************/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <SX128XLT.h>
|
||||
#include "Settings.h"
|
||||
#include <ProgramLT_Definitions.h>
|
||||
|
||||
SX128XLT LT;
|
||||
|
||||
uint32_t RXpacketCount;
|
||||
uint16_t errors;
|
||||
|
||||
uint8_t RXPacketL; //length of received packet
|
||||
uint8_t RXPacketType; //type of received packet
|
||||
int16_t PacketRSSI; //RSSI of received packet
|
||||
int8_t PacketSNR; //signal to noise ratio of received packet
|
||||
|
||||
uint8_t SwitchByte = 0xFF; //this is the transmitted switch values, bit 0 = Switch0 etc
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
RXPacketL = LT.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort, no timeout
|
||||
|
||||
digitalWrite(LED1, HIGH); //something has happened
|
||||
|
||||
PacketRSSI = LT.readPacketRSSI(); //read the signal strength of the received packet
|
||||
PacketSNR = LT.readPacketSNR(); //read the signal to noise ratio of the received packet
|
||||
|
||||
if (RXPacketL == 0)
|
||||
{
|
||||
packet_is_Error();
|
||||
}
|
||||
else
|
||||
{
|
||||
packet_is_OK();
|
||||
}
|
||||
|
||||
digitalWrite(LED1, LOW);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
|
||||
uint8_t packet_is_OK()
|
||||
{
|
||||
//packet has been received, now read from the SX12xx Buffer using the same variable type and
|
||||
//order as the transmit side used.
|
||||
uint32_t TXIdentity;
|
||||
|
||||
RXpacketCount++;
|
||||
Serial.print(RXpacketCount);
|
||||
Serial.print(F(" Packet Received"));
|
||||
|
||||
LT.startReadSXBuffer(0); //start buffer read at location 0
|
||||
RXPacketType = LT.readUint8(); //read in the packet type
|
||||
TXIdentity = LT.readUint32(); //read in the identity of transmitter
|
||||
SwitchByte = LT.readUint8(); //read in the Switch values
|
||||
RXPacketL = LT.endReadSXBuffer(); //finish buffer read
|
||||
|
||||
printpacketDetails();
|
||||
|
||||
if (RXPacketType != RControl1)
|
||||
{
|
||||
Serial.print(F(" Wrong packet type"));
|
||||
led_Flash(5, 25); //short fast speed flash indicates wrong packet type
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (TXIdentity != RXIdentity)
|
||||
{
|
||||
Serial.print(F(" Transmitter "));
|
||||
Serial.print(TXIdentity);
|
||||
Serial.print(F(" not recognised"));
|
||||
led_Flash(5, 25); //short fast speed flash indicates transmitter not recognised
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (LT.readRXPacketL() != 6)
|
||||
{
|
||||
Serial.print(F(" Wrong Packet Length"));
|
||||
led_Flash(5, 25); //short fast speed flash indicates transmitter not recognised
|
||||
return 0;
|
||||
}
|
||||
|
||||
//if we get to here, then the packet is valid so switch outputs accordingly
|
||||
|
||||
Serial.print(F(",SwitchByte Received "));
|
||||
Serial.print(SwitchByte, BIN); //print switch values in binary, if a bit is 0, that switch is active
|
||||
actionOutputs(SwitchByte);
|
||||
|
||||
return RXPacketL;
|
||||
}
|
||||
|
||||
|
||||
void packet_is_Error()
|
||||
{
|
||||
uint16_t IRQStatus;
|
||||
IRQStatus = LT.readIrqStatus();
|
||||
|
||||
if (IRQStatus & IRQ_RX_TIMEOUT)
|
||||
{
|
||||
Serial.print(F("RXTimeout"));
|
||||
}
|
||||
else
|
||||
{
|
||||
errors++;
|
||||
Serial.print(F("PacketError"));
|
||||
printpacketDetails();
|
||||
Serial.print(F("IRQreg,"));
|
||||
Serial.print(IRQStatus, HEX);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void printpacketDetails()
|
||||
{
|
||||
Serial.print(F(" RSSI,"));
|
||||
Serial.print(PacketRSSI);
|
||||
Serial.print(F("dBm,SNR,"));
|
||||
Serial.print(PacketSNR);
|
||||
Serial.print(F("dB,Length,"));
|
||||
Serial.print(LT.readRXPacketL());
|
||||
}
|
||||
|
||||
|
||||
void led_Flash(uint16_t flashes, uint16_t delaymS)
|
||||
{
|
||||
uint16_t index;
|
||||
|
||||
for (index = 1; index <= flashes; index++)
|
||||
{
|
||||
digitalWrite(LED1, HIGH);
|
||||
delay(delaymS);
|
||||
digitalWrite(LED1, LOW);
|
||||
delay(delaymS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void actionOutputs(uint8_t switches)
|
||||
{
|
||||
//read the recreived switch byte and toggle outputs as required
|
||||
|
||||
if (!bitRead(switches, 0))
|
||||
{
|
||||
//toggle Output state
|
||||
digitalWrite(OUTPUT0, !digitalRead(OUTPUT0)); //toggle Output state
|
||||
}
|
||||
|
||||
if (!bitRead(switches, 1))
|
||||
{
|
||||
digitalWrite(OUTPUT1, !digitalRead(OUTPUT1)); //toggle Output state
|
||||
}
|
||||
|
||||
if (!bitRead(switches, 2))
|
||||
{
|
||||
digitalWrite(OUTPUT2, !digitalRead(OUTPUT2)); //toggle Output state
|
||||
}
|
||||
|
||||
if (!bitRead(switches, 3))
|
||||
{
|
||||
digitalWrite(OUTPUT3, !digitalRead(OUTPUT3)); //toggle Output state
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setupOutputs()
|
||||
{
|
||||
//configure the output pins, if a pin is defiend in 'Settings.h' as -1, its not configured, so stays as input
|
||||
|
||||
if (OUTPUT0 >= 0)
|
||||
{
|
||||
pinMode(OUTPUT0, OUTPUT);
|
||||
}
|
||||
|
||||
if (OUTPUT1 >= 0)
|
||||
{
|
||||
pinMode(OUTPUT1, OUTPUT);
|
||||
}
|
||||
|
||||
if (OUTPUT2 >= 0)
|
||||
{
|
||||
pinMode(OUTPUT2, OUTPUT);
|
||||
}
|
||||
|
||||
if (OUTPUT3 >= 0)
|
||||
{
|
||||
pinMode(OUTPUT3, OUTPUT);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void outputCheck(uint8_t number, uint32_t ondelaymS, uint32_t offdelaymS)
|
||||
{
|
||||
uint8_t index;
|
||||
|
||||
Serial.println(F("Toggling outputs"));
|
||||
|
||||
for (index = 1; index <= number; index++)
|
||||
{
|
||||
digitalWrite(OUTPUT0, HIGH);
|
||||
delay(ondelaymS);
|
||||
digitalWrite(OUTPUT0, LOW);
|
||||
delay(offdelaymS);
|
||||
digitalWrite(OUTPUT1, HIGH);
|
||||
delay(ondelaymS);
|
||||
digitalWrite(OUTPUT1, LOW);
|
||||
delay(offdelaymS);
|
||||
digitalWrite(OUTPUT2, HIGH);
|
||||
delay(ondelaymS);
|
||||
digitalWrite(OUTPUT2, LOW);
|
||||
delay(offdelaymS);
|
||||
digitalWrite(OUTPUT3, HIGH);
|
||||
delay(offdelaymS);
|
||||
digitalWrite(OUTPUT3, LOW);
|
||||
delay(offdelaymS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
pinMode(LED1, OUTPUT);
|
||||
led_Flash(2, 125);
|
||||
|
||||
Serial.begin(9600);
|
||||
|
||||
setupOutputs();
|
||||
|
||||
outputCheck(3, 500, 100);
|
||||
|
||||
SPI.begin();
|
||||
|
||||
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
|
||||
{
|
||||
led_Flash(2, 125);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("Device error"));
|
||||
while (1)
|
||||
{
|
||||
led_Flash(50, 50); //long fast speed flash indicates device error
|
||||
}
|
||||
}
|
||||
|
||||
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate);
|
||||
|
||||
Serial.println(F("Receiver ready"));
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 19/03/20
|
||||
|
||||
This program is supplied as is, it is up to the user of the program to decide if the program is
|
||||
suitable for the intended purpose and free from errors.
|
||||
*******************************************************************************************************/
|
||||
|
||||
|
||||
//******* Setup hardware pin definitions here ! ***************
|
||||
|
||||
//These are the pin definitions for one of my own boards, the Easy Pro Mini,
|
||||
//be sure to change the definitions to match your own setup.
|
||||
|
||||
const int8_t NSS = 10; //select on LoRa device
|
||||
const int8_t NRESET = 9; //reset on LoRa device
|
||||
const int8_t RFBUSY = 7; //RF busy on LoRa device
|
||||
const int8_t DIO1 = 3; //DIO1 on LoRa device, used for RX and TX done
|
||||
const int8_t LED1 = 8; //On board LED, logic high is on
|
||||
|
||||
#define LORA_DEVICE DEVICE_SX1280 //this is the device we are using
|
||||
|
||||
const int8_t OUTPUT0 = 2;
|
||||
const int8_t OUTPUT1 = 4;
|
||||
const int8_t OUTPUT2 = A3;
|
||||
const int8_t OUTPUT3 = A2;
|
||||
|
||||
const uint32_t RXIdentity = 1234554321; //define an identity number, the receiver must use the same number
|
||||
//range is 0 to 4294967296
|
||||
|
||||
|
||||
|
||||
//******* Setup LoRa Test Parameters Here ! ***************
|
||||
|
||||
//LoRa Modem Parameters
|
||||
#define Frequency 2445000000 //frequency of transmissions
|
||||
#define Offset 0 //offset frequency for calibration purposes
|
||||
#define Bandwidth LORA_BW_0400 //LoRa bandwidth
|
||||
#define SpreadingFactor LORA_SF7 //LoRa spreading factor
|
||||
#define CodeRate LORA_CR_4_5 //LoRa coding rate
|
||||
|
||||
#define TXpower 10 //power for transmissions in dBm
|
||||
@ -0,0 +1,189 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 19/03/20
|
||||
|
||||
This program is supplied as is, it is up to the user of the program to decide if the program is
|
||||
suitable for the intended purpose and free from errors.
|
||||
*******************************************************************************************************/
|
||||
|
||||
/*******************************************************************************************************
|
||||
Program Operation - This is a remote control transmitter that uses a LoRa link to transmit the positions
|
||||
from a simple joystick to a remote receiver. The receiver uses the sent joystick positions to adjust the
|
||||
positions of servos. The postions of the joysticks potentiometers on the transmitter are read with the
|
||||
analogueRead() function.
|
||||
|
||||
If the joystick has a switch, often made by pressing on the joystick, then this can be used to remote
|
||||
control an output on the receiver. The switch is read by an interrupt, the interrupt routine sets a flag
|
||||
byte which is read in loop().
|
||||
|
||||
The program is intended as a proof of concept demonstration of how to remote control servos, the program
|
||||
is not designed as a practical remote control device for RC model cars for instance.
|
||||
|
||||
To have the transmitter program print out the values read from the joystick, comment in the line;
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
Which is just above the loop() function. With the DEBUG enabled the transmission rate, the rate at which
|
||||
the control packets are transmitted will be slowed down.
|
||||
|
||||
To reduce the risk of the receiver picking up LoRa packets from other sources, the packet sent contains a
|
||||
'TXidentity' number, valid values are 0 - 65535. The receiver must be setup with the matching identity
|
||||
number or the received packets will be ignored.
|
||||
|
||||
The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file. These settings
|
||||
are not necessarily optimised for long range.
|
||||
|
||||
Serial monitor baud rate is set at 115200.
|
||||
*******************************************************************************************************/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <SX128XLT.h>
|
||||
#include "Settings.h"
|
||||
#include <ProgramLT_Definitions.h>
|
||||
|
||||
SX128XLT LT;
|
||||
|
||||
#include "PinChangeInterrupt.h" //get the library here; https://github.com/NicoHood/PinChangeInterrupt
|
||||
|
||||
uint32_t TXpacketCount;
|
||||
uint8_t TXPacketL;
|
||||
|
||||
uint8_t joystickX1value; //variable to read the value from the analog pin
|
||||
uint8_t joystickY1value; //variable to read the value from the analog pin
|
||||
|
||||
volatile bool switch1flag = false;
|
||||
|
||||
//#define DEBUG //comment in thie line (remove the two // at the beggining) for debug output
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
uint8_t switchByte = 0xFF;
|
||||
|
||||
joystickX1value = (uint8_t) (analogRead(joystickX1) / 4) ; //read the joystick X1 pot, turn 0-1023 into 0 to 255
|
||||
joystickY1value = (uint8_t) (analogRead(joystickY1) / 4); //read the joystick Y1 pot
|
||||
|
||||
if (switch1flag)
|
||||
{
|
||||
bitClear(switchByte, 1); //if the switch is down clear the bit
|
||||
digitalWrite(LED1, HIGH); //turn on LED as switch indicator
|
||||
switch1flag = false;
|
||||
}
|
||||
|
||||
if (!sendJoystickPacket(joystickX1value, joystickY1value, switchByte))
|
||||
{
|
||||
Serial.print(F("Send Error - IRQreg,"));
|
||||
Serial.print(LT.readIrqStatus(), HEX);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t sendJoystickPacket(uint16_t X1value, uint16_t Y1value, uint8_t switches)
|
||||
{
|
||||
//The SX12XX buffer is filled with variables of a known type and in a known sequence. Make sure the
|
||||
//receiver uses the same variable types and sequence to read variables out of the receive buffer.
|
||||
|
||||
LT.startWriteSXBuffer(0); //start the write packet to buffer process
|
||||
LT.writeUint8(RControl1); //this is the packet type
|
||||
LT.writeUint8(TXIdentity); //this value represents the transmitter number
|
||||
LT.writeUint8(X1value); //this byte contains joystick pot AD X1 value to be sent
|
||||
LT.writeUint8(Y1value); //this byte contains joystick pot AD Y1 value to be sent
|
||||
LT.writeUint8(switches); //switches value
|
||||
LT.endWriteSXBuffer(); //close the packet, thee are 5 bytes to send
|
||||
|
||||
//now transmit the packet, 10 second timeout, and wait for it to complete sending
|
||||
TXPacketL = LT.transmitSXBuffer(0, PacketLength, 10000, TXpower, WAIT_TX);
|
||||
|
||||
#ifdef DEBUG
|
||||
Serial.print(TXIdentity);
|
||||
Serial.print(F(",X1,"));
|
||||
Serial.print(joystickX1value);
|
||||
Serial.print(F(",Y1,"));
|
||||
Serial.print(joystickY1value);
|
||||
Serial.print(F(","));
|
||||
Serial.print(switches, BIN);
|
||||
Serial.println();
|
||||
#endif
|
||||
|
||||
digitalWrite(LED1, LOW); //LED off, may have been on due to switch press
|
||||
|
||||
return TXPacketL; //TXPacketL will be 0 if there was an error sending
|
||||
}
|
||||
|
||||
|
||||
void led_Flash(uint16_t flashes, uint16_t delaymS)
|
||||
{
|
||||
uint16_t index;
|
||||
for (index = 1; index <= flashes; index++)
|
||||
{
|
||||
digitalWrite(LED1, HIGH);
|
||||
delay(delaymS);
|
||||
digitalWrite(LED1, LOW);
|
||||
delay(delaymS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void attachInterrupts()
|
||||
{
|
||||
if (SWITCH1 >= 0)
|
||||
{
|
||||
attachPCINT(digitalPinToPCINT(SWITCH1), wake1, FALLING);
|
||||
switch1flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void detachInterrupts()
|
||||
{
|
||||
if (SWITCH1 >= 0)
|
||||
{
|
||||
detachPCINT(digitalPinToPCINT(SWITCH1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void wake1()
|
||||
{
|
||||
switch1flag = true;
|
||||
}
|
||||
|
||||
|
||||
void setupSwitches()
|
||||
{
|
||||
if (SWITCH1 >= 0)
|
||||
{
|
||||
pinMode(SWITCH1, INPUT_PULLUP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
pinMode(LED1, OUTPUT);
|
||||
led_Flash(2, 125);
|
||||
|
||||
setupSwitches();
|
||||
|
||||
Serial.begin(115200);
|
||||
|
||||
SPI.begin();
|
||||
|
||||
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
|
||||
{
|
||||
led_Flash(2, 125);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("Device error"));
|
||||
while (1)
|
||||
{
|
||||
led_Flash(50, 50);
|
||||
}
|
||||
}
|
||||
|
||||
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate);
|
||||
|
||||
attachInterrupts();
|
||||
|
||||
Serial.println(F("35_Remote_Control_Servo_Transmitter ready"));
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 19/03/20
|
||||
|
||||
This program is supplied as is, it is up to the user of the program to decide if the program is
|
||||
suitable for the intended purpose and free from errors.
|
||||
*******************************************************************************************************/
|
||||
|
||||
|
||||
//******* Setup hardware pin definitions here ! ***************
|
||||
|
||||
//These are the pin definitions for one of my own boards, the Easy Pro Mini,
|
||||
//be sure to change the definitions to match your own setup.
|
||||
|
||||
const int8_t NSS = 10; //select on LoRa device
|
||||
const int8_t NRESET = 9; //reset on LoRa device
|
||||
const int8_t RFBUSY = 7; //RF busy on LoRa device
|
||||
const int8_t DIO1 = 3; //DIO1 on LoRa device, used for RX and TX done
|
||||
const int8_t LED1 = 8; //On board LED, logic high is on
|
||||
|
||||
#define LORA_DEVICE DEVICE_SX1280 //this is the device we are using
|
||||
|
||||
const int8_t joystickX1 = A2; //analog pin for the joystick 1 X pot
|
||||
const int8_t joystickY1 = A3; //analog pin for the joystick 1 Y pot
|
||||
const int8_t SWITCH1 = 2; //switch on joystick, set to -1 if not used
|
||||
|
||||
const uint32_t TXIdentity = 123 ; //define a transmitter number, the receiver must use the same number
|
||||
//range is 0 to 255
|
||||
|
||||
|
||||
|
||||
//******* Setup LoRa Test Parameters Here ! ***************
|
||||
|
||||
//LoRa Modem Parameters
|
||||
#define Frequency 2445000000 //frequency of transmissions
|
||||
#define Offset 0 //offset frequency for calibration purposes
|
||||
#define Bandwidth LORA_BW_0400 //LoRa bandwidth
|
||||
#define SpreadingFactor LORA_SF7 //LoRa spreading factor
|
||||
#define CodeRate LORA_CR_4_5 //LoRa coding rate
|
||||
|
||||
const uint8_t PacketLength = 5; //packet length is fixed
|
||||
const int8_t TXpower = 10; //LoRa transmit power in dBm
|
||||
@ -0,0 +1,244 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 19/03/20
|
||||
|
||||
This program is supplied as is, it is up to the user of the program to decide if the program is
|
||||
suitable for the intended purpose and free from errors.
|
||||
*******************************************************************************************************/
|
||||
|
||||
/*******************************************************************************************************
|
||||
Program Operation - This is a remote control receiver that uses a LoRa link to control the positions of
|
||||
servos sent from a remote transmitter.
|
||||
|
||||
If the transmitter joystick has a switch, often made by pressing on the joystick, then this can be used
|
||||
to remote control an output on the receiver.
|
||||
|
||||
The program is intended as a proof of concept demonstration of how to remote control servos, the program
|
||||
is not designed as a practical remote control device for RC model cars for instance.
|
||||
|
||||
To have the receiver program print out the joystick values (0-255) read from the received packet, comment
|
||||
in the line;
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
Which is just above the loop() function. With the DEBUG enabled then there is a possibility that some
|
||||
transmitted packets will be missed. With the DEBUG line enabled to servos should also sweep to and fro 3
|
||||
times at program start-up.
|
||||
|
||||
To reduce the risk of the receiver picking up LoRa packets from other sources, the packet sent contains a
|
||||
'TXidentity' number, valid values are 0 - 255. The receiver must be setup with the matching RXIdentity
|
||||
number in Settings.h or the received packets will be ignored.
|
||||
|
||||
The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file. These settings
|
||||
are not necessarily optimised for long range.
|
||||
|
||||
Serial monitor baud rate is set at 115200.
|
||||
*******************************************************************************************************/
|
||||
|
||||
#define programversion "V1.0"
|
||||
|
||||
#include <SPI.h>
|
||||
#include <SX128XLT.h>
|
||||
#include "Settings.h"
|
||||
#include <ProgramLT_Definitions.h>
|
||||
|
||||
SX128XLT LT;
|
||||
|
||||
#include <Servo.h>
|
||||
Servo ServoX1; //create the servo object
|
||||
Servo ServoY1; //create the servo object
|
||||
|
||||
uint8_t joystickX1value; //variable to read the value from the analog pin
|
||||
uint8_t joystickY1value; //variable to read the value from the analog pin
|
||||
uint8_t RXPacketL; //length of received packet
|
||||
uint8_t RXPacketType; //type of received packet
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
uint16_t IRQStatus;
|
||||
|
||||
RXPacketL = LT.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort
|
||||
|
||||
while (!digitalRead(DIO1)); //wait for DIO1 to go high
|
||||
|
||||
if (LT.readIrqStatus() == (IRQ_RX_DONE + IRQ_HEADER_VALID + IRQ_PREAMBLE_DETECTED) )
|
||||
{
|
||||
packet_is_OK();
|
||||
}
|
||||
else
|
||||
{
|
||||
packet_is_Error();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
uint8_t packet_is_OK()
|
||||
{
|
||||
//packet has been received, now read from the SX12xx Buffer using the same variable type and
|
||||
//order as the transmit side used.
|
||||
uint8_t TXIdentity;
|
||||
uint16_t pulseX1, pulseY1;
|
||||
uint8_t switchByte = 0xFF; //this is the transmitted switch values, bit 0 = Switch0 etc
|
||||
|
||||
LT.startReadSXBuffer(0); //start buffer read at location 0
|
||||
RXPacketType = LT.readUint8(); //read in the packet type
|
||||
TXIdentity = LT.readUint8(); //read in the transmitter number
|
||||
joystickX1value = LT.readUint8(); //this byte contains joystick pot AD X1 value sent
|
||||
joystickY1value = LT.readUint8(); //this byte contains joystick pot AD Y1 value sent
|
||||
switchByte = LT.readUint8(); //read in the Switch values
|
||||
RXPacketL = LT.endReadSXBuffer(); //end buffer read
|
||||
|
||||
#ifdef DEBUG
|
||||
Serial.print(TXIdentity);
|
||||
Serial.print(F(",X1,"));
|
||||
Serial.print(joystickX1value);
|
||||
Serial.print(F(",Y1,"));
|
||||
Serial.print(joystickY1value);
|
||||
Serial.print(F(","));
|
||||
Serial.print(switchByte, BIN);
|
||||
Serial.println();
|
||||
#endif
|
||||
|
||||
|
||||
if (RXPacketType != RControl1)
|
||||
{
|
||||
Serial.print(F("Packet type "));
|
||||
Serial.println(RXPacketType);
|
||||
led_Flash(5, 25); //short fast speed flash indicates wrong packet type
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (TXIdentity != RXIdentity)
|
||||
{
|
||||
Serial.print(F("TX"));
|
||||
Serial.print(TXIdentity);
|
||||
Serial.println(F("?"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
//actionServos
|
||||
pulseX1 = map(joystickX1value, 0, 255, 1000, 2000); //scale the numbers from the joystick
|
||||
ServoX1.writeMicroseconds(pulseX1);
|
||||
pulseY1 = map(joystickY1value, 0, 255, 1000, 2000); //scale the numbers from the joystick
|
||||
ServoY1.writeMicroseconds(pulseY1); //move the servo to position
|
||||
|
||||
//actionOutputs
|
||||
if (!bitRead(switchByte, 1))
|
||||
{
|
||||
digitalWrite(OUTPUT1, !digitalRead(OUTPUT1)); //Toggle Output state
|
||||
}
|
||||
|
||||
return RXPacketL;
|
||||
}
|
||||
|
||||
|
||||
void packet_is_Error()
|
||||
{
|
||||
uint16_t IRQStatus;
|
||||
int16_t PacketRSSI;
|
||||
IRQStatus = LT.readIrqStatus();
|
||||
|
||||
if (IRQStatus & IRQ_RX_TIMEOUT)
|
||||
{
|
||||
Serial.print(F("RXTimeout"));
|
||||
}
|
||||
else
|
||||
{
|
||||
PacketRSSI = LT.readPacketRSSI(); //read the signal strength of the received packet
|
||||
Serial.print(F("Err,"));
|
||||
Serial.print(PacketRSSI);
|
||||
Serial.print(F("dBm"));
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
|
||||
void setupOutputs()
|
||||
{
|
||||
//configure the output pins, if a pin is defiend in 'Settings.h' as -1, its not configured, so stays as input
|
||||
if (OUTPUT1 >= 0)
|
||||
{
|
||||
pinMode(OUTPUT1, OUTPUT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void led_Flash(uint16_t flashes, uint16_t delaymS)
|
||||
{
|
||||
uint16_t index;
|
||||
|
||||
for (index = 1; index <= flashes; index++)
|
||||
{
|
||||
digitalWrite(LED1, HIGH);
|
||||
delay(delaymS);
|
||||
digitalWrite(LED1, LOW);
|
||||
delay(delaymS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void sweepTest(uint8_t num)
|
||||
{
|
||||
uint16_t index1, index2;
|
||||
for (index1 = 1; index1 <= num; index1++)
|
||||
{
|
||||
for (index2 = 900; index2 <= 2100; index2++)
|
||||
{
|
||||
ServoX1.writeMicroseconds(index2);
|
||||
ServoY1.writeMicroseconds(index2);
|
||||
}
|
||||
|
||||
delay(1000);
|
||||
|
||||
for (index2 = 2100; index2 >= 900; index2--)
|
||||
{
|
||||
ServoX1.writeMicroseconds(index2);
|
||||
ServoY1.writeMicroseconds(index2);
|
||||
}
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
pinMode(LED1, OUTPUT);
|
||||
led_Flash(2, 125);
|
||||
|
||||
setupOutputs();
|
||||
|
||||
Serial.begin(115200);
|
||||
|
||||
ServoX1.attach(pinservoX1); //connect pin pinservoX1 to ServoX1 object
|
||||
ServoY1.attach(pinservoY1); //connect pin pinservoY1 to ServoY1 object
|
||||
|
||||
#ifdef DEBUG
|
||||
Serial.println(F("Servo sweep test"));
|
||||
sweepTest(3);
|
||||
#endif
|
||||
|
||||
SPI.begin();
|
||||
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
|
||||
{
|
||||
led_Flash(2, 125);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("Device error"));
|
||||
while (1)
|
||||
{
|
||||
led_Flash(50, 50); //long fast speed flash indicates device error
|
||||
}
|
||||
}
|
||||
|
||||
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate);
|
||||
|
||||
Serial.println(F("36_Remote_Control_Servo_Receiver ready"));
|
||||
Serial.println();
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 19/03/20
|
||||
|
||||
This program is supplied as is, it is up to the user of the program to decide if the program is
|
||||
suitable for the intended purpose and free from errors.
|
||||
*******************************************************************************************************/
|
||||
|
||||
|
||||
//******* Setup hardware pin definitions here ! ***************
|
||||
|
||||
|
||||
//These are the pin definitions for one of my own boards, the Easy Pro Mini,
|
||||
//be sure to change the definitions to match your own setup.
|
||||
|
||||
const int8_t NSS = 10; //select on LoRa device
|
||||
const int8_t NRESET = 9; //reset on LoRa device
|
||||
const int8_t RFBUSY = 7; //RF busy on LoRa device
|
||||
const int8_t DIO1 = 3; //DIO1 on LoRa device, used for RX and TX done
|
||||
const int8_t LED1 = 8; //On board LED, logic high is on
|
||||
|
||||
#define LORA_DEVICE DEVICE_SX1280 //this is the device we are using
|
||||
|
||||
const int8_t pinservoX1 = 2; //pin for controlling servo X1
|
||||
const int8_t pinservoY1 = 4; //pin for controlling servo Y1
|
||||
const int8_t OUTPUT1 = 8; //this output toggles when joystick switch is pressed on receiver
|
||||
|
||||
const uint16_t RXIdentity = 123; //define a receiver number, the transmitter must use the same number
|
||||
//range is 0 to 255
|
||||
|
||||
//******* Setup LoRa Test Parameters Here ! ***************
|
||||
|
||||
//LoRa Modem Parameters
|
||||
#define Frequency 2445000000 //frequency of transmissions
|
||||
#define Offset 0 //offset frequency for calibration purposes
|
||||
#define Bandwidth LORA_BW_0400 //LoRa bandwidth
|
||||
#define SpreadingFactor LORA_SF7 //LoRa spreading factor
|
||||
#define CodeRate LORA_CR_4_5 //LoRa coding rate
|
||||
|
||||
const uint8_t PacketLength = 5; //packet length is fixed
|
||||
Reference in New Issue
Block a user