#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Encoder.h>
#include <OneButton.h>
//Library for Speed PWM Freq
// LCD SETTINGS
LiquidCrystal_I2C lcd(0x27, 20, 4); // LCD Display Details (I2C address, columns, rows)
OneButton btn_Impact (4, true); // Attach rotary encoder button
// PWM FREQUENCY SETTINGS
// ENCODER SETTINGS
#define ENC_A 3 // Define pin for A
#define ENC_B 2 // Define pin for B
#define ENC_SW 4 // Define pin for Button
#define aux_Power_Pin A3 // Define pin for Aux Power verification (Nano)
/* Encoder Debounce */
unsigned long _lastIncReadTime = micros(); // Debounce (see void read_encoder)
unsigned long _lastDecReadTime = micros(); // Debounce (see void read_encoder)
int _pauseLength = 25000; // Debounce (see void read_encoder)
int _fastIncrement = 10; // Debounce (see void read_encoder)
volatile int counter = 0; // Debounce (see void read_encoder)
byte last_Count_X; //
// SCREEN LABELS
char lbl_Header[] = "DEV4 SIMULATOR"; //
char lbl_Speed[] = "S:"; //
char lbl_Weight[] = "W:"; //
char lbl_Impact[] = "I:"; //
char lbl_Implvl[] = "G"; //
char lbl_Implvl_X[] = "xG"; //
char lbl_Implvl_Y[] = "yG"; //
char lbl_Start_0[] = " START "; //
char lbl_Start_1[] = ">START"; //
char lbl_Cancel_0[] = " CANCEL "; //
char lbl_Cancel_1[] = ">CANCEL"; //
char lbl_ImpCal[] = "IMPACT CALIBRATION"; //
char current_Progress_Count[3] = "0"; //
byte cal_Command = 0; // 0 = Cancel, 1 = Start
// VARIABLES
int speed_Value; // Raw input value from speed potentiometer
float speed_Write; // Converted output to device
byte speed_Pin = A1; // Input pin for speed sensor potentiometer
int speed_Output_Pin = 6; // Output pin for speed sensor
byte weight_Pin = 2; // Pin for Weigh sensor potentiometer
byte impactPin = 3; // Pin for Weigh sensor potentiometer
int selectedVal = 0; // Impact switch case to send to slave Nano
float displayImpact; // Display impact value in .25 increments
float increment_ImpX; // Increment value for Impact selection (may replace selectedVal)
float increment_ImpY; // Increment value for Impact selection (may replace selectedVal)
volatile int x_Val = 0; // Store the X Impact value for sending
volatile int y_Val = 0; // Store the Y Impact value for sending
byte incrCal; // Calibration Start/Cancel Select
byte calMode = 0; // 0 = calMode OFF, 1 = calMode ON.
unsigned int cal_Progress = 0; // Calibration progress value. Updated from slave
byte screenState = 0; // Save the current screen state and do not re-draw
byte counter_State = 0; // Determine if X or Y is currently selected. 0 = X, 1 = Y
int progress_Count = 0; // Calibration event value. Updated from slave
int comm_Baud = 9600; // Baud Rate
int boot_Steps = 5; // Total number of steps in boot sequence
int boot_Complete = 0; // Current boot phase. Updated from slave and master
byte aux_Comm = 0; // Check serial comm trigger to check comm with slave
byte aux_Power = 0; // Check slave power trigger
byte aux_Threshold = 512; // Aux power threshold from slave to determine that slave is powered
float kph_Convert = 1.60934; // Value to convert MPH to KPH
byte axis;
// Custom Characters
/* Main Screen Icons */
byte axis_Select_X[] = {
B00000,
B00100,
B01100,
B11111,
B01100,
B00100,
B00000,
B00000
};
byte axis_Select_Y[] = {
B00000,
B00100,
B00110,
B11111,
B00110,
B00100,
B00000,
B00000
};
byte pulse_ON[] = {
B00000,
B00000,
B01010,
B11111,
B11111,
B01110,
B00100,
B00000
};
byte wheel[] = {
B00000,
B01110,
B10001,
B10101,
B10001,
B01110,
B00000,
B00000
};
byte forks_ON2[] = {
B00000,
B10000,
B10010,
B10111,
B10111,
B01111,
B00000,
B00000
};
byte forks_OFF[] = {
B00000,
B10000,
B10000,
B10000,
B10000,
B01111,
B00000,
B00000
};
byte hit[] = {
B00000,
B10011,
B11001,
B11101,
B11001,
B10011,
B00000,
B00000
};
/* Progress Bar % */
byte pct_0[] = {
B00000,
B11111,
B00000,
B00000,
B00000,
B00000,
B11111,
B00000
};
byte pct_1[] = {
B00000,
B11111,
B10000,
B10000,
B10000,
B10000,
B11111,
B00000
};
byte pct_2[] = {
B00000,
B11111,
B11000,
B11000,
B11000,
B11000,
B11111,
B00000
};
byte pct_3[] = {
B00000,
B11111,
B11100,
B11100,
B11100,
B11100,
B11111,
B00000
};
byte pct_4[] = {
B00000,
B11111,
B11110,
B11110,
B11110,
B11110,
B11111,
B00000
};
byte pct_5[] = {
B00000,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B00000
};
void setup(){
// Set encoder pins and attach interrupts
pinMode(ENC_A, INPUT_PULLUP);
pinMode(ENC_B, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(ENC_A), read_Encoder, CHANGE);
attachInterrupt(digitalPinToInterrupt(ENC_B), read_Encoder, CHANGE);
pinMode(aux_Power_Pin, INPUT_PULLUP);
//LED
pinMode(speed_Pin,INPUT);
//BUTTON FUNCTIONS
btn_Impact.attachClick(singleclick); // Link the function to be called on a single click event
btn_Impact.attachLongPressStop(longclick); // Link the function to be called on a long click event
btn_Impact.attachDoubleClick(double_Click); // Link the function to be called on a double click event
lcd.init(); // Initialize and start LCD
lcd.backlight(); // Turn on backlight
splash_Screen(); //Display Splash Screen
Serial.begin(comm_Baud); // Begin Serial Communication
delay(1000); // Wait 1 seconds - purely aesthetic
lcd.setCursor(0,3);
lcd.println(" Check Impact Power ");
init_Screen(); //Display Initilize Screen
lcd.clear();
lcd.createChar(0, axis_Select_X); // Create special characters for main screen
lcd.createChar(1, axis_Select_Y); // Create special characters for main screen
lcd.createChar(2, wheel); // Create special characters for main screen
lcd.createChar(3, forks_OFF); // Create special characters for main screen
lcd.createChar(4, forks_ON2); // Create special characters for main screen
lcd.createChar(5, hit); // Create special characters for main screen
lcd.createChar(6, pulse_ON); // Create special characters for main screen
primary_Labels(); //display main screen layout
}
// START OF LOOP
void loop(){
listener();
static int lastCounter = 0; // Track counter state
read_Encoder(); // Read the encoder for state change
btn_Impact.tick(); // Check the status of the button. Short press to select, Double press to send, Long press to change screens
if (calMode == 0){
display_ImpactSel(); // Display the current Impact Setting - sends command to slave on short press
detect_Speed(); // This adjusts PWM based upon potentiometer position.
//sendSpeed();
detect_Weight(); // This is a basic reference to potentiometer postion. Dual Potentiometer used to send 5v to Arduino and 12v to Head Unit
if(counter != lastCounter){ // Only do this, if count changed
}
}
if (calMode == 1){
calibration_Impacts(); // Calibrate function. On shortclick, sends command to slave Nano
if(counter != lastCounter){ // Only do this, if count changed
//debug_Cal(); // Uncomment to debug on-screen
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////|
//////////////////////////////////////////////// END OF LOOP \\\\\\\\\\\\\\\\\\\\\\\\\\\\\|
//////////////////////////////////////////////////////////////////////////////////////////|
/* ////////// LISTENER & PRIMARY CONTROLS \\\\\\\\\\ */
void listener(){
if (Serial.available()) { // Check to see if Serial command is available & anything in buffer
String data_from_slave = ""; // Empty String to collect serial data
delay(30); // 30ms delay to catch entire string without double touch
while (Serial.available()) {
data_from_slave += char(Serial.read()); // Collect data and append to itself
}
primary_Control(data_from_slave);
}
}
void primary_Control(String data_from_slave) {
if (data_from_slave.startsWith("p_")){ // Prefix of p_ will update the progress bar
calibration_Progress(data_from_slave);
}
if (data_from_slave.startsWith("t_")){ // Prefix of t_ will update the progress count of total events completed
update_Progress_Count(data_from_slave);
}
if (data_from_slave.startsWith("q_")){ // Prefix of q_ will clear current progress. This is sent by slave in response to STOP command sent from Master
calibration_Progress(data_from_slave);
update_Progress_Count(data_from_slave);
}
if (data_from_slave.startsWith("h_")){ // Heartbeat from Slave
heartbeat(data_from_slave);
}
}
void heartbeat(String data_from_slave){
if (calMode == 0){
int slave_Pulse = data_from_slave.substring(2).toInt(); // Remove prefix cal_Update = number after prefix and will update by this value
switch(slave_Pulse){
case 0:
lcd.setCursor(0,0);
lcd.print(" "); // Write Heartbeat icon
break;
case 1:
lcd.setCursor(0,0);
lcd.write(6); // Write Heartbeat icon
break;
}
}
}
/* ////////// ENCODER BUTTON & ROTARY CONTROLS \\\\\\\\\\ */
void read_Encoder() {
// Encoder interrupt routine for both pins. Updates counter
// if they are valid and have rotated a full indent
static uint8_t old_AB = 3; // Lookup table index
static int8_t encval = 0; // Encoder value
static const int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0}; // Lookup table
old_AB <<=2; // Remember previous state
if (digitalRead(ENC_A)) old_AB |= 0x02; // Add current state of pin A
if (digitalRead(ENC_B)) old_AB |= 0x01; // Add current state of pin B
encval += enc_states[( old_AB & 0x0f )];
// Update counter if encoder has rotated a full indent, that is at least 4 steps
if( encval > 3 ) { // Four steps forward
int changevalue = 1;
if (calMode == 0){
if (counter_State == 0){
//incrImp = incrImp + 0.25;
increment_ImpX = increment_ImpX + 0.1; // Increment X Impact Value
//x_Val = x_Val + changevalue;
}
else if (counter_State == 1){
increment_ImpY = increment_ImpY + 0.1; // Increment Y Impact Value
//y_Val = y_Val + changevalue;
}
}
if((micros() - _lastIncReadTime) < _pauseLength) {
changevalue = _fastIncrement * changevalue;
}
_lastIncReadTime = micros();
counter = counter + changevalue; // Update counter
if (counter_State == 0){
x_Val = x_Val + changevalue; // Update X value
}
if (counter_State == 1){
y_Val = y_Val + changevalue; // Update Y value
}
encval = 0;
//DEBUGGING
/*
unsigned int impPWM;
impPWM = map(counter, 0, 100, 127, 255);
Serial.print("Current Counter is at: ");
Serial.println(counter);
if(calMode == 0){
Serial.print(" Impact PWM Value is: ");
Serial.println(impPWM);
Serial.print(" X Value is: ");
Serial.println(x_Val);
Serial.print(" Y Value is: ");
Serial.println(y_Val);
}
*/
}
else if( encval < -3 ) { // Four steps backward
int changevalue = -1;
if (calMode == 0){
if (counter_State == 0){
increment_ImpX = increment_ImpX - 0.1; // Decrement X Impact Value
//x_Val = x_Val + changevalue;
}
else if (counter_State == 1){
increment_ImpY = increment_ImpY - 0.1; // Decrement Y Impact Value
//y_Val = y_Val + changevalue;
}
}
if((micros() - _lastDecReadTime) < _pauseLength) {
changevalue = _fastIncrement * changevalue;
}
_lastDecReadTime = micros();
counter = counter + changevalue; // Update counter
if (counter_State == 0){
x_Val = x_Val + changevalue; // Update X value
}
if (counter_State == 1){
y_Val = y_Val + changevalue; // Update Y value
}
encval = 0;
//DEBUGGING
/*
unsigned int impPWM; //Debugging
impPWM = map(counter, 0, 100, 127, 255);
Serial.print("Current Counter is at: ");
Serial.println(counter);
if(calMode == 0){
Serial.print(" Impact PWM Value is: ");
Serial.println(impPWM);
Serial.print(" X Value is: ");
Serial.println(x_Val);
Serial.print(" Y Value is: ");
Serial.println(y_Val);
}
*/
}
}
void singleclick(){
if (calMode == 0){ // If not in calibration mode, switch between X and Y
if (counter_State == 1){ // If Y is currently selected, switch to X
counter_State = 0;
lcd.setCursor(10,3);
lcd.write(0);
lcd.setCursor(12,3);
lcd.print(" ");
}else if (counter_State == 0){ // If X is currently selected, switch to Y
counter_State = 1;
lcd.setCursor(12,3);
lcd.write(1);
lcd.setCursor(10,3);
lcd.print(" ");
}
}
if (calMode == 1){ // If in calibration mode, send start or stop command with button press
Serial.print("c");
Serial.println(cal_Command);
}
Serial.println("Single Click triggered");
}
void longclick(){
if (calMode == 0){ //If entering Cal mode
lcd.clear(); // Clear the screen and create percentage custom characters
lcd.createChar(0, pct_0);
lcd.createChar(1, pct_1);
lcd.createChar(2, pct_2);
lcd.createChar(3, pct_3);
lcd.createChar(4, pct_4);
lcd.createChar(5, pct_5);
lcd.createChar(6, axis_Select_Y);
calMode = 1;
subLabels();
}else{ // If exiting cal mode:
lcd.clear(); // Clear the screen & re-create custom characters
lcd.createChar(0, axis_Select_X);
lcd.createChar(1, axis_Select_Y);
lcd.createChar(2, wheel);
lcd.createChar(3, forks_OFF);
lcd.createChar(4, forks_ON2);
lcd.createChar(5, hit);
lcd.createChar(6, pulse_ON);
primary_Labels();
calMode = 0;
}
}
void double_Click(){
if (boot_Complete == boot_Steps){
if (calMode == 0){ // If not in cal mode, just send X Y to Nano
generate_Impact();
}
if (calMode == 1){ // If in cal mode, no current function
//Serial.print("c_");
//Serial.println(counter);
}
}
if (boot_Complete != boot_Steps){
boot_Complete = 5;
//Serial.println("test ok");
}
Serial.println("Double Click triggered");
}
//Encoder
void encoder_Monitor(){
static int lastCounter = 0; // Track counter state
read_Encoder(); // Read the encoder for state change
btn_Impact.tick(); // Check the status of the button. Short press to select, Double press to send, Long press to change screens
}
/* ////////// SCREEN CHANGE CONTROLS \\\\\\\\\\ */
void primary_Labels(){
//HEADER
lcd.setCursor(0,0);
lcd.write(6); // Write Heartbeat icon (ON ONLY AS PLACEHOLDER)
lcd.setCursor(3,0);
lcd.print(lbl_Header);
//SPEED
lcd.setCursor(0,1);
lcd.write(2); // Write Wheel icon
//lcd.print(lbl_Speed);
lcd.setCursor(4,1);
lcd.print("MpH");
lcd.setCursor(11,1);
lcd.print("KpH");
//WEIGHT
lcd.setCursor(0,2);
lcd.write(3); // Write Forks icon
//lcd.print(lbl_Weight);
//IMPACT
lcd.setCursor(0,3);
lcd.write(5); // Write Impact icon
lcd.setCursor(11,3);
lcd.print("-");
/* X IMPACT */
if (counter_State == 0){
lcd.setCursor(10,3);
lcd.write(0); // Write left arrow icon
}else if(counter_State == 1){
lcd.setCursor(12,3);
lcd.write(1); // Write right arrow icon
}
lcd.setCursor(6,3);
lcd.print(lbl_Implvl_X);
/* Y IMPACT */
lcd.setCursor(18,3);
lcd.print(lbl_Implvl_Y);
}
void subLabels(){
lcd.setCursor(3,0);
lcd.print("TM CALIBRATION");
lcd.setCursor(2,1);
lcd.print(" START");
lcd.setCursor(12,1);
lcd.print(" STOP");
/* Write empty progress bar */
lcd.setCursor(0,2);
lcd.write(0);
lcd.setCursor(1,2);
lcd.write(0);
lcd.setCursor(2,2);
lcd.write(0);;
lcd.setCursor(3,2);
lcd.write(0);
lcd.setCursor(4,2);
lcd.write(0);
lcd.setCursor(5,2);
lcd.write(0);
lcd.setCursor(6,2);
lcd.write(0);
lcd.setCursor(7,2);
lcd.write(0);;
lcd.setCursor(8,2);
lcd.write(0);
lcd.setCursor(9,2);
lcd.write(0);
lcd.setCursor(10,2);
lcd.write(0);
lcd.setCursor(11,2);
lcd.write(0);
lcd.setCursor(12,2);
lcd.write(0);;
lcd.setCursor(13,2);
lcd.write(0);
lcd.setCursor(14,2);
lcd.write(0);
lcd.setCursor(15,2);
lcd.write(0);
lcd.setCursor(16,2);
lcd.write(0);
lcd.setCursor(17,2);
lcd.write(0);;
lcd.setCursor(18,2);
lcd.write(0);
lcd.setCursor(19,2);
lcd.write(0);
lcd.setCursor(9,3);
lcd.print("/25");
lcd.setCursor(7,3);
sprintf(current_Progress_Count,"%2d", progress_Count);
lcd.print(current_Progress_Count);
}
void splash_Screen(){
lcd.setCursor(0,0); // Display splash-screen
lcd.println(" ProjPerson");
lcd.setCursor(0,1);
lcd.println(" DEV4 Mini-Sim");
lcd.setCursor(0,2);
lcd.println(" v1.0");
lcd.setCursor(3,3);
lcd.println("Initializing...");
}
void init_Screen(){
do{ // Confirm Impact Sensor is on and functional
encoder_Monitor(); // Monitor encoder during initialization
if (aux_Power == 1){
//analogRead aux_Power_Pin
analogRead(aux_Power_Pin);
if (aux_Power_Pin > aux_Threshold){ //CHANGE TO aux_Power with condition
aux_Power = 1;
boot_Complete = 1;
Serial.println("received boot1");
lcd.setCursor(0,3);
lcd.println(" Impact Power Good ");
delay(500);
lcd.setCursor(0,3);
lcd.println(" Check Impact Comms ");
aux_Comm = 1;
}
}
if (aux_Comm == 1){ // Don't send comm command until power is verified
Serial.println("test");
}
if (Serial.available()) { //Check to see if Serial command is available
String data_from_slave = ""; //Empty String to collect serial data
delay(30); //30ms delay to catch entire string without double touch
while (Serial.available()) {
data_from_slave += char(Serial.read()); //Collect data and append to itself
if (data_from_slave == "test ok"){
boot_Complete = 2;
Serial.println("received test ok");
lcd.setCursor(0,3);
lcd.println(" Impact Comms Ready ");
delay(500);
lcd.setCursor(0,3);
lcd.println(" Starting DEV4 Sim ");
delay(1000);
boot_Complete = 5;
aux_Comm = 0;
}else{
//Place holder for additional checks during startup
}
}
}
}
while (boot_Complete != boot_Steps);
}
/* ////////// DETECTION & OUTPUT CONTROLS \\\\\\\\\\ */
void detect_Speed(){
//Speed Value
unsigned int current_Speed = analogRead(speed_Pin);
unsigned int speed_Percent = map(current_Speed, 0, 1023, 0, 100); // Speed % of throttle reference
unsigned int speed_Output = map(current_Speed, 0, 1023, 255, 0); // Speed PWM output
unsigned int mph_Val = map(speed_Percent, 0, 100, 0, 25); // Display MPH reference
unsigned int kph_Val = round(mph_Val * kph_Convert); // Display KPH reference
speed_Value = analogRead(speed_Pin); // Get current value of potentiometer for PWM
speed_Write = map(speed_Value, 0, 1023, 0, 255); // Convert to speed PWM output range
analogWrite(speed_Output_Pin,speed_Output); // Output PWM to speed sensor output
//MAP ROUGH MPH/KPH VALUES
lcd.setCursor(2,1);
char mph_Display[2];
sprintf(mph_Display, "%02d", mph_Val);
lcd.print(mph_Display);
lcd.setCursor(9,1);
char kph_Display[6];
sprintf(kph_Display, "%02d", kph_Val);
lcd.print(kph_Display);
lcd.setCursor(16,1);
char speed_Display_Pct[5];
sprintf(speed_Display_Pct, "%3d%%", speed_Percent);
lcd.print(speed_Display_Pct);
// PWM CONTROL
}
void detect_Weight(){
unsigned int current_Weight = analogRead(weight_Pin);
unsigned int weight_Percent = map(current_Weight, 0, 1023, 0, 100);
unsigned int simulated_Weight =map(current_Weight, 0, 1023, 0, 5000);
if (simulated_Weight <= 0){
lcd.setCursor(2,2);
lcd.print("OFF ");
lcd.setCursor(0,2);
lcd.write(byte(3));
}
else if (simulated_Weight > 0 && (simulated_Weight < 175)) {
lcd.setCursor(2,2);
lcd.print("GND ");
lcd.setCursor(0,2);
lcd.write(byte(3));
}
else if (simulated_Weight > 175 && (simulated_Weight < 300)) {
lcd.setCursor(2,2);
lcd.print("EMP ");
lcd.setCursor(0,2);
lcd.write(byte(3));
}
else if (simulated_Weight > 300 && (simulated_Weight < 4900)) {
lcd.setCursor(2,2);
lcd.print("LOAD");
lcd.setCursor(0,2);
lcd.write(byte(4));
}
else if (simulated_Weight > 4900) {
lcd.setCursor(2,2);
lcd.print("MAX ");
lcd.setCursor(0,2);
lcd.write(byte(4));
}
//Calibration Zone Notification
if (simulated_Weight > 2400 && (simulated_Weight < 2600)) {
lcd.setCursor(6,2);
lcd.print("c");
lcd.setCursor(0,2);
lcd.write(byte(4));
}
else{
lcd.setCursor(6,2);
lcd.print(" ");
}
lcd.setCursor(9,2);
char simulated_Val[5];
sprintf(simulated_Val, "%04d", simulated_Weight); // Display current simulated weight lbs/kg is irrelevant
lcd.print(simulated_Val);
lcd.setCursor(16,2);
char weight_Val[5];
sprintf(weight_Val, "%3d%%", weight_Percent); // Display current weight percent reference
lcd.print(weight_Val);
}
void generate_Impact(){
char static_Impact[10];
sprintf(static_Impact, "g_%03d%03d%1d", x_Val, y_Val, counter_State); // Send X & Y values to Slave with the axis that was selected.
Serial.println(static_Impact);
}
void display_ImpactSel(){
if (counter_State == 0){
if (x_Val < 0){
x_Val = 100;
increment_ImpX = 10;
}
if (x_Val > 100){
x_Val = 0;
increment_ImpX = 0;
}
}
else if (counter_State == 1){
if (y_Val < 0){
y_Val = 100;
increment_ImpY = 10;
}
if (y_Val > 100){
y_Val = 0;
increment_ImpY = 0;
}
}
/* X VALUE */
char impact_Setting_X[6];
dtostrf(increment_ImpX, 4, 1, impact_Setting_X);
lcd.setCursor(2,3);
lcd.print(impact_Setting_X);
/* Y VALUE */
char impact_Setting_Y[6];
dtostrf(increment_ImpY, 4, 1, impact_Setting_Y);
lcd.setCursor(14,3);
lcd.print(impact_Setting_Y);
}
/* ////////// IMPACT CALIBRATION CONTROLS \\\\\\\\\\ */
void calibration_Impacts(){
if (counter <= 0){
counter = 0;
lcd.setCursor(2,1);
//lcd.print(">START");
lcd.write(6);
lcd.setCursor(12,1);
//lcd.print(" STOP");
lcd.print(" ");
cal_Command = 1;
}else if (counter >= 1){
counter = 1;
lcd.setCursor(2,1);
lcd.print(" ");
lcd.setCursor(12,1);
lcd.write(6);
cal_Command = 0;
}
//update progress bar!
// cal_Progress = cal_Progress + cal_Update
}
void calibration_Progress(String data_from_slave){
int cal_Update = data_from_slave.substring(2).toInt(); // Remove prefix cal_Update = number after prefix and will update by this value
if (cal_Update > 0){
//Serial.print("Update Progress by: ");
//Serial.println(cal_Update);
cal_Progress = cal_Progress + cal_Update; // Update progress bar value by adding value sent from slave
//Serial.print("Current Progress: ");
//Serial.print(cal_Progress);
//Serial.println("%");
update_ProgressBar(cal_Progress, 100, 2); // Call update ProgressBar function with value, total count, and line to print on
}
else if (cal_Update == 0){ // Remove progress, set to 0, re-draw progress bar
cal_Progress = 0;
update_ProgressBar(cal_Progress,100,2);
subLabels();
}
}
void update_Progress_Count(String data_from_slave){
int cal_Update = data_from_slave.substring(2).toInt();
if (cal_Update == 0){ // Command p_0 will reset this count to 0
progress_Count = 0;
}
if (cal_Update > 0){ // Increment by 1 with p_1
progress_Count = progress_Count + 1;
}
if (progress_Count >= 25){ // MAX count = 25
progress_Count = 25;
}
lcd.setCursor(7,3); // Print current count to display
char current_Progress_Count[2];
sprintf(current_Progress_Count,"%2d", progress_Count);
lcd.print(current_Progress_Count);
}
void update_ProgressBar(unsigned long cal_Progress, unsigned long total_Count, int lineToPrintOn){
double factor = total_Count/100.0; // Take the total count & divide by number of vertical slots on LCD screen
int percent = (cal_Progress)/factor; // Make a percentage Current Count / Total Count
int number = percent/5; // Divide by 5. 5 lines per LCD position
int remainder = percent%5; // Obtain the remainder of the number. This is divisible by 5
if (number > 0){
lcd.setCursor(number-1, lineToPrintOn); // Print character that matches whole number 0-5. If 9 were the number, this would be 5
lcd.write(5);
}
lcd.setCursor(number, lineToPrintOn); // Print character that matches 0-4 as the remainder. If 9 were the number, this will be 4
lcd.write(remainder);
}