├── .gitattributes ├── AntennaTesterReceiverWEMOS └── AntennaTesterReceiverWEMOS.ino ├── AntennaTesterSenderV1 └── AntennaTesterSenderV1.ino └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /AntennaTesterReceiverWEMOS/AntennaTesterReceiverWEMOS.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static const uint32_t GPSBaud = 9600; 6 | 7 | /*WeMos D1 RFM9x Module 8 | GPIO12 (D6) <----> MISO 9 | GPIO13 (D7) <----> MOSI 10 | GPIO14 (D5) <----> CLK 11 | GPIO15 (D8) <----> DIO0/D2 OR DIO1/D3 OR DIO2/D4 12 | GPIO16 (D0) <----> SEL Chip Select (depending on bottom solder PAD position) 13 | 14 | WeMos D1 Shield Feature 15 | GPIO5 (D1) <----> I2C SCL 16 | GPIO4 (D2) <----> I2C SDA 17 | GPIO0 (D3) <----> WS2812 LEDS 18 | GPIO2 (D4) <----> Push Button 19 | GPIO16 (D0) <----> RESET (depending on bottom solder PAD position) 20 | 21 | */ 22 | 23 | #define SS D0 24 | #define RST D0 25 | #define DI0 D8 26 | 27 | 28 | #define spreadingFactor 9 29 | #define SignalBandwidth 125E3 30 | #define preambleLength 8 31 | #define codingRateDenominator 8 32 | 33 | // The TinyGPS++ object 34 | TinyGPSPlus gps; 35 | 36 | // The serial connection to the GPS device 37 | HardwareSerial receiverSerial(1); 38 | HardwareSerial GPSserial(2); 39 | 40 | #define FREQUENCY 868.9E6 41 | 42 | #define LEDPIN 5 43 | 44 | 45 | double retFrequency; 46 | int retSF; 47 | 48 | struct locStruct 49 | { 50 | bool isValid; 51 | bool isUpdated; 52 | uint32_t age; 53 | double lat; 54 | double lng; 55 | double altitude; 56 | double hdop; 57 | int power; 58 | int rssi; 59 | } sendLoc, recLoc; 60 | 61 | struct GPStimeStruct 62 | { 63 | bool isValid; 64 | bool isUpdated; 65 | uint32_t age; 66 | uint32_t value; 67 | uint16_t year; 68 | uint8_t month; 69 | uint8_t day; 70 | uint8_t hour; 71 | uint8_t minute; 72 | uint8_t second; 73 | uint8_t centisecond; 74 | } GPStime; 75 | 76 | 77 | void displayVersion() { 78 | Serial.println(F("DeviceExample.ino")); 79 | Serial.println(F("A simple demonstration of TinyGPS++ with an attached GPS module")); 80 | Serial.print(F("Testing TinyGPS++ library v. ")); 81 | Serial.println(TinyGPSPlus::libraryVersion()); 82 | Serial.println(F("by Mikal Hart")); 83 | Serial.println(); 84 | } 85 | 86 | void getPosition() { 87 | unsigned long GPSentry = millis(); 88 | while (GPSserial.available() > 0) 89 | if (gps.encode(GPSserial.read())) 90 | if (millis() > GPSentry + 5000 && gps.charsProcessed() < 10) 91 | { 92 | Serial.println(F("No GPS detected: check wiring.")); 93 | while (true); 94 | } 95 | if (gps.location.isValid()) 96 | { 97 | if (gps.location.isValid()) { 98 | sendLoc.isUpdated = (gps.location.isUpdated()); 99 | sendLoc.lat = gps.location.lat(); 100 | sendLoc.lng = gps.location.lng(); 101 | sendLoc.altitude = gps.altitude.meters(); 102 | sendLoc.hdop = gps.hdop.value(); 103 | } 104 | if (gps.time.isValid()) { 105 | GPStime.year = gps.date.year(); 106 | GPStime.month = gps.date.month(); 107 | GPStime.day = gps.date.day(); 108 | GPStime.hour = gps.time.hour(); 109 | GPStime.minute = gps.time.minute(); 110 | GPStime.second = gps.time.second(); 111 | GPStime.centisecond = gps.time.centisecond(); 112 | } 113 | } 114 | } 115 | 116 | void receivingMessage () { 117 | unsigned long eentry = millis(); 118 | StaticJsonBuffer<500> jsonBuffer; 119 | char json[500]; 120 | Serial.println("HIGH"); 121 | digitalWrite(LEDPIN, LOW); 122 | 123 | // Receive Message 124 | 125 | // Serial.print("Start receiving "); 126 | // Serial.println(millis()); 127 | while (LoRa.parsePacket() == 0) yield(); 128 | // received a packet 129 | // Serial.println("Received packet"); 130 | 131 | // read packet 132 | json[0] = '\0'; 133 | while (LoRa.available()) { 134 | byte hi = strlen(json); 135 | json[hi] = (char)LoRa.read(); 136 | json[hi + 1] = '\0'; 137 | } 138 | // Serial.println(json); 139 | JsonObject& recMessage = jsonBuffer.parse(json); 140 | 141 | if (recMessage.success()) { 142 | 143 | recMessage["RSSI"] = LoRa.packetRssi(); 144 | 145 | recMessage["rLat"] = sendLoc.lat; 146 | recMessage["rLng"] = sendLoc.lng; 147 | recMessage["rAlt"] = sendLoc.altitude; 148 | recMessage["rHdop"] = sendLoc.hdop; 149 | 150 | // Serial.println("-------"); 151 | // Serial.print("Received Data / Start sending "); 152 | // Serial.println(millis()); 153 | recMessage.printTo(Serial); 154 | // Serial.println(); 155 | Serial.println("LOW"); 156 | digitalWrite(LEDPIN, HIGH); 157 | delay(200); 158 | 159 | // Send packet back 160 | String sendMessage; 161 | recMessage.printTo(sendMessage); 162 | LoRa.setTxPower(17); 163 | LoRa.beginPacket(); 164 | LoRa.print(sendMessage); 165 | LoRa.endPacket(); 166 | Serial.println("Package sent"); 167 | } else Serial.println("parseObject() failed"); 168 | Serial.println(millis() - eentry); 169 | } 170 | 171 | void initLoRa() { 172 | SPI.begin(); 173 | LoRa.setPins(D0, D0, D8); 174 | if (!LoRa.begin(FREQUENCY)) { 175 | Serial.println("Starting LoRa failed!"); 176 | while (1) { 177 | digitalWrite(LEDPIN, 1); 178 | delay(200); 179 | digitalWrite(LEDPIN, 0); 180 | delay(200); 181 | } 182 | } 183 | Serial.print("FREQUENCY "); 184 | Serial.println(FREQUENCY); 185 | LoRa.setTxPower(1); 186 | Serial.print("LoRa Spreading Factor: "); 187 | Serial.println(spreadingFactor); 188 | LoRa.setSpreadingFactor(spreadingFactor); 189 | Serial.print("LoRa Signal Bandwidth: "); 190 | Serial.println(SignalBandwidth); 191 | LoRa.setSignalBandwidth(SignalBandwidth); 192 | Serial.println("LoRa Initial OK!"); 193 | } 194 | 195 | void setup() { 196 | Serial.begin(115200); 197 | pinMode(LEDPIN, OUTPUT); 198 | digitalWrite(LEDPIN, 1); 199 | delay(1000); 200 | digitalWrite(LEDPIN, 0); 201 | GPSserial.begin(GPSBaud); 202 | initLoRa(); 203 | } 204 | 205 | void loop() { 206 | getPosition(); 207 | receivingMessage(); 208 | yield(); 209 | } 210 | -------------------------------------------------------------------------------- /AntennaTesterSenderV1/AntennaTesterSenderV1.ino: -------------------------------------------------------------------------------- 1 | #include "SSD1306.h" // alias for `#include "SSD1306Wire.h"' 2 | #include 3 | #include 4 | #include 5 | 6 | static const uint32_t GPSBaud = 9600; 7 | 8 | // WIFI_LoRa_32 ports 9 | // GPIO5 -- SX1278's SCK 10 | // GPIO19 -- SX1278's MISO 11 | // GPIO27 -- SX1278's MOSI 12 | // GPIO18 -- SX1278's CS 13 | // GPIO14 -- SX1278's RESET 14 | // GPIO26 -- SX1278's IRQ(Interrupt Request) 15 | 16 | //GPIO16 OLED RESET 17 | 18 | 19 | #define SS 18 20 | #define RST 14 21 | #define DI0 26 22 | 23 | #define STARTPIN 25 24 | #define BUZZERPIN 13 25 | #define ZEROPIN 2 26 | 27 | 28 | #define spreadingFactor 9 29 | #define SignalBandwidth 125E3 30 | #define preambleLength 8 31 | #define codingRateDenominator 8 32 | 33 | #define FREQUENCY 868.9E6 34 | 35 | #define TIMEOUT 2000 36 | #define DELAY_MS 400 37 | 38 | // The TinyGPS++ object 39 | TinyGPSPlus gps; 40 | int rssi; 41 | int performance; 42 | int power = 7; 43 | float average; 44 | float zero = 0; 45 | 46 | // SSD1306 display(0x3c, 21, 22); // TTGOV2 47 | SSD1306 display(0x3c, 4, 15); // TTGo V1 48 | 49 | // The serial connection to the GPS device 50 | HardwareSerial GPSserial(1); 51 | 52 | struct locStruct 53 | { 54 | bool isValid; 55 | bool isUpdated; 56 | uint32_t age; 57 | double lat; 58 | double lng; 59 | double altitude; 60 | double hdop; 61 | int power; 62 | int rssi; 63 | } sendLoc, recLoc; 64 | 65 | struct GPStimeStruct 66 | { 67 | bool isValid; 68 | bool isUpdated; 69 | uint32_t age; 70 | uint32_t value; 71 | uint16_t year; 72 | uint8_t month; 73 | uint8_t day; 74 | uint8_t hour; 75 | uint8_t minute; 76 | uint8_t second; 77 | uint8_t centisecond; 78 | } GPStime; 79 | 80 | 81 | void initDisplay() { 82 | display.init(); 83 | display.flipScreenVertically(); 84 | display.setFont(ArialMT_Plain_24); 85 | display.setColor(WHITE); 86 | } 87 | 88 | void getPosition() { 89 | 90 | unsigned long GPSentry = millis(); 91 | while (GPSserial.available() > 0) 92 | if (gps.encode(GPSserial.read())) 93 | if (millis() > GPSentry + 5000 && gps.charsProcessed() < 10) 94 | { 95 | Serial.println(F("No GPS detected: check wiring.")); 96 | } 97 | if (gps.location.isValid()) 98 | { 99 | if (gps.location.isValid()) { 100 | sendLoc.isUpdated = (gps.location.isUpdated()); 101 | sendLoc.lat = gps.location.lat(); 102 | sendLoc.lng = gps.location.lng(); 103 | sendLoc.altitude = gps.altitude.meters(); 104 | sendLoc.hdop = gps.hdop.value(); 105 | } 106 | if (gps.time.isValid()) { 107 | GPStime.year = gps.date.year(); 108 | GPStime.month = gps.date.month(); 109 | GPStime.day = gps.date.day(); 110 | GPStime.hour = gps.time.hour(); 111 | GPStime.minute = gps.time.minute(); 112 | GPStime.second = gps.time.second(); 113 | GPStime.centisecond = gps.time.centisecond(); 114 | } 115 | } 116 | } 117 | 118 | 119 | bool sendMessage() { 120 | bool success = false; 121 | char json[500]; 122 | StaticJsonBuffer<500> jsonBuffer; 123 | JsonObject& sendMessage = jsonBuffer.createObject(); 124 | sendMessage["freq"] = FREQUENCY; 125 | sendMessage["sf"] = spreadingFactor; 126 | sendMessage["power"] = power; 127 | sendMessage["rLat"] = ""; 128 | sendMessage["rLng"] = ""; 129 | sendMessage["rAlt"] = ""; 130 | sendMessage["rHdop"] = ""; 131 | sendMessage["RSSI"] = ""; 132 | 133 | // Send Packet 134 | String sMessage; 135 | Serial.println("Send"); 136 | sendMessage.printTo(sMessage); 137 | LoRa.setTxPower(power); 138 | LoRa.beginPacket(); 139 | LoRa.print(sMessage); 140 | LoRa.endPacket(); 141 | 142 | // Receive Message 143 | unsigned long entry = millis(); 144 | Serial.println("wait for receive"); 145 | while (LoRa.parsePacket() == 0 && (millis() < entry + TIMEOUT)); 146 | Serial.println("receive"); 147 | if (millis() < entry + TIMEOUT - 1) { 148 | // received a packet 149 | json[0] = '\0'; 150 | while (LoRa.available()) { 151 | byte hi = strlen(json); 152 | json[hi] = (char)LoRa.read(); 153 | json[hi + 1] = '\0'; 154 | } 155 | JsonObject& recMessage = jsonBuffer.parse(json); 156 | if (recMessage.success()) { 157 | recLoc.lat = recMessage["rLat"]; 158 | recLoc.lng = recMessage["rLng"]; 159 | recLoc.altitude = recMessage["rAlt"]; 160 | recLoc.hdop = recMessage["rHdop"]; 161 | power = recMessage["power"]; 162 | rssi = recMessage["RSSI"]; 163 | Serial.print("Power: "); 164 | Serial.print(power); 165 | Serial.print(" RSSI: "); 166 | Serial.print(rssi); 167 | Serial.print(" Performance: "); 168 | performance = (rssi - power); 169 | Serial.println(performance); 170 | Serial.print(" Relative Performance: "); 171 | Serial.println(performance - zero); 172 | 173 | success = true; 174 | } else Serial.println("parseObject() failed"); 175 | } else Serial.println("Timeout"); 176 | return success; 177 | } 178 | 179 | double calculateDistance(double senderLat, double senderLng, double receiverLat, double receiverLng) { 180 | double distanceKm = 181 | gps.distanceBetween( 182 | receiverLat, 183 | receiverLng, 184 | senderLat, 185 | senderLng); 186 | /* 187 | Serial.println("Coordinates"); 188 | Serial.println(receiverLat); 189 | Serial.println(receiverLng); 190 | Serial.println(senderLat); 191 | Serial.println(senderLng); 192 | Serial.println(); 193 | */ 194 | return distanceKm; 195 | } 196 | 197 | double calculateCourse(double senderLat, double senderLng, double receiverLat, double receiverLng) { 198 | double courseTo = 199 | gps.courseTo( 200 | receiverLat, 201 | receiverLng, 202 | senderLat, 203 | senderLng); 204 | return courseTo; 205 | } 206 | void initLoRa() { 207 | 208 | SPI.begin(5, 19, 27, 18); 209 | LoRa.setPins(SS, RST, DI0); 210 | if (!LoRa.begin(FREQUENCY)) { 211 | Serial.println("Starting LoRa failed!"); 212 | while (1); 213 | } 214 | Serial.print("FREQUENCY "); 215 | Serial.println(FREQUENCY); 216 | LoRa.setTxPower(1); 217 | Serial.print("LoRa Spreading Factor: "); 218 | Serial.println(spreadingFactor); 219 | LoRa.setSpreadingFactor(spreadingFactor); 220 | Serial.print("LoRa Signal Bandwidth: "); 221 | Serial.println(SignalBandwidth); 222 | LoRa.setSignalBandwidth(SignalBandwidth); 223 | Serial.println("LoRa Initial OK!"); 224 | } 225 | 226 | void buzz(int duration, int number) { 227 | for (int i = 0; i < number; i++) { 228 | digitalWrite(BUZZERPIN, 1); 229 | delay(duration); 230 | digitalWrite(BUZZERPIN, 0); 231 | } 232 | } 233 | 234 | void setup() 235 | { 236 | Serial.begin(115200); 237 | GPSserial.begin(GPSBaud); 238 | pinMode(16, OUTPUT); 239 | digitalWrite(16, HIGH); 240 | initDisplay(); 241 | pinMode(STARTPIN, INPUT_PULLUP); 242 | pinMode(ZEROPIN, INPUT_PULLUP); 243 | pinMode(BUZZERPIN, OUTPUT); 244 | digitalWrite(BUZZERPIN, 0); 245 | getPosition(); 246 | initLoRa(); 247 | display.clear(); 248 | display.setTextAlignment(TEXT_ALIGN_CENTER); 249 | display.setFont(ArialMT_Plain_24); 250 | display.drawString(64, 0, "Press"); 251 | display.drawString(64, 35, "Button"); 252 | display.display(); 253 | } 254 | 255 | void loop() 256 | { 257 | Serial.println("Press button"); 258 | while (digitalRead(STARTPIN) > 0) { // Wait for start 259 | } 260 | Serial.println("waiting"); 261 | display.clear(); 262 | display.setColor(WHITE); 263 | display.setTextAlignment(TEXT_ALIGN_CENTER); 264 | display.setFont(ArialMT_Plain_24); 265 | display.drawString(64, 15, "Waiting"); 266 | display.display(); 267 | delay(4000); 268 | buzz(100, 1); 269 | Serial.println("Start "); 270 | float sum = 0; 271 | for (int i = 0; i < 5; i++) { 272 | while (!sendMessage()) { 273 | Serial.println("Failure"); 274 | delay(DELAY_MS); 275 | // buzz(500, 1); 276 | } 277 | sum = sum + performance; 278 | display.clear(); 279 | display.setColor(WHITE); 280 | display.setTextAlignment(TEXT_ALIGN_LEFT); 281 | display.setFont(ArialMT_Plain_24); 282 | display.drawString(0, 0, "RSSI: " + String(rssi)); 283 | display.drawString(0, 35, "IND: " + String(performance - zero)); 284 | display.display(); 285 | delay(DELAY_MS); 286 | } 287 | buzz(100, 3); 288 | average = (sum / 5.0); 289 | Serial.print("Average RSSI "); 290 | Serial.println(average); 291 | double distance = calculateDistance(sendLoc.lat, sendLoc.lng, recLoc.lat, recLoc.lng); 292 | // Serial.print("Distance "); 293 | // Serial.println(distance); 294 | double direction = calculateCourse(sendLoc.lat, sendLoc.lng, recLoc.lat, recLoc.lng); 295 | // Serial.print("Direction "); 296 | // Serial.println(direction); 297 | 298 | // dtostrf(distance, 7, 2, line1); 299 | // dtostrf(direction, 7, 0, line2); 300 | 301 | char line3[15]; 302 | dtostrf(average-zero, 7, 1, line3); 303 | display.clear(); 304 | display.setTextAlignment(TEXT_ALIGN_LEFT); 305 | display.setFont(ArialMT_Plain_24); 306 | display.drawString(0, 0, "AVG:" ); 307 | display.drawString(50, 0, line3); 308 | display.setTextAlignment(TEXT_ALIGN_CENTER); 309 | display.drawString(64, 35, "Button"); 310 | display.display(); 311 | 312 | while ((digitalRead(STARTPIN) == 1) && (digitalRead(ZEROPIN) == 1)) { 313 | // Serial.print(digitalRead(ZEROPIN)); 314 | delay(50); 315 | if (digitalRead(ZEROPIN) == 0) { 316 | zero = average; 317 | Serial.print("Zero "); 318 | Serial.println(zero); 319 | display.clear(); 320 | display.setTextAlignment(TEXT_ALIGN_CENTER); 321 | display.setFont(ArialMT_Plain_24); 322 | display.drawString(64, 0, "Zero"); 323 | display.drawString(64, 35, "Button"); 324 | display.display(); 325 | if (digitalRead(ZEROPIN) == 0); 326 | } 327 | } 328 | } 329 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Antenna-Tester 2 | LoRa Antenna Tester 3 | 4 | Code for YouTube video: https://youtu.be/J3PBL9oLPX8 5 | 6 | Sender sketch is made for a TTGO V1 ESP32 board with a Oled and a LoRa chip. You have to change the pins if you want to use it on another platform 7 | Receiver sketch is made for a Wemos D1 mini ESP8266 board connected to a shield with a RFM95 module.( https://github.com/hallard/WeMos-Lora ) 8 | --------------------------------------------------------------------------------