Merge branches 'main' and 'feature/add-sx1280PA' of https://github.com/Genaker/LoraSA into feature/add-sx1280PA

This commit is contained in:
Egor Shitikov
2024-09-22 14:17:32 -07:00
8 changed files with 299 additions and 60 deletions

102
README.md
View File

@@ -1,5 +1,15 @@
# Lora SA(Spectrum Analyzer)
# Supportted boards:
- Heltec Lora V3 128 x 64 OLED
- Heltec Wireless Stick V3 64 x 32 (Not tested)
- Heltec Wireless Stick Lite V3 No Display (Not Tested)
- Heltec Vision Master E290 - e-Ink 296 x 128 (No OSD)
- Heltec Vision MAster T190 - color TFT 320X170 (No OSD)
- LilyGo Radio Lora T3S3 V.2 SX1262
- LilyGo Radio Lora T3S3 V.2 SX1280
- LilyGo Radio Lora T3_V1.6.1 SX1276 (Not Tested)
## RF Spectrum Analyzer using Lora Radio
<img src="https://github.com/user-attachments/assets/4caeb467-1964-4184-ab20-ba68b97144aa" alt="LORA hardware" width="200"/>
@@ -213,3 +223,95 @@ or buy :
![image](https://github.com/user-attachments/assets/a1e00b51-5566-4ff5-98fe-67eaeb5bc81f)
We are using pin 41 as a Buzzer trigger. Connect buzzer + leg with pin 41 and - leg with the ground (GND). You can change the buzzer pin in the code.
## Analog FPV OSD (ON SCREEN DISPLAY)
To Enable OSD, Uncomment these lines </br>
```
// #define OSD_ENABLED true
```
**OSD sidebar enabled/disable**
comment or uncomment this line
```
#define OSD_SIDE_BAR true
```
Or you can set this and other variables as a build parameter:
```
build_flags =
-DOSD_ENABLED
```
## DFRobot OSD Wiring
**Heltec V3 -> DFRobot OSD** <br />
GND -> GND <br />
3V3 -> 3V3 <br />
26 -> SCK <br />
34 ->MOSI <br />
33 ->MISO <br />
47 -> D3 <br />
More photos you can see there: <br />
https://github.com/Genaker/LoraSA/issues/11
![image](https://github.com/user-attachments/assets/3ba8230d-21de-449d-881b-bdc5f5b4907d)
# Camera to DF robot Wiring
**Camera -> DFRobotOSD** <br />
Video out -> In <br />
GND -> GND <br />
3v3 -> 3V3 Heltec or some 3v on FPV <br />
# DFRobot to Drone or VTX(video transmitter)
**DF Robot -> VTX or** <br />
Video Out - Video IN <br />
```
// SPI pins
#define OSD_CS 47
#define OSD_MISO 33
#define OSD_MOSI 34
#define OSD_SCK 26
```
## Joystick Wiring
https://www.aliexpress.us/item/2251832815289133.html
https://www.amazon.com/dp/B00P7QBGD2
**Loystic -> Heltec V3** <br />
SW -> 46 <br />
VRX -> 19 <br />
VRY -> X has not been implemented yet <br />
+5v -> 5V <br />
GND -> GND <br />
## Buzzer/Beeper Wiring
TMB12A03 - in my case. Low voltage is better. <br />
**Buzzer -> Heltec V3** <br />
(+) -> 41 <br />
GND (another) -> GND <br />
## Select Board to build
Select Visual Code environment:
![image](https://github.com/user-attachments/assets/3765615b-3a80-4270-bc74-8f6eae2b8458)
Edit **paltformio.io** uncommenting/selecting your sources
```
[platformio]
; for env:vision-master-e190
; src_dir = tft_src
; for env:vision-master-e290
; src_dir = eink_src
; for env:heltec_wifi_lora_32_V3
; src_dir = src ;;Default
```
for LilyGo use env:heltec_wifi_lora_32_V3
# WiFi and Bluetooth BT Scanning
Works only with OSD enabled <br/>
Uncomment this lines
```
// #define OSD_ENABLED true
// #define WIFI_SCANNING_ENABLED true
// #define BT_SCANNING_ENABLED true
```

View File

@@ -13,8 +13,67 @@
#ifndef _DFRobot_OSD_H_
#define _DFRobot_OSD_H_
#define MAX_POWER_LEVELS 33
#include <Arduino.h>
/*Define Custom characters Example*/
static const int buf0[36] = {0x02, 0x80, 0x02, 0x40, 0x7F, 0xE0, 0x42, 0x00,
0x42, 0x00, 0x7A, 0x40, 0x4A, 0x40, 0x4A, 0x80,
0x49, 0x20, 0x5A, 0xA0, 0x44, 0x60, 0x88, 0x20};
static constexpr uint16_t levels[10] = {
0x105, // 0
0x10E, // 1
0x10D, // 2
0x10C, // 3
0x10B, // 4
0x10A, // 5
0x109, // 6
0x108, // 7
0x107, // 8
0x106, // 9
};
static constexpr uint16_t power_level[MAX_POWER_LEVELS + 1] = {
0x10E, // 0
0x10E, // 1
0x10D, // 2
0x10C, // 3
0x10B, // 4
0x10A, // 5
0x109, // 6
0x108, // 7
0x107, // 8
0x106, // 9 not using 106 to accent rise
// new line
0x10E, // 10
0x10D, // 11
0x10C, // 12
0x10B, // 13
0x10A, // 14
0x109, // 15
0x108, // 16
0x107, // 17
0x106, // 18 not using 106
// new line
0x10E, // 19
0x10D, // 20
0x10C, // 21
0x10B, // 22
0x10A, // 23
0x109, // 24
0x108, // 25
0x107, // 26
0x106, // 27
0x105, // 28 ---
0x105, // 29
0x105, // 30
0x105, // 31
0x105, // 32
0x105 // 33
};
// #define ENABLE_DBG //!< Open this macro and you can see the details of the program
#ifdef ENABLE_DBG
#define DBG(...) \

69
lib/scan/scan.cpp Normal file
View File

@@ -0,0 +1,69 @@
#ifndef LORASA_CORE_CPP
#define LORASA_CORE_CPP
#include "scan.h"
#include <cstdint>
#include <cstring>
#include <stdlib.h>
float Scan::getRSSI() { return 0.1; }
uint16_t Scan::rssiMethod(uint16_t *result)
{
memset(result, 0, res_size * sizeof(uint16_t));
int result_index = 0;
//
uint16_t max_signal = 65535;
// N of samples
for (int r = 0; r < SAMPLES_RSSI; r++)
{
float rssi = getRSSI();
if (rssi < -65535)
rssi = -65535;
uint16_t abs_rssi = abs(rssi);
if (abs_rssi < max_signal)
{
max_signal = abs_rssi;
}
// ToDO: check if 4 is correct value for 33 power bins
// Now we have more space because we are ignoring low dB values
// we can / 3 default 4
if (RSSI_OUTPUT_FORMULA == 1)
{
result_index =
/// still not clear formula but it works
uint8_t(abs(rssi) / 4);
}
else if (RSSI_OUTPUT_FORMULA == 2)
{
if (rssi > HI_RSSI_THRESHOLD)
{
rssi = HI_RSSI_THRESHOLD;
}
else if (rssi < LO_RSSI_THRESHOLD)
{
rssi = LO_RSSI_THRESHOLD;
}
result_index = uint8_t((HI_RSSI_THRESHOLD - rssi) * scale);
}
if (result_index >= res_size)
{
// Maximum index possible
result_index = res_size - 1;
}
LOG("RSSI: %f IDX: %d\n", rssi, result_index);
if (result[result_index] == 0 || result[result_index] > abs_rssi)
{
result[result_index] = abs_rssi;
}
}
return max_signal;
}
#endif

46
lib/scan/scan.h Normal file
View File

@@ -0,0 +1,46 @@
#include <cstdint>
#include <stdlib.h>
#ifndef LORASA_CORE_H
#define LORASA_CORE_H
#ifdef PRINT_DEBUG
#define LOG(args...) Serial.printf(args...)
#define LOG_IF(cond, args...) \
if (cond) \
LOG(args...)
#elif !defined(LOG)
#define LOG(args...)
#define LOG_IF(cond, args...)
#endif
// Output Pixel Formula
// 1 = rssi / 4, 2 = (rssi / 2) - 22 or 20
constexpr int RSSI_OUTPUT_FORMULA = 2;
// based on the formula for RSSI_OUTPUT_FORMULA == 2
// -2 * (22 + RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE) < rssi =< -44
// practice may require a better pair of thresholds
constexpr float HI_RSSI_THRESHOLD = -44.0;
constexpr float LO_RSSI_THRESHOLD = HI_RSSI_THRESHOLD - 66;
// number of samples for RSSI method
#define SAMPLES_RSSI 12 // 21 //
struct Scan
{
Scan(int sz)
: res_size(sz), scale((float)sz / (HI_RSSI_THRESHOLD - LO_RSSI_THRESHOLD + 0.1))
{
}
virtual float getRSSI();
uint16_t rssiMethod(uint16_t *result);
int res_size;
float scale;
};
#endif

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 18 KiB

13
ml_research/datasets.md Normal file
View File

@@ -0,0 +1,13 @@
## Overview of ML Dataets
| dataset name | data content | data format | frequencies / Sampling rate | other infos | source paper/website | source data | open questions |
|----------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------|
| Noisy Drone RF Signal Classification (Glüge et al.) | Drones: DJI, FutabaT14, FutabaT7, Graupner, Taranis, Turnigy | I/Q Data as well as generated Spectrograms available | The device can scan a range of 6Ghz. But the newest plot is very weird. +/- 7 Mhz, can this really be? "non-overlapping signal vectors of length of 1048576 samples, which corresponds to approx. 74.9ms at 14MHz" | mixed with either Labnoise (50%) or Gaussian noise (50%). The noise class was created by mixing Labnoise and Gaussian noise in all possible combinations. Several levels of SNR were used over the entire dataset. | https://www.scitepress.org/Link.aspx?doi=10.5220/0012176800003595 https://github.com/sgluege/Noisy-Drone-RF-Signal-Classification https://github.com/sgluege/Noisy-Drone-RF-Signal-Classification-v2/tree/main | https://www.kaggle.com/datasets/sgluege/noisy-drone-rf-signal-classification-v2/data https://www.kaggle.com/datasets/sgluege/noisy-drone-rf-signal-classification | Not sure about the frequencies. |
| DroneDataset (Swinney and Woods) | Drones: new DJI Mavic 2 Air S, DJI Mavic Pro, DJI Mavic Pro 2, DJI Inspire 2, DJI Mavic Mini, DJI Phantom 4 and the Parrot Disco. | Raw I/Q Data | TODO; Recordings were collected using a Nuand BladeRF SDR and using open source software GNURadio | There are 4 subsets of data included in this dataset, the UAS signals in the presence of Bluetooth interference, in the presence of Wi-Fi signals, in the presence of both and with no interference. 3 flight modes are captured - switched on, hovering and flying. | No paper seen | https://ieee-dataport.org/open-access/dronedetect-dataset-radio-frequency-dataset-unmanned-aerial-system-uas-signals-machine | Sampling rate? |
| DroneRF (Allahham et al.) | Drones: Bepop; AR; Phantom | "the dataset contains only time series data, and not the complex IQ signals" (From Glüge and not from the authors) - but what does this exactly mean? | capture the whole 2.4GHz bandwidth, we have used 2 RF receivers. Each RF receiver has a maximum instantaneous bandwidth of 40 MHz, so both receivers must be operating simultaneously to at least capture a technology spectrum such as WiFi (i.e. 80 MHz). Recorded using universal soft- ware radio peripheral (USRP) software-defined radio (SDR) transceivers. Signals that could be considered noise in the 2.4 GHz band (Bluetooth, Wi-Fi) were not recorded. | modes, including off, on and connected, hovering, flying, and video recording. | https://www.sciencedirect.com/science/article/pii/S2352340919306675?ref=pdf_download&fr=RR-2&rr=8bf5de727fa35d7f | https://data.mendeley.com/datasets/f4c2b4n755/1 | Apparently time versus db? Not very clear what is in the data |
| Radio-Frequency Control and Video Signal Recordings of Drones (Vuorenmaa et al.) | Drones: DJI Inspire 2 (2.44 and 5.8 GHz), DJI Matrice 100 (2.44 GHz), DJI Matrice 210 (2.44 and 5.8 GHz), DJI Mavic Mini (2.44 GHz), DJI Mavic Pro (2.44 GHz), DJI Phantom 4 (2.44 GHz), DJI Phantom 4 Pro Plus (2.44 and 5.8 GHz), Parrot Disco (2.44 GHz), Parrot Mambo (2.44 GHz), Yuneec Typhoon H (2.44 and 5.7 GHz) | I/Q Data (And Video data) | TODO: not clear yet | | https://zenodo.org/records/4264467 | | |
| Spectrogram Dataset (Wicht et al.) | Wi-Fi and Bluetooth signals (NOT DRONES) | Sepctrograms | | | https://www.mdpi.com/2306-5729/7/12/168 | | |
## Current Proposal for ML
![Diagram ML](./Diagram_ML.svg)

View File

@@ -9,6 +9,7 @@
; https://docs.platformio.org/page/projectconf.html
[platformio]
default_envs = heltec_wifi_lora_32_V3
; for env:vision-master-e190
; src_dir = tft_src
; for env:vision-master-e290

View File

@@ -25,7 +25,7 @@
#include <Arduino.h>
// #define OSD_ENABLED true
#define OSD_ENABLED true
// #define WIFI_SCANNING_ENABLED true
// #define BT_SCANNING_ENABLED true
@@ -71,58 +71,6 @@ uint64_t bt_start = 0;
#include "DFRobot_OSD.h"
#define OSD_SIDE_BAR true
static constexpr uint16_t levels[10] = {
0x105, // 0
0x10E, // 1
0x10D, // 2
0x10C, // 3
0x10B, // 4
0x10A, // 5
0x109, // 6
0x108, // 7
0x107, // 8
0x106, // 9
};
static constexpr uint16_t power_level[MAX_POWER_LEVELS + 1] = {
0x10E, // 0
0x10E, // 1
0x10D, // 2
0x10C, // 3
0x10B, // 4
0x10A, // 5
0x109, // 6
0x108, // 7
0x107, // 8
0x106, // 9 not using 106 to accent rise
// new line
0x10E, // 10
0x10D, // 11
0x10C, // 12
0x10B, // 13
0x10A, // 14
0x109, // 15
0x108, // 16
0x107, // 17
0x106, // 18 not using 106
// new line
0x10E, // 19
0x10D, // 20
0x10C, // 21
0x10B, // 22
0x10A, // 23
0x109, // 24
0x108, // 25
0x107, // 26
0x106, // 27
0x105, // 28 ---
0x105, // 29
0x105, // 30
0x105, // 31
0x105, // 32
0x105 // 33
};
// SPI pins
#define OSD_CS 47
#define OSD_MISO 33
@@ -147,11 +95,6 @@ int global_counter = 0;
DFRobot_OSD osd(OSD_CS);
#endif
/*Define Custom characters Example*/
static const int buf0[36] = {0x02, 0x80, 0x02, 0x40, 0x7F, 0xE0, 0x42, 0x00,
0x42, 0x00, 0x7A, 0x40, 0x4A, 0x40, 0x4A, 0x80,
0x49, 0x20, 0x5A, 0xA0, 0x44, 0x60, 0x88, 0x20};
#include "global_config.h"
#include "ui.h"
@@ -212,8 +155,6 @@ constexpr int WINDOW_SIZE = 15;
// Number of samples for each frequency scan. Fewer samples = better temporal resolution.
// if more than 100 it can freeze
#define SAMPLES 35 //(scan time = 1294)
// number of samples for RSSI method
#define SAMPLES_RSSI 12 // 21 //
#define RANGE (int)(FREQ_END - FREQ_BEGIN)
@@ -232,6 +173,7 @@ uint64_t median_frequency = FREQ_BEGIN + FREQ_END - FREQ_BEGIN / 2;
// Array to store the scan results
uint16_t result[RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE];
uint16_t result[RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE];
bool filtered_result[RADIOLIB_SX126X_SPECTRAL_SCAN_RES_SIZE];
@@ -831,6 +773,8 @@ int max_rssi_x = 999;
RadioScan r;
RadioScan r;
void loop(void)
{
UI_displayDecorate(0, 0, false); // some default values
@@ -919,6 +863,7 @@ void loop(void)
// horizontal (x axis) Frequency loop
osd_x = 1, osd_y = 2, col = 0, max_bin = 0;
int radio_error_count = 0;
// x loop
for (x = 0; x < STEPS * SCAN_RBW_FACTOR; x++)
{