Closed augusto3691 closed 3 years ago
To complement to the original post.
I understood that SX1278 can only receive ONE message at a time. So you CAN NOT receive multiple messages from multiple nodes.
When you have 2 nodes, by right, 50% - 50% for each of them.
But when I enableCrc(), it seems that the node with higher RSSI wins all the time.
From the photo, I have 2 nodes (ESP32 + AIThinker SX1278). When node 1 (...AE60) is on, can not receive anything from node 2 (...114C)
By right, it should be 50%-50% chance for two nodes?
So you can check if the one with higher RSSI wins the battle?
I have issues with RSSI too. The further I move away from the gateway, the rssi increase, allowing the other node to send.
i found a solution, it's not a big deal actually, i build a FIFO array in my broker...
like that:
start recieve->recieve for X seconds and store everything recieved in a array->enter in iddle->send everything to the internet and empty the array->start again...
in that way i recieve one at time and leave the connection open to recieve a N more nodes
I'm doing the polling. The master polls the first node then wait a while, then polls the second node.... 99% of the messages can reach the master.
I'm doing the polling. The master polls the first node then wait a while, then polls the second node.... 99% of the messages can reach the master.
This actually is a pretty good solution, are you nodes in sleep mode? And when they're call, they wake and send the data ?
I'm doing the polling. The master polls the first node then wait a while, then polls the second node.... 99% of the messages can reach the master.
This actually is a pretty good solution, are you nodes in sleep mode? And when they're call, they wake and send the data ?
My nodes are always active. For sleep nodes, may be you need to let the nodes awake LONGER than one polling cycle? For example, the master takes 5s to complete polling 5 nodes regardless the nodes are active or not. When a node is active, let it active for at least 5s. Hopefully, the node can get 1 polling request for it. :D
@IoTThinks Can you please share how you implement the "polling" from the master side? I am doing a project with 3 wifi sniffer nodes as 3 slaves. They will always be active, keeping sniffering/listening to the nearby packets data. They send the data to the server only when a specific request has been sent by the master. The workflow will be like: master send requests to slave 1 and wait for answer from slave 1 at 0~1s. When the slave 1 got the request, it will send the data to the server. Same applies to slave 2 and 3 in every second afterwards.
My problem is that not every request sent by master will be answered by the specific slave. I.e., it might request 5 times and only got 1 response, like the picture below. Also, the program became blocked forever when around 32 packets have been set to the master (Not sure if it's relevant to LoRa.endPacket())
The (part of) master code is:
loop()
{
if (millis() - lastRequestSentTime > 500)
{
if (turn == 1)
{
SendRequest("1#"); // Send request to Client 1
receiveFromSlaveDevice("1#"); // This is data from Client 1
lastRequestSentTime = millis();
// trun = 2;
// contintues to turn 2 and 3
}
}
vTaskDelay( 100 / portTICK_PERIOD_MS );
}
void SendRequest( String request )
{
LoRa.beginPacket(); // start packet
LoRa.print(request); // send request
LoRa.endPacket(); // finish packet and send it
} // SendRequest
void receiveFromSlaveDevice( String nodeID )
{
int packetSize = LoRa.parsePacket();
if (packetSize)
{
Serial.println( "Received packet from: " + nodeID );
String incomingMessage = ""; // payload of incoming packet
while ( LoRa.available() )
{
String incomingMessage = LoRa.readString();
// incomingMessage (WiFi device data) format: Timestamp \t MAC Address \t RSSI \n
int pos1 = incomingMessage.indexOf('\t');
int pos2 = incomingMessage.indexOf('\t', pos1 + 1);
int pos3 = incomingMessage.indexOf('\n', pos2 + 1);
std::vector<String> wifiDevicePayload(3);
wifiDevicePayload[0] = incomingMessage.substring(0, pos1); // Timestamp
wifiDevicePayload[1] = incomingMessage.substring(pos1 + 1, pos2); // MAC Address
wifiDevicePayload[2] = incomingMessage.substring(pos2 + 1, pos3); // RSSI
Serial.println("Index 1: " + wifiDevicePayload[0]);
printWiFiDeviceData( wifiDevicePayload );
xQueueSend( g_queueBetweenReceiveAndWebServer, &wifiDevicePayload, portMAX_DELAY );
}
}
}
The (part of) slave code is:
int packetSize = LoRa.parsePacket();
if (packetSize)
{
while ( LoRa.available() )
{
String request = LoRa.readString();
if ( request == "1#" )
{
Serial.println( "Client 1 got request, answering Server..." );
sendToMasterDevice( WiFiDeviceData );
}
else
{
Serial.println( "ERROR - No requests from Server." );
}
}
}
It seems there is some transition time needed for the LoRa chip to switch from sending mode to receiving mode. But there is not a function can be used to wait until a message is received... (Like RF95.waitAvailableTimeout()
in RadioHead Library, http://www.airspayce.com/mikem/arduino/RadioHead/classRHGenericDriver.html#a8ed545cecc22196a325333dc9637e4cf).
Any suggestions or ideas will be of highly appreciated!
I use callback to listen for LoRa packet.
For gateway, I use esp32 with 2 cores. Core 1 to listen for packet and spin off a vTask to process at core 0.
In your code, I see you process a lot of things after receiving a packet. That may make your node miss incoming packets.
I have a system that have multiples nodes and one broker, when i have 1 broker and 1 node everything is fine but wen i put one more, the broker recieve data just from the last one...
here is my code:
Node:
include
include
include
include "SSD1306.h"
include <TinyGPS++.h>
include
define OLED_SDA 21
define OLED_SLA 22
define LORA_SCK 5
define LORA_MISO 19
define LORA_MOSI 27
define LORA_SS 18
define LORA_RST 14
define LORA_DI0 26
define LORA_BAND 915E6
define NODE_ID "gco89770" // Aqui vai o ID unico desse device, deve seguir o modelo aaa99999 (3 letras, 5 numeros)
define REBOOT_EEPROM_ADDRESS 0
SSD1306 display(0x3c, OLED_SDA, OLED_SLA); TinyGPSPlus gps;
void setup() { Serial.begin(115200); display.init(); display.flipScreenVertically();
Serial1.begin(9600, SERIAL_8N1, 12, 15); //12-15 para placa ESP32-LORA, para o ESP32 Stand-alone use 16-17
SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_SS); LoRa.setPins(LORA_SS, LORA_RST, LORA_DI0); if (!LoRa.begin(LORA_BAND)) { display.clear(); display.drawString(0, 0, "LoRa falhou ao iniciar"); display.display(); return; } if (!EEPROM.begin(64)) { display.clear(); display.drawString(0, 0, "Flash Memory falhou"); display.drawString(0, 15, "Reiniciando..."); display.display(); delay(1000); ESP.restart(); }
int reboots = EEPROM.read(REBOOT_EEPROM_ADDRESS); int nextReboot = reboots + 1; if ( reboots < 0) { EEPROM.write(REBOOT_EEPROM_ADDRESS, 0); EEPROM.commit(); } else { EEPROM.write(REBOOT_EEPROM_ADDRESS, nextReboot); EEPROM.commit(); }
delay(1500);
}
void loop() { char v_millis_b[10]; int v_reboot = EEPROM.read(REBOOT_EEPROM_ADDRESS); String v_separator = "/"; int v_millis = millis(); sprintf(v_millis_b,"%08d", v_millis); String Version = v_reboot + v_separator + v_millis_b;
if (v_millis >= 86400000) { ESP.restart(); }
display.clear(); display.setTextAlignment(TEXT_ALIGN_LEFT); display.setFont(ArialMT_Plain_10); display.drawString(0, 0, "Enviando pacote..."); display.drawString(0, 15, "Versão:"); display.drawString(40, 15, Version); display.display();
Serial.print("lat: "); Serial.println(gps.location.lat(), 5); Serial.print("lng: "); Serial.println(gps.location.lng(), 5); Serial.print("sat: "); Serial.println(gps.satellites.value()); Serial.print("Versão: "); Serial.println(Version);
//Send packet LoRa.beginPacket(); LoRa.print(NODE_ID); LoRa.print(","); LoRa.print(gps.location.lat(), 5); LoRa.print(","); LoRa.print(gps.location.lng(), 5); LoRa.print(","); LoRa.print(Version); LoRa.endPacket();
smartDelay(1000); }
//delay mais preciso static void smartDelay(unsigned long ms) { unsigned long start = millis(); do { while (Serial1.available()) gps.encode(Serial1.read()); } while (millis() - start < ms); }
Broker:
include
include
include "SSD1306.h"
include
include
include
include
include
include
SSD1306 display(0x3c, 21, 22); HTTPClient http;
define SS 18
define RST 14
define DI0 26
define BAND 915E6
define PACK_SIZE_FROM_NODE 40
define PACK_SIZE_FROM_COLECTOR 49
define BROKER_ID "5c8c3229" // Aqui vai o ID unico desse device, deve seguir o modelo aaa99999 (3 letras, 5 numeros)
define WIFI_NAME "Klabin Broker"
define API "http://us-central1-klabin-waze-florestal.cloudfunctions.net/pois"
void setup() { Serial.begin(115200);
display.init(); display.flipScreenVertically(); display.setFont(ArialMT_Plain_10); display.setTextAlignment(TEXT_ALIGN_LEFT);
WiFiManager wifiManager; wifiManager.setAPCallback(configModeCallback); wifiManager.setSaveConfigCallback(saveConfigCallback); wifiManager.autoConnect(WIFI_NAME);
delay(1000); Serial.println("LoRa Receiver"); display.drawString(5, 5, "LoRa Receiver"); display.display(); SPI.begin(5, 19, 27, 18); LoRa.setPins(SS, RST, DI0);
if (!LoRa.begin(BAND)) { display.drawString(5, 25, "Starting LoRa failed!"); while (1); } Serial.println("LoRa Initial OK!"); display.drawString(5, 25, "LoRa Initializing OK!"); display.display(); }
void sendData(String nodeId, String colectorId, String lat, String lng,String v) { StaticJsonBuffer<400> JSONbuffer; JsonObject& JSONencoder = JSONbuffer.createObject();
JSONencoder["brokerId"] = BROKER_ID; JSONencoder["colectorId"] = colectorId; JSONencoder["nodeId"] = nodeId; JSONencoder["lat"] = lat; JSONencoder["lng"] = lng; JSONencoder["version"] = v; char JSONBuffer[300]; JSONencoder.prettyPrintTo(JSONBuffer, sizeof(JSONBuffer)); Serial.println(JSONBuffer); http.begin(API); http.addHeader("Content-Type", "application/json"); int httpResponseCode = http.POST(JSONBuffer); if (httpResponseCode > 0) { String response = http.getString(); Serial.println(httpResponseCode); Serial.println(response); } else { Serial.print("Error on sending POST: "); Serial.println(httpResponseCode); } http.end(); //Free resources }
void loop() { int packetSize = LoRa.parsePacket(); if (WiFi.status() == WL_CONNECTED) { if (packetSize == PACK_SIZE_FROM_NODE || packetSize == PACK_SIZE_FROM_COLECTOR) { // received a packets display.clear(); display.drawString(0, 0, "Pacote recebido "); // read packet while (LoRa.available()) { String data = LoRa.readString(); display.drawString(0, 15, getValueInString(data, ',', 0)); display.drawString(0, 30, "Sinal:"); display.drawString(30, 30, (String)LoRa.packetRssi()); display.display(); if (packetSize == PACK_SIZE_FROM_COLECTOR) { sendData(getValueInString(data, ',', 0), getValueInString(data, ',', 4), getValueInString(data, ',', 1), getValueInString(data, ',', 2),getValueInString(data, ',', 3)); } else { sendData(getValueInString(data, ',', 0), "0", getValueInString(data, ',', 1), getValueInString(data, ',', 2),getValueInString(data, ',', 3)); } delay(3000); } } else { display.clear(); display.drawString(0, 0, "Procurando POIs..."); display.display();; } } else { display.clear(); display.drawString(0, 0, "Aguardando config. WiFi..."); display.display();; } }
String getValueInString(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]) : ""; }
//callback que indica que o ESP entrou no modo AP void configModeCallback(WiFiManager *myWiFiManager){ display.drawString(0, 0, "Modo de configuração"); display.drawString(0, 15, myWiFiManager->getConfigPortalSSID()); display.display(); }
//callback que indica que salvamos uma nova rede para se conectar (modo estação) void saveConfigCallback(){ display.drawString(0, 0, "Configuração salva!"); display.display(); delay(2000); }