Browse Source

initiate...

master
Englebert 4 years ago
commit
b5ab8bdceb
  1. 423
      OpenFlightRX.ino

423
OpenFlightRX.ino

@ -0,0 +1,423 @@
/*
* Filename: OpenFlightRX.ino
* Description:
* To receive signals from LoRA module and configurable over WiFi
* Author: Englebert
* Date: Fri 25 Sep 2020 04:22:40 PM +08
*
* TODO/Wish Lists:
* 1. BT Serial Relay - For INAV
* 2. WiFi Configuration - NOT going to work because going to cause issue on LoRA speed. Demolish the idea.
* 3. Status Display -
* 4. Sending SBUS over ESP32
* 5. Serial Configuration for the 1st time or debugging
* 6. Configuration over LoRA signals using the last byte.
*
*
* REF:
* WiFi AP - https://randomnerdtutorials.com/esp32-access-point-ap-web-server/
*
* Frequency for RFM95W:
* 900MHz ~ 930MHz (900000000Hz - 930000000Hz)
*
* EEPROM Format:
*
* HFFFFS
*
* H: Header. Must be equal to 0x70. Else this will be consider not valid
* FFFF: 4 bytes Frequency Channel Number
* S: Sync word. Key to prevent other LoRA channels listened. Valid Range: 0x00 ~ 0xFF
*
* Signal Format:
* TTYYPPRRS
* TYPRS----
* Hell0 012
*/
// LoRA Module Needed
#include <SPI.h>
#include <LoRa.h>
// Display
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// For storing configurations and settings
#include <EEPROM.h>
//define the pins used by the transceiver module
#define SS 5
#define RST 14
#define DIO0 2
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
uint64_t last_received_lora = 0;
uint64_t last_display = 0;
uint32_t uptime = 0;
uint32_t lora_packets = 0;
uint32_t lora_packets_per_second = 0;
uint32_t delayed = 0;
uint32_t frequency = 900000000;
uint8_t syncword = 0x00;
bool stop_delay = false;
bool tx_mode = false;
bool oled = true;
uint8_t counter = 0;
String LoRaData;
// Example:
// String a = explode("Data|Raw1|Raw2", "|", 4);
String explode(String data, char separator, int index) {
int found = 0;
int strIndex[] = {0, -1};
int maxIndex = data.length() - 1;
for(int i = 0; i <= maxIndex && found<=index; i++) {
if(data.charAt(i) == separator || i == maxIndex) {
found++;
strIndex[0] = strIndex[1]+1;
strIndex[1] = (i == maxIndex) ? i+1 : i;
}
}
return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}
void showFreeMem() {
Serial.println(F(""));
Serial.print(F("FREE Memory: "));
Serial.println(ESP.getFreeHeap());
}
void showHelp() {
Serial.println(F("*** Help ***"));
Serial.print(F("free - Show FREE memory\nhelp - this page\nreboot - restart the device\nsetfreq - change frequency and syncword\ngetfreq - retrive current settings\ntx - TX Mode\nrx - RX Mode\n"));
}
void resetFunc(void) {
ESP.restart();
}
void getOpenFlightRXSettings(void) {
uint16_t addr = 0x00;
// If heder not the same then use the default settings
if(EEPROM.read(addr) != 0x70) {
return;
}
// Retriving data
frequency = (EEPROM.read(0x01) << 24) | (EEPROM.read(0x02) << 16) | (EEPROM.read(0x03) << 8) | (EEPROM.read(0x04));
/*
Serial.println(frequency);
Serial.println(EEPROM.read(0x01), HEX);
Serial.println(EEPROM.read(0x02), HEX);
Serial.println(EEPROM.read(0x03), HEX);
Serial.println(EEPROM.read(0x04), HEX);
*/
// Default to minimum if less then 900MHz
if(frequency < 900000000) frequency = 900000000;
// Default to maximum if more than 930MHz
if(frequency > 930000000) frequency = 930000000;
// Sync Word
syncword = EEPROM.read(0x05);
// Receiver or TX mode
tx_mode = EEPROM.read(0x06) & 0x01;
// Debug...
Serial.print(F("Freq:"));
Serial.print(frequency);
Serial.println(F("Hz"));
Serial.print(F("Sync:"));
Serial.println(syncword, HEX);
Serial.print(F("Mode:"));
Serial.println(tx_mode, DEC);
}
void setOpenFlightRXSettings(void) {
uint8_t addr = 0x00;
// Header
write_data(addr++, 0x70);
// Frequency
write_data(addr++, ((frequency & 0xFF000000) >> 24 ));
Serial.println(EEPROM.read(addr - 1), HEX);
write_data(addr++, ((frequency & 0x00FF0000) >> 16 ));
Serial.println(EEPROM.read(addr - 1), HEX);
write_data(addr++, ((frequency & 0x0000FF00) >> 8));
Serial.println(EEPROM.read(addr - 1), HEX);
write_data(addr++, ((frequency & 0x000000FF)));
Serial.println(EEPROM.read(addr - 1), HEX);
// Sync Word
write_data(addr++, syncword);
Serial.println(EEPROM.read(addr - 1), HEX);
// TX Mode/RX Mode
write_data(addr++, (tx_mode));
Serial.println(EEPROM.read(addr - 1), HEX);
Serial.println(F("**** New Settings Saved *****"));
Serial.print(F("FREQ:"));
Serial.println(frequency);
Serial.print(F("SYNC:"));
Serial.println(syncword, HEX);
Serial.print(F("MODE:"));
Serial.println(tx_mode, DEC);
}
void resetConfig(void) {
// Erase 1st byte will do.
EEPROM.write(0x00, 0x00);
EEPROM.commit();
}
void write_data(uint16_t addr, uint8_t val) {
// Only enabel the timerAlarmDisable if crash in future....
// timerAlarmDisable(timer);
EEPROM.write(addr, val);
EEPROM.commit();
// timerAlarmEnable(timer);
}
/* create a hardware timer */
hw_timer_t * timer = NULL;
void IRAM_ATTR onTimer(){
uptime++;
if(!stop_delay) delayed++;
lora_packets_per_second = lora_packets;
lora_packets = 0;
}
void setup() {
//initialize Serial Monitor
Serial.begin(115200);
while (!Serial);
Serial.println(F("OpenFlightRX v1.0 @ 2020"));
// Define a range for the EEPROM (512 bytes). May be can be lesser
EEPROM.begin(512);
// Getting settings and starts the system
getOpenFlightRXSettings();
// Setup LoRa transceiver module
LoRa.setPins(SS, RST, DIO0);
// while (!LoRa.begin(914990000)) {
Serial.print(F("Starting up LoRA"));
while(!LoRa.begin(frequency)) {
Serial.print(F("."));
delay(500);
}
Serial.println(F("OK"));
// The sync word assures you don't get LoRa messages from other LoRa transceivers
// ranges from 0-0xFF
LoRa.setSyncWord(syncword);
LoRa.setPreambleLength(8);
// LoRa.setSpreadingFactor(6);
// LoRa.setSpreadingFactor(7);
//7.8E3, 10.4E3, 15.6E3, 20.8E3, 31.25E3, 41.7E3, 62.5E3, 125E3, and 250E3.
// LoRa.setSignalBandwidth(250E3);
// LoRa.setCodingRate4(5);
// LoRa.setSpreadingFactor(9);
// LoRa.setSignalBandwidth(62.5E3);
// LoRa.setCodingRate4(8);
/* Use 1st timer of 4 */
/* 1 tick take 1/(80MHZ/80) = 1us so we set divider 80 and count up */
timer = timerBegin(0, 80, true);
/* Attach onTimer function to our timer */
timerAttachInterrupt(timer, &onTimer, true);
/* Set alarm to call onTimer function every second 1 tick is 1us => 1 second is 1000000us */
/* Repeat the alarm (third parameter) */
timerAlarmWrite(timer, 1000000, true);
/* Start an alarm */
timerAlarmEnable(timer);
/**** TO BE COMMENTED OUT ****/
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 not found"));
oled = false;
}
if(oled) {
// Clear the buffer
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("START RX LORA...");
display.display();
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("DONE!");
display.display();
}
}
void loop() {
if(!tx_mode) {
// try to parse packet
int packetSize = LoRa.parsePacket();
if (packetSize) {
// received a packet
// Serial.print("Received packet '");
if(!stop_delay) {
stop_delay = true;
}
// read packet
while (LoRa.available()) {
LoRaData = LoRa.readString();
// Serial.print(LoRaData);
}
lora_packets++;
last_received_lora = millis();
// print RSSI of packet
// Serial.print("' with RSSI ");
// Serial.println(LoRa.packetRssi());
// if(millis() - last_display > 1000) {
if(oled) {
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("RSSI:");
display.print(LoRa.packetRssi());
display.setCursor(0, 16);
display.print("SNR:");
display.print(LoRa.packetSnr());
display.setTextSize(1);
display.setCursor(0, 32);
display.print("Data:");
display.print(LoRaData);
display.setCursor(0, 48);
display.print("Packet/s:");
display.print(lora_packets_per_second);
display.setCursor(0, 40);
display.print("Delayed:");
display.print(delayed);
display.setCursor(0, 56);
display.print("Up:");
display.print(uptime);
display.setCursor(64, 56);
display.print("Band: ");
display.print(LoRa.packetFrequencyError());
display.display();
}
/*
Serial.print(F("RSSI:"));
Serial.println(LoRa.packetRssi());
Serial.print(F("SNR:"));
Serial.println(LoRa.packetSnr());
Serial.print(F("Data:"));
Serial.println(LoRaData);
Serial.print(F("Packet/s:"));
Serial.println(lora_packets_per_second);
*/
last_display = millis();
} else {
if(millis() - last_received_lora > 1000) {
if(oled) {
display.clearDisplay();
display.setCursor(0, 0);
display.setTextColor(SSD1306_WHITE);
display.print("SIGNAL LOST");
display.display();
}
}
}
} else {
// TX mode. For distance checking via remote ;)
LoRa.beginPacket();
LoRa.print("HELLO ");
LoRa.print(counter);
LoRa.endPacket();
if(oled) {
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("TX MODE");
display.display();
}
counter++;
delay(25);
}
// Processing CLI
if(Serial.available() > 0){
String serial_commands_string = Serial.readStringUntil('\n');
serial_commands_string.trim();
String serial_command = explode(serial_commands_string, ' ', 0);
if(serial_command == "reset") {
Serial.println(F("Clearing EEPROM settings..."));
resetConfig();
resetFunc();
} else if(serial_command == "free") {
showFreeMem();
} else if(serial_command == "help") {
showHelp();
} else if(serial_command == "reboot") {
resetFunc();
} else if(serial_command == "setfreq") {
String frequency_raw = explode(serial_commands_string, ' ', 1);
String syncword_raw = explode(serial_commands_string, ' ', 2);
if(
frequency_raw.length() > 0 &&
syncword_raw.length() > 0) {
frequency = frequency_raw.toInt();
syncword = (uint8_t) (syncword_raw.toInt() & 0xFF);
setOpenFlightRXSettings();
}
} else if(serial_command == "getfreq") {
Serial.print(F("FREQ:"));
Serial.println(frequency);
Serial.print(F("SYNC:"));
Serial.println(syncword, HEX);
} else if(serial_command == "tx") {
tx_mode = true;
setOpenFlightRXSettings();
} else if(serial_command == "rx") {
tx_mode = false;
setOpenFlightRXSettings();
}
}
}
Loading…
Cancel
Save