#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)
connectedToBaseStation = 1;
// timer2.pause();
}
// Check if connected node is the EX station (Excavator)
connectedToEXStation = 1;
timer1.pause();
timer2.start();
}
}
void changedConnectionCallback() {
Serial.printf("Changed connections\n");
// Check if the connection to the base station is lost
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- Setup:
- Initializes the mesh network, timers, and GPS module.
- Reads timer values from EEPROM.
- Configures LEDs and starts timers.
- 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.
- 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.