I'm getting an error when trying to compile my code using PlatformIO in VSCode.
.pio\build\uno\src\lpcooling_calibration\lpcooling_calibration.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `substring(char*, unsigned char, unsigned char, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_calibration\lpcooling_calibration.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `concat(char const*, char, char const*, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_calibration\lpcooling_calibration.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `concat(char const*, char, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_calibration\lpcooling_calibration.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `concat(char const*, char const*, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_calibration\lpcooling_calibration.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `remove(char*, unsigned char, unsigned char)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_calibration\lpcooling_calibration.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `mapProgress(unsigned int, long, long)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_calibration\lpcooling_calibration.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `mapProgress(unsigned int, float, float)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_i2c\lpcooling_i2c.cpp.o (symbol from plugin): In function `lcd':
(.text+0x0): multiple definition of `substring(char*, unsigned char, unsigned char, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_i2c\lpcooling_i2c.cpp.o (symbol from plugin): In function `lcd':
(.text+0x0): multiple definition of `concat(char const*, char, char const*, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_i2c\lpcooling_i2c.cpp.o (symbol from plugin): In function `lcd':
(.text+0x0): multiple definition of `concat(char const*, char, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_i2c\lpcooling_i2c.cpp.o (symbol from plugin): In function `lcd':
(.text+0x0): multiple definition of `concat(char const*, char const*, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_i2c\lpcooling_i2c.cpp.o (symbol from plugin): In function `lcd':
(.text+0x0): multiple definition of `remove(char*, unsigned char, unsigned char)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_i2c\lpcooling_i2c.cpp.o (symbol from plugin): In function `lcd':
(.text+0x0): multiple definition of `mapProgress(unsigned int, long, long)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_i2c\lpcooling_i2c.cpp.o (symbol from plugin): In function `lcd':
(.text+0x0): multiple definition of `mapProgress(unsigned int, float, float)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_menu\lpcooling_menu.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `substring(char*, unsigned char, unsigned char, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_menu\lpcooling_menu.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `concat(char const*, char, char const*, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_menu\lpcooling_menu.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `concat(char const*, char, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_menu\lpcooling_menu.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `concat(char const*, char const*, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_menu\lpcooling_menu.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `remove(char*, unsigned char, unsigned char)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_menu\lpcooling_menu.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `mapProgress(unsigned int, long, long)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_menu\lpcooling_menu.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `mapProgress(unsigned int, float, float)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_monitoring\lpcooling_monitoring.cpp.o (symbol from plugin): In function `lastLoggingTime':
(.text+0x0): multiple definition of `substring(char*, unsigned char, unsigned char, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_monitoring\lpcooling_monitoring.cpp.o (symbol from plugin): In function `lastLoggingTime':
(.text+0x0): multiple definition of `concat(char const*, char, char const*, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_monitoring\lpcooling_monitoring.cpp.o (symbol from plugin): In function `lastLoggingTime':
(.text+0x0): multiple definition of `concat(char const*, char, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_monitoring\lpcooling_monitoring.cpp.o (symbol from plugin): In function `lastLoggingTime':
(.text+0x0): multiple definition of `concat(char const*, char const*, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_monitoring\lpcooling_monitoring.cpp.o (symbol from plugin): In function `lastLoggingTime':
(.text+0x0): multiple definition of `remove(char*, unsigned char, unsigned char)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_monitoring\lpcooling_monitoring.cpp.o (symbol from plugin): In function `lastLoggingTime':
(.text+0x0): multiple definition of `mapProgress(unsigned int, long, long)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_monitoring\lpcooling_monitoring.cpp.o (symbol from plugin): In function `lastLoggingTime':
(.text+0x0): multiple definition of `mapProgress(unsigned int, float, float)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_utils\lpcooling_utils.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `substring(char*, unsigned char, unsigned char, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_utils\lpcooling_utils.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `concat(char const*, char, char const*, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_utils\lpcooling_utils.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `concat(char const*, char, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_utils\lpcooling_utils.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `concat(char const*, char const*, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_utils\lpcooling_utils.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `remove(char*, unsigned char, unsigned char)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_utils\lpcooling_utils.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `mapProgress(unsigned int, long, long)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\lpcooling_utils\lpcooling_utils.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `mapProgress(unsigned int, float, float)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.ino.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `substring(char*, unsigned char, unsigned char, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.ino.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `concat(char const*, char, char const*, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.ino.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `concat(char const*, char, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.ino.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `concat(char const*, char const*, char*)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.ino.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `remove(char*, unsigned char, unsigned char)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.ino.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `mapProgress(unsigned int, long, long)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
.pio\build\uno\src\main.ino.cpp.o (symbol from plugin): In function `substring(char*, unsigned char, unsigned char, char*)':
(.text+0x0): multiple definition of `mapProgress(unsigned int, float, float)'
.pio\build\uno\src\globals.cpp.o (symbol from plugin):(.text+0x0): first defined here
C:\Users\Shaun\AppData\Local\Temp\ccFNxbJg.ltrans0.ltrans.o: In function `main':
<artificial>:(.text.startup+0x452): undefined reference to `setup'
<artificial>:(.text.startup+0x45a): undefined reference to `loop'
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\uno\firmware.elf] Error 1
I've been moving the fucntion into new source files to try and avoid multiple definitions of these functions and using namespaces to no success. If someone can help me make sense of this error I'd appreciate it.
main.ino
#include <Arduino.h>
//User header files
#include "main.h"
#include "globals.h"
#include "lpcooling_utils/lpcooling_utils.h"
#include "lpcooling_i2c/lpcooling_i2c.h"
#include "lpcooling_menu/lpcooling_menu.h"
#include "lpcooling_calibration/lpcooling_calibration.h"
#include "lpcooling_monitoring/lpcooling_monitoring.h"
namespace lpcooling{
void setup() {
// put your setup code here, to run once:
// initialise serial communication
Serial.begin(SERIAL_BAUD);
i2c__init();
Wire.begin();
// initialise the push buttons
pinMode(buttonUpPin, INPUT_PULLUP);
pinMode(buttonDownPin, INPUT_PULLUP);
pinMode(buttonLeftPin, INPUT_PULLUP);
pinMode(buttonRightPin, INPUT_PULLUP);
pinMode(buttonEnterPin, INPUT_PULLUP);
// initialise the toggle switch
pinMode(toggleSwitchPin, INPUT_PULLUP);
delay(100);
startSampling();
// initialise mode according to the toggleSwitch state and attach interrupts
// monitor__init();
if (digitalRead(toggleSwitchPin)){
isMonitoring = true;
isCalibrating = false;
isSampling = true;
} else {
isMonitoring = false;
calibrationState = CALIBRATION_IDLE;
isCalibrating = true;
isSampling = true;
}
// menuMain__init();
}
void loop() {
// get readings from the pressure sensor and digital input
menuMain();
readButtons();
monitorMain();
calibration();
}
} // namespace lpcooling
main.h
#ifndef LPCOOLING_H
#define LPCOOLING_H
#include <Arduino.h>
#include <SPI.h>
#include <Wire.h>
#include <LcdMenu.h>
#include <string.h>
#include <stdint.h>
namespace lpcooling{
// Function prototypes******************************************************************************************************************
} // namespace lpcooling
#endif // LPCOOLING_H
globals.h
#ifndef GLOBALS_H
#define GLOBALS_H
#include <MenuItem.h>
#include <LcdMenu.h>
#include <string.h>
namespace lpcooling{
//Global variables, constants and definitions*******************************************************************************************************************
//Globals variables************************************************************************
// declare global variables
extern bool isOnBacklight;
extern double pressureReading;
extern bool valveState;
extern String vState;
extern bool isSampling;
extern bool isMonitoring;
extern bool isCalibrating;
extern double pressureBar;
extern float scaleFactor;
// decalare button states
enum ButtonState{
BUTTON_NONE,
BUTTON_UP,
BUTTON_DOWN,
BUTTON_LEFT,
BUTTON_RIGHT,
BUTTON_ENTER,
};
extern ButtonState currentButtonState;
enum CalibrationState {
CALIBRATION_IDLE,
CALIBRATION_INPUT_0,
CALIBRATION_INPUT_0_1,
CALIBRATION_INPUT_1,
CALIBRATION_INPUT_2,
CALIBRATION_INPUT_3_1,
CALIBRATION_INPUT_3_2,
CALIBRATION_INPUT_3_3,
CALIBRATION_COMPLETE
};
// extern RTC_DS3231 rtc;
// define SD card chip
extern const int chipSelectSD;
extern const int SSDCard;
// extern const unsigned long lcdScrollDelay;
extern const int calibrationRepeats;
extern CalibrationState calibrationState;
//CONSTANTS*********************************************************************************
//Constants and definitions
// define calibration analogue pins
#define input1Pin A0
#define input2Pin A1
#define pressureSensorPin A2
#define input0Pin A3
#define REF_VOLTAGE 5.12
#define CAL_VOLTAGE 3275
// define the 5 push buttons digital input pins
#define buttonUpPin 4
#define buttonDownPin 3
#define buttonLeftPin 0
#define buttonRightPin 1
#define buttonEnterPin 5
// define the toggle switch digital input
#define toggleSwitchPin 2
// define valve state pin
#define valveStatePin 8
// define LCD paramaters
#define LCD_SELECT 0x27
#define LCD_ROWS 2
#define LCD_COLS 16
#define LCD_SCROLL_DELAY 1000
#define LCD_BLANK "~"
// define serial rate
#define SERIAL_BAUD 9600
// configure keyboard keys (ASCII)
#define UP 56 // NUMPAD 8
#define DOWN 50 // NUMPAD 2
#define LEFT 52 // NUMPAD 4
#define RIGHT 54 // NUMPAD 6
#define ENTER 53 // NUMPAD 5
#define BACK 55 // NUMPAD 7
#define BACKSPACE 8 // BACKSPACE
#define CLEAR 46 // NUMPAD .
#endif //GLOBALS_H
} // namespace lpcooling
globals.cpp
//STD Libraries
#include <SPI.h>
#include <Wire.h>
#include <RTClib.h>
#include <string.h>
#include <stdint.h>
//User header files
#include "globals.h"
namespace lpcooling{
// define and create variables for the pressure sensor and analogue input readings
bool isOnBacklight = false;
double pressureReading = 0.0;
bool digitalReading = false;
bool valveState = false;
bool isCalibrating = false;
bool isSampling = true;
bool isMonitoring = false;
double pressureBar = 0.0;
float scaleFactor = 1.0;
String vState = "";
const int chipSelectSD = 4;
const int SSDCard = 10;
// const unsigned long lcdScrollDelay = 1000;
const int calibrationRepeats = 10;
// initialise button state
ButtonState currentButtonState = BUTTON_NONE;
CalibrationState calibrationState = CALIBRATION_IDLE;
}
lpcooling_utils.h
#ifndef LPCOOLING_UTILS_H
#define LPCOOLING_UTILS_H
double getPressureReading();
void startSampling();
void startMonitoring();
void stopMonitoring();
void readButtons();
#endif // lpcooling_utils
lpcooling_utils.cpp
#include "../globals.h"
using namespace lpcooling;
void startSampling(){
isSampling = true;
isMonitoring = false;
isCalibrating = false;
}
void startMonitoring(){
isSampling = true;
isMonitoring = true;
isCalibrating = false;
}
void stopMonitoring(){
isSampling = true;
isMonitoring = false;
// reinitialise default calibarionState
calibrationState = CALIBRATION_IDLE;
isCalibrating = true;
}
double getPressureReading(){
return pressureBar;
}
void readButtons(){
bool buttonUpState = digitalRead(buttonUpPin);
if (buttonUpState == HIGH){
currentButtonState = BUTTON_UP;
} else{
currentButtonState = BUTTON_NONE;
}
bool buttonDownState = digitalRead(buttonDownPin);
if (buttonDownState == HIGH){
currentButtonState = BUTTON_DOWN;
} else{
currentButtonState = BUTTON_NONE;
}
bool buttonLeftState = digitalRead(buttonLeftPin);
if (buttonLeftState == HIGH){
currentButtonState = BUTTON_LEFT;
} else{
currentButtonState = BUTTON_NONE;
}
bool buttonRightState = digitalRead(buttonRightPin);
if (buttonRightState == HIGH){
currentButtonState = BUTTON_RIGHT;
} else{
currentButtonState = BUTTON_NONE;
}
bool buttonEnterState = digitalRead(buttonEnterPin);
if (buttonEnterState == HIGH){
currentButtonState = BUTTON_ENTER;
} else{
currentButtonState = BUTTON_NONE;
}
}
lpcooling_monitoring.h
#ifndef LPCOOLING_MONITORING_H
#define LPCOOLING_MONITORING_H
#include <RTClib.h>
// Function prototypes******************************************************************************************************************
void monitor__init();
void monitorMain();
void handleMonitoring();
#endif // LPCOOLING_MONITORING_H
lpcooling_monitoring.cpp
//User header files
#include "../globals.h"
// #include "../main.h"
#include "lpcooling_monitoring.h"
#include "../lpcooling_utils/lpcooling_utils.h"
#include "../lpcooling_i2c/lpcooling_i2c.h"
using namespace lpcooling;
double pressureSum = 0.0;
double pressureMin = 0.0;
double pressureMax = 0.0;
int sampleCount = 0;
const int numSamples = 100;
const unsigned long loggingInterval = 5000;
DateTime lastLoggingTime;
void monitor__init() {
// put your setup code here, to run once:
attachInterrupt(digitalPinToInterrupt(toggleSwitchPin), startMonitoring, RISING);
attachInterrupt(digitalPinToInterrupt(toggleSwitchPin), stopMonitoring, FALLING);
}
void monitorMain() {
// put your main code here, to run repeatedly:
//presure reading
if (isSampling){
pressureReading = analogRead(pressureSensorPin)*scaleFactor;
pressureSum += pressureReading;
sampleCount++;
if (pressureReading > pressureMax){
pressureMax = pressureReading;
}
else if (pressureReading < pressureMin){
pressureMin = pressureReading;
}
if (sampleCount >= numSamples){
//convert analogue voltage reading to pressure value
// double pressureBar = 0.25*((2.176*(pressureSum/sampleCount)/2 + 2.72)/680) -1;
// double pressureBar = 0.25*((1.088*(pressureSum/sampleCount)/2 + 2.72)/680) -1;
pressureBar = 1.2*((2.176*(pressureSum/sampleCount) + 2.72)/680) -4.8;
//valve state
valveState = digitalRead(valveStatePin);
vState = valveState ? "Active" : "Inactive";
// update the display with the current readings
lcdClear();
writeLCD("Pressure: " + String(pressureBar) + " bar", "Valve: " + vState );
// reset sampleCount and pressureSum
sampleCount = 0;
pressureSum = 0;
// log the readings to the SD card
if (isMonitoring){
handleMonitoring();
}
}
}
}
void handleMonitoring() {
// code to handle data logging and display of the readings
DateTime now = getNow();
if (isMonitoring){
unsigned long elapsedMillis = now.unixtime() - lastLoggingTime.unixtime();
if (elapsedMillis >= loggingInterval){
lastLoggingTime = now;
String sdTxt [] = { now.timestamp() + " Pressure Reading (Min|Nom|Max): " + pressureMin + "|" + String(pressureBar) + "|" + pressureMax + " " + "Safety Valve: " + vState };
writeSDCard(sdTxt);
}
}
else{
unsigned long elapsedMillis = now.unixtime() - lastLoggingTime.unixtime();
if (elapsedMillis >= loggingInterval){
lastLoggingTime = now;
String sdTxt [] = {"CALIBRATION MODE ACTIVE"};
writeSDCard(sdTxt);
}
}
}
lpcooling_menu.h
#ifndef LPCOOLING_MENU_H
#define LPCOOLING_MENU_H
#include <Arduino.h>
// Function prototypes******************************************************************************************************************
void menuMain__init();
void menuMain();
#endif // LPCOOLING_MENU_H
lpcooling_menu.cpp
//STD Libraries
#include <LcdMenu.h>
#include <Constants.h>
#include <ItemCommand.h>
#include <ItemSubMenu.h>
#include <ItemToggle.h>
//User header files
#include "../globals.h"
// #include "../main.h"
#include "../lpcooling_i2c/lpcooling_i2c.h"
#include "lpcooling_menu.h"
using namespace lpcooling;
MenuItem* settingsMenu[] = { ITEM_TOGGLE("Toggle Backlight", toggleBacklight),
ITEM_BASIC("Clear SD Card") };
LcdMenu menu(LCD_ROWS, LCD_COLS);
// add the submenus to the main menu
MAIN_MENU(
ITEM_BASIC("Monitoring"),
ITEM_BASIC("Calibration"),
ITEM_SUBMENU("Settings", settingsMenu)
);
void menuMain__init() {
// Initialize LcdMenu with the menu items
menu.setupLcdWithMenu(LCD_SELECT, mainMenu);
}
void menuMain() {
if (currentButtonState == BUTTON_UP)
menu.up();
else if (currentButtonState == BUTTON_DOWN)
menu.down();
else if (currentButtonState == BUTTON_LEFT)
menu.left();
else if (currentButtonState == BUTTON_RIGHT)
menu.right();
else if (currentButtonState == BUTTON_ENTER)
menu.enter();
}
lpcoolong_i2c.h
#ifndef LPCOOLING_I2C_H
#define LPCOOLING_I2C_H
#include <string.h>
#include <RTClib.h>
void scrollMessage(int row, String message, int delayTime, int totalColumns);
void writeLCD(String textline1, String textline2);
void writeSDCard(String text[]);
void toggleBacklight(uint8_t isOn);
DateTime getNow();
void lcdClear();
int retryWriteSD ();
void i2c__init();
#endif // LPCOOLING_I2C_H
lpcooling_i2c.cpp
#include "../globals.h"
#include <RTClib.h>
#include <LiquidCrystal_I2C.h>
#include <SD.h>
#include <string.h>
using namespace lpcooling;
// define and initialise LCD
LiquidCrystal_I2C lcd(LCD_SELECT, LCD_COLS, LCD_ROWS);
// define and initialise RTC
RTC_DS3231 rtc;
// define dataFile for RTC
File dataFile;
void i2c__init(){
lcd.init();
lcd.backlight();
isOnBacklight = true;
// set SS to output
pinMode(SSDCard,OUTPUT);
// initialise the RTC
if (! rtc.begin()) {
lcd.print("RTC failed");
while (1);
}
if(rtc.lostPower()) {
// this will adjust to the date and time at compilation
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
// initialise the SD card
if (!SD.begin(chipSelectSD)) {
lcd.print("SD card failed");
while (1);
}
}
void scrollMessage(int row, String message, int delayTime, int totalColumns) {
for (int i=0; i < totalColumns; i++) {
message = " " + message;
}
message = message + " ";
for (unsigned int position = 0; position < message.length(); position++) {
lcd.setCursor(0, row);
lcd.print(message.substring(position, position + totalColumns));
delay(delayTime);
}
}
void writeLCD(String textline1, String textline2){
if (textline1 != LCD_BLANK && textline1.length() < LCD_COLS){
lcd.setCursor(0, 0);
lcd.print(textline1);
}
else {
scrollMessage(0, textline1, LCD_SCROLL_DELAY, LCD_COLS);
}
if (textline2 != LCD_BLANK && textline2.length() < LCD_COLS){
lcd.setCursor(1, 0);
lcd.print(textline2);
}
else {
scrollMessage(1, textline2, LCD_SCROLL_DELAY, LCD_COLS);
}
}
void lcdClear(){
lcd.clear();
}
void toggleBacklight(uint8_t isOn){
if (isOn) {
lcd.backlight();
isOn = true;
} else {
lcd.noBacklight();
isOn = false;
}
}
int retryWriteSD (){
int retryCount = 0;
bool writeSuccess = false;
while (retryCount < 4 && ! writeSuccess ){
if (! dataFile){
retryCount++;
writeSuccess = false;
writeLCD("SD CARD WRITE", "ERROR (" + String(retryCount) + "/3)");
delay(50);
} else{
writeSuccess = true;
return 1;
}
}
return 0;
}
DateTime getNow(){
DateTime now = rtc.now();
return now;
}
void writeSDCard(String text[]){
DateTime now = getNow();
if (isMonitoring){
String fileName = String(now.year()) + "-" + String(now.month()) + "-" + String(now.day()) + "-MONITORING.txt";
dataFile = SD.open(fileName,FILE_WRITE);
if (retryWriteSD() == 1){
dataFile.println(text[0]);
dataFile.flush();
dataFile.close();
}else{
lcdClear();
writeLCD("DATA NOT", "RECORDED");
}
} else if (isCalibrating){
String fileName = String(now.year()) + "-" + String(now.month()) + "-" + String(now.day()) + "-CALIBRATION.txt";
dataFile = SD.open(fileName,FILE_WRITE);
if (retryWriteSD() == 1){
dataFile.println(text[0]);
dataFile.println(text[1]);
dataFile.println(text[2]);
dataFile.println(text[3]);
dataFile.flush();
dataFile.close();
}else{
lcdClear();
writeLCD("DATA NOT", "RECORDED");
}
}
}
lpcooling_calibration.h
#ifndef LPCOOLING_CALIBRATION_H
#define LPCOOLING_CALIBRATION_H
// Function prototypes******************************************************************************************************************
void calibration();
void handleUserInput();
void readInputValues();
#endif // LPCOOLING_CALIBRATION_H
lpcooling_calibration.cpp
#include <string.h>
//User header files
// #include "../main.h"
#include "../lpcooling_i2c/lpcooling_i2c.h"
#include "../lpcooling_utils/lpcooling_utils.h"
#include "../globals.h"
#include "lpcooling_calibration.h"
using namespace lpcooling;
long input0Sum = 0;
long input0Sum10 [10] ;
long input0SumHigh = 0;
long input0SumLow = 0;
double input1Value = 0.0;
double input2Value = 0.0;
double input31Value = 0.0;
bool input32Value = false;
double convertedInput1 = 0.0;
double convertedInput2 = 0.0;
void calibration() {
while (isCalibrating && digitalRead(toggleSwitchPin)){
switch (calibrationState) {
case CALIBRATION_IDLE:{
// Display idle screen or instructions
// Wait for user input to start calibration
lcdClear();
writeLCD("Press enter to"," start ");
break;
}
case CALIBRATION_INPUT_0:{
// display instructions for internal reference analogue calibration
lcdClear();
writeLCD("CONNECT PIN 3.3V","TO PIN A3 AND PRESS ENTER TO CONTINUE");
break;
}
case CALIBRATION_INPUT_0_1:{
readInputValues();
long sum = 0;
for (int k = 0; k < 10; k++){
sum += input0Sum10[k];
}
long average = sum/10;
scaleFactor = CAL_VOLTAGE/average;
lcdClear();
writeLCD("CAL_0 COMPLETE","PRESS ENTER");
break;
}
case CALIBRATION_INPUT_1:{
// Display input 1 calibration screen
// Read and display input 1 value in real-time
// Allow user to adjust potentiometer for calibration
// Wait for user to press enter button to proceed to the next input
readInputValues();
convertedInput1 = 4.8 * input1Value;
lcdClear();
writeLCD("Current: " + String(convertedInput1),"Target: 19V");
break;
}
case CALIBRATION_INPUT_2:{
// Display input 2 calibration screen
// Read and display input 2 value in real-time
// Allow user to adjust potentiometer for calibration
// Wait for user to press enter button to proceed to the next input
readInputValues();
convertedInput2 = 4.8 * input2Value;
lcdClear();
writeLCD("Current: " + String(convertedInput2), "Target: 6.7V" );
break;
}
case CALIBRATION_INPUT_3_1:{
// Display input 3 calibration screen
// Read and display input 3 value in real-time
// Allow user to adjust potentiometer for calibration
// Wait for user to press enter button to complete the calibration
// readInputValues();
// double convertedInput3 = 1.2*((2.176*(input3Value) + 2.72)/680) -4.8;
lcdClear();
writeLCD("Apply pressure", String(getPressureReading()) + " bar/2.3 bar");
break;
}
case CALIBRATION_INPUT_3_2:{
lcdClear();
writeLCD("Adjust input 2","until active");
break;
}
case CALIBRATION_INPUT_3_3:{
lcdClear();
writeLCD("Valve State: ", vState );
break;
}
case CALIBRATION_COMPLETE:{
// Display calibration complete screen or message
// Perform any necessary actions after calibration is complete
// wait for data to finish being written to SD card
String calibrationTxt [] = {"CALIBRATION INFORMATION START",
"Input 1: " + String(convertedInput1) + "/19V",
"Input 2: " + String(convertedInput2) + "/6.7V",
"Pressure Sensor Reading: " + String(getPressureReading()) + "/2.3bar" } ;
writeSDCard(calibrationTxt);
lcdClear();
writeLCD("Calibration Done", "Toggle Switch");
break;
}
}
// Perform any other tasks, such as handling user input, LCD updates, etc.
handleUserInput();
}
}
void handleUserInput() {
// Handle user input, such as button presses, for calibration process
switch (calibrationState) {
case CALIBRATION_IDLE:
// Check if user pressed start button to initiate calibration
// Transition to CALIBRATION_INPUT_0 state
if (currentButtonState == BUTTON_ENTER)
calibrationState = CALIBRATION_INPUT_0;
break;
case CALIBRATION_INPUT_0:
// Check if user pressed enter button to proceed to next input
// Transition to CALIBRATION_INPUT_1 state
if (currentButtonState == BUTTON_ENTER)
calibrationState = CALIBRATION_INPUT_0_1;
break;
case CALIBRATION_INPUT_0_1:
// Check if user pressed enter button to proceed to next input
// Transition to CALIBRATION_INPUT_1 state
if (currentButtonState == BUTTON_ENTER)
calibrationState = CALIBRATION_INPUT_1;
break;
case CALIBRATION_INPUT_1:
// Check if user pressed enter button to proceed to next input
// Transition to CALIBRATION_INPUT_2 state
if (currentButtonState == BUTTON_ENTER)
calibrationState = CALIBRATION_INPUT_2;
break;
case CALIBRATION_INPUT_2:
// Check if user pressed enter button to proceed to next input
// Transition to CALIBRATION_INPUT_3_1 state
if (currentButtonState == BUTTON_ENTER)
calibrationState = CALIBRATION_INPUT_3_1;
break;
case CALIBRATION_INPUT_3_1:
// Check if user pressed enter button to complete calibration
// Transition to CALIBRATION_INPUT_3_2 state
if (currentButtonState == BUTTON_ENTER)
calibrationState = CALIBRATION_INPUT_3_2;
break;
case CALIBRATION_INPUT_3_2:
// Check if user pressed enter button to complete calibration
// Transition to CALIBRATION_INPUT_3_3 state
if (currentButtonState == BUTTON_ENTER)
calibrationState = CALIBRATION_INPUT_3_3;
break;
case CALIBRATION_INPUT_3_3:
// Check if user pressed enter button to complete calibration
// Transition to CALIBRATION_COMPLETE state
if (currentButtonState == BUTTON_ENTER)
calibrationState = CALIBRATION_COMPLETE;
break;
case CALIBRATION_COMPLETE:
// Handle any additional user input or actions after calibration is complete
break;
}
}
void readInputValues() {
// Read and update the input values for calibration
switch (calibrationState) {
case CALIBRATION_INPUT_0:
break;
case CALIBRATION_INPUT_0_1:{
// calibration code
analogReference(DEFAULT);
for (int k = 0; k < 10; k++){
input0Sum = 0;
for (int j = 0; j < calibrationRepeats; j++){
input0Sum += analogRead(input0Pin)*scaleFactor;
delay(7);
}
if (input0Sum > input0SumHigh){
input0SumHigh = input0Sum;
} else if (input0Sum < input0SumLow){
input0SumLow = input0Sum;
}
input0Sum10[k] = input0Sum ;
}
break;
}
case CALIBRATION_INPUT_1:
input1Value = analogRead(input1Pin)*scaleFactor;
// Update LCD to display input 1 value in real-time
break;
case CALIBRATION_INPUT_2:
input2Value = analogRead(input2Pin)*scaleFactor;
// Update LCD to display input 2 value in real-time
break;
case CALIBRATION_INPUT_3_1:
input31Value = analogRead(pressureSensorPin)*scaleFactor;
// Update LCD to display input 3 value in real-time
break;
case CALIBRATION_INPUT_3_2:
input32Value = digitalRead(valveStatePin);
// Update LCD to display input 3 value in real-time
break;
case CALIBRATION_INPUT_3_3:
// input3_3Value = analogRead(input3Pin);
// Update LCD to display input 3 value in real-time
break;
case CALIBRATION_COMPLETE:
break;
case CALIBRATION_IDLE:
break;
}
}