Painless Mesh going into a unfound loop

42 views
Skip to first unread message

niel joubert

unread,
Jul 3, 2024, 6:03:31 AM7/3/24
to painlessmesh-user
Good day, I am experiencing some odd behaviour and are hoping you guys can help me debug and fix this problem.

Problem statement: So I have a mesh network with 5 nodes acting as dynamic nodes between 2 static nodes. I am trying to measure the time it takes to move from one static node to the other and visa versa. My dynamic nodes successfully records the time and display it via LED's  but   my dynamic node takes a while to find the static nodes on the second time it gets nearby the nodes. So when my dynamic node connects for the first time to static node 1 it happens almost instantly and then it travels to the second static node 2 and connects almost instantly, but returning and having this in a loop it starts not to want to connect to node 1 again but the moment you are nearby node 2 it instantly connects again. I don't know if there is a fix. But any help will be appreciated 

CODE: 

//

#include "painlessMesh.h"
#include "Timer.h"
#include <SoftwareSerial.h>
#include <TinyGPSPlus.h>
#include <SPI.h>
#include <EEPROM.h>


#define MESH_PREFIX "whateverYouLike"
#define MESH_PASSWORD "somethingSneaky"
#define MESH_PORT 5555

#define LEDGreen 27
#define LEDRed 12
#define LEDYellow 32
//#define LEDBlue 2

#define EEPROM_SIZE 250

Scheduler userScheduler; // to control your personal task
painlessMesh mesh;
Timer timer1;
Timer timer2;
//Timer timer3;

int Timer1Mem;
int Timer2Mem;

int setTimer1;
int setTimer2;

// Define variables to store start time of timer

int connectedToBaseStation;
int connectedToEXStation;

int load = 0;
float Total = 0;

int rxPin = 4;
int txPin = 0;


int counter = 0;
const int MAX_SAMPLES = 30; // Store up to 30 samples
float latitudes[MAX_SAMPLES];
float longitudes[MAX_SAMPLES];
unsigned long previousMillis = 0; // Stores last time coordinates were recorded
const unsigned long interval = 60000; // Interval to take readings (1 minute)
int sampleIndex = 0; // Index to store data

SoftwareSerial gpsSerial(rxPin, txPin);

HardwareSerial neogps(1);

TinyGPSPlus gps;

void sendMessage();

//IPAddress myIP(0, 0, 0, 0);

Task taskSendMessage(TASK_SECOND * 5, TASK_FOREVER, &sendMessage);

void sendMessage() {

// Check if connected to the base station and timer has started
if (connectedToBaseStation == 1 && timer1.state() == PAUSED) {
String msg = "Time to EX:" + String(timer1.read() / 1000) + " seconds";
mesh.sendBroadcast(msg);
TotalTime();
timer1.stop();
timer1.start();
timer2.pause();



connectedToBaseStation = 0;
}
if (connectedToEXStation == 1 && timer2.state() == PAUSED) {
String msg = "Time From EX:" + String(timer2.read() / 1000) + " seconds";
mesh.sendBroadcast(msg);
timer2.stop();

loads();
delay(100);
GPS_sent();

connectedToEXStation = 0;

}


}


void GPS_sent() {
String msg = "GPS Coordinates:";
for (int i = 0; i < MAX_SAMPLES; i++) {
if (i < sampleIndex) {
msg += String(latitudes[i], 6) + "," + String(longitudes[i], 6) + "; ";
} else {
// Once you reach the last valid sample, break out of the loop
break;
}
}
mesh.sendBroadcast(msg);
}

void loads() {
load++;
Serial.print(load);
String msg = "Number of Loads:" + String(load) + " N";
mesh.sendBroadcast(msg);
}

void TotalTime() {
Total = (timer1.read() + timer2.read()) / 1000;
String msg = "Total Cycle Time:" + String(Total) + " Seconds";
mesh.sendBroadcast(msg);
}

void nodeTimeAdjustedCallback(int32_t offset) {
Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(), offset);
}

void newConnectionCallback(uint32_t nodeId) {
Serial.printf("--> startHere: New Connection, nodeId = %u\n", nodeId);
// Check if connected node is the base station (Dumping)
if (nodeId == 3087806869) {
connectedToBaseStation = 1;
// timer2.pause();
}
// Check if connected node is the EX station (Excavator)
if (nodeId == 3087820581) {
connectedToEXStation = 1;
timer1.pause();
timer2.start();
}
}

void changedConnectionCallback() {
Serial.printf("Changed connections\n");
// Check if the connection to the base station is lost
if (!mesh.isConnected(3087806869)) {
connectedToBaseStation = 0;
}
}

void Time1(const String &msg) {
// Extract the number from the received message
int index = msg.indexOf(':') + 1; // Find the index of ':' character
String numberString = msg.substring(index); // Extract the substring after ':'
int number = numberString.toInt(); // Convert the substring to an integer
Serial.println(number);
if (number != 0) {
Timer1Mem = number;
EEPROM.write(0, Timer1Mem);
EEPROM.commit();
setTimer1 = Timer1Mem * 60000; // Update setTimer1
Serial.println(setTimer1);
}
}

void Time2(const String &msg) {
// Extract the number from the received message
int index = msg.indexOf(':') + 1; // Find the index of ':' character
String numberString = msg.substring(index); // Extract the substring after ':'
int number = numberString.toInt(); // Convert the substring to an integer
Serial.println(number);
if (number != 0) {
Timer2Mem = number;
EEPROM.write(1, Timer2Mem);
EEPROM.commit();
setTimer2 = Timer2Mem * 60000; // Update setTimer2
Serial.println(setTimer2);
}
}

void receivedCallback(const uint32_t &from, const String &msg) {
if (msg.indexOf("Time1:") == 0) {
Time1(msg); // Call Time1 function
Serial.println(msg);
} else if (msg.indexOf("Time2:") == 0) {
Time2(msg); // Call Time2 function
Serial.println(msg);
}
}

void setup() {
Serial.begin(115200);


EEPROM.begin(EEPROM_SIZE);

Timer1Mem = EEPROM.read(0);
Timer2Mem = EEPROM.read(1);

setTimer1 = Timer1Mem * 60000; // Initialize setTimer1
setTimer2 = Timer2Mem * 60000; // Initialize setTimer2

pinMode(LEDGreen, OUTPUT);
pinMode(LEDRed, OUTPUT);
pinMode(LEDYellow, OUTPUT);

neogps.begin(9600, SERIAL_8N1, rxPin, txPin);

timer1.start();
//timer3.start();

mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);

mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT, WIFI_AP_STA);
mesh.onReceive(&receivedCallback);
mesh.onNewConnection(&newConnectionCallback);
mesh.onChangedConnections(&changedConnectionCallback);
mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);

userScheduler.addTask(taskSendMessage);
taskSendMessage.enable();
}



void loop() {
mesh.update();
print1();
timersproccess();
// printGPS();

}

void print1() {
Serial.print("Time to EX(s): ");
Serial.println(timer1.read() / 1000);
Serial.println();
Serial.print("Time from EX(s): ");
Serial.println(timer2.read() / 1000);
delay(1000);
}

void printGPS() {
boolean newData = false;
for (unsigned long start = millis(); millis() - start < 1000;) {
while (neogps.available()) {
if (gps.encode(neogps.read())) {
newData = true;
}
}
}

if (newData) {
newData = false;
if (millis() - previousMillis >= interval) {
previousMillis = millis();
if (gps.location.isValid()) {
if (sampleIndex < MAX_SAMPLES) {
latitudes[sampleIndex] = gps.location.lat();
longitudes[sampleIndex] = gps.location.lng();
Serial.print("Stored Lat: ");
Serial.print(latitudes[sampleIndex], 6);
Serial.print(", Lng: ");
Serial.println(longitudes[sampleIndex], 6);
sampleIndex++;
} else {
Serial.println("Sample storage is full.");
}
} else {
Serial.println("Invalid GPS data.");
}
}
}
}

void timersproccess() {
if (timer1.read() <= setTimer1 && timer1.state() == RUNNING) {
digitalWrite(LEDRed, LOW);
digitalWrite(LEDYellow, LOW);
digitalWrite(LEDGreen, HIGH);
} else if (timer1.read() > setTimer1 && timer1.read() < setTimer1 + 120000 && timer1.state() == RUNNING) {
digitalWrite(LEDRed, LOW);
digitalWrite(LEDGreen, LOW);
digitalWrite(LEDYellow, HIGH);
} else if (timer1.read() > setTimer1 + 120000 && timer1.state() == RUNNING) {
digitalWrite(LEDGreen, LOW);
digitalWrite(LEDYellow, LOW);
digitalWrite(LEDRed, HIGH);
}

if (timer2.read() <= setTimer2 && timer2.state() == RUNNING) {
digitalWrite(LEDRed, LOW);
digitalWrite(LEDYellow, LOW);
digitalWrite(LEDGreen, HIGH);
} else if (timer2.read() > setTimer2 && timer2.read() < setTimer2 + 120000 && timer2.state() == RUNNING) {
digitalWrite(LEDRed, LOW);
digitalWrite(LEDGreen, LOW);
digitalWrite(LEDYellow, HIGH);
} else if (timer2.read() > setTimer2 + 120000 && timer2.state() == RUNNING) {
digitalWrite(LEDGreen, LOW);
digitalWrite(LEDYellow, LOW);
digitalWrite(LEDRed, HIGH);
}
}

//


Explaination of code :

This Arduino sketch is designed to work with a mesh network using the painlessMesh library, a GPS module, and multiple timers to control various tasks and LEDs. Below is an explanation of the main components and functionality of the code:

Libraries and Definitions
  • Libraries:
    • painlessMesh.h: For mesh networking.
    • Timer.h: For timer functions.
    • SoftwareSerial.h: For software-based serial communication.
    • TinyGPSPlus.h: For parsing GPS data.
    • SPI.h and EEPROM.h: For SPI communication and EEPROM storage, respectively.
  • Mesh Network Configuration:
    • MESH_PREFIX, MESH_PASSWORD, and MESH_PORT define the mesh network settings.
  • LED Pin Definitions: Define pins for green, red, and yellow LEDs.
  • EEPROM_SIZE: Size of the EEPROM.
Variables
  • Timers:
    • Scheduler userScheduler: Manages scheduled tasks.
    • Timer timer1, timer2: Timer instances for various tasks.
    • Timer1Mem, Timer2Mem: Store timer values.
    • setTimer1, setTimer2: Store initial timer values from EEPROM.
  • Mesh Network Status:
    • connectedToBaseStation, connectedToEXStation: Flags to indicate connection status.
  • GPS and Coordinates:
    • latitudes, longitudes: Arrays to store GPS coordinates.
    • previousMillis, interval: Variables to manage GPS data sampling rate.
    • sampleIndex: Index for storing GPS data.
    • gpsSerial: Software serial instance for GPS communication.
    • gps: TinyGPSPlus instance for parsing GPS data.
  • Other Variables:
    • load: Counter for the number of loads.
    • Total: Stores the total cycle time.
Functions
  • sendMessage:
    • Sends messages with time to and from the EX station, broadcasts total cycle time, and GPS coordinates.
  • GPS_sent:
    • Sends GPS coordinates over the mesh network.
  • loads:
    • Increments and broadcasts the load count.
  • TotalTime:
    • Calculates and broadcasts the total cycle time.
  • Mesh Network Callbacks:
    • nodeTimeAdjustedCallback: Handles time adjustments.
    • newConnectionCallback: Handles new connections and starts/stops timers based on the connection type.
    • changedConnectionCallback: Handles connection changes.
  • Time Extraction Functions:
    • Time1, Time2: Extract timer values from received messages and update EEPROM.
  • receivedCallback:
    • Handles received messages and calls appropriate functions based on the message content.
  • setup:
    • Initializes serial communication, EEPROM, timers, LEDs, mesh network, and tasks.
  • loop:
    • Updates the mesh network, prints timer values, processes GPS data, and controls LEDs based on timer states.
  • print1:
    • Prints timer values to the serial monitor.
  • printGPS:
    • Collects and stores GPS data at regular intervals.
  • timersproccess:
    • Controls LED states based on timer values.
Workflow
  1. Setup:
    • Initializes the mesh network, timers, and GPS module.
    • Reads timer values from EEPROM.
    • Configures LEDs and starts timers.
  2. Loop:
    • Continuously updates the mesh network.
    • Prints current timer values.
    • Collects GPS data and stores it at defined intervals.
    • Controls LED states based on the current timer values.
  3. Callbacks and Message Handling:
    • Handles new connections, connection changes, and received messages.
    • Sends messages with timer values, load count, and GPS coordinates over the mesh network.

This code is designed for a system that tracks and reports the time taken for specific tasks, manages connections between nodes in a mesh network, and collects and transmits GPS data. The LEDs provide visual feedback based on the state and progress of the timers.

Reply all
Reply to author
Forward
0 new messages