#define BLYNK_DEBUG
#define BLYNK_PRINT Serial // Comment this out to disable prints and save space
#include <SPI.h>
#include <Ethernet.h>
#include <BlynkSimpleEthernet.h>
#include <EEPROM.h>
#include <wdt101.h>
#include <inttypes.h>
#include <Wire.h>
#include <SimpleTimer.h>
//////////////////////////////////////
// Tire pressure : 1 bit = 0.01 PSI //
// Tank pressure : 1 bit = 0.01 PSI //
//////////////////////////////////////
//////// GLOBAL PARAMETERS /////
// Tire pressure control parameters:
const uint8_t TOLERANCE = 5; //[Tire pressure storage unit] set point tolerance
const uint16_t ALL_WITHIN_TOL_WAIT_TIME = 8000; //[ms]
const uint8_t TIME_BETW_MEAS = 50; //[ms]
const uint8_t NUM_OF_MEASUREMENTS_SHORT_FILTER = 6; //Number of measurements averaged
const uint8_t NUM_OF_MEASUREMENTS_LONG_FILTER = 50; //Number of measurements averaged
const uint16_t MAX_DEFLATION_TIME = 6000; //[ms]
const uint16_t MAX_INFLATION_TIME = 6000; //[ms]
const uint16_t WITHIN_TOL_SET_POINT_THRESHOLD = 10; //[raw set point bits]
const uint8_t STAND_BY_THRESHOLD = 10; //Stand by threshold
const uint8_t STAND_BY_MULTIPLAYER = 4; //Stand by multiplier
const uint16_t SETTLING_TIME = 100; //[ms] pressure settling time
const uint16_t VALVE_OPENING_TIME = 7; //[ms]
const float BITS_TO_PSIUNIT_MXP4250 = 2.5360; // 1 bit = 0,038425 psi
const int16_t FILTER_THRESHOLD = 100; // raw ADC value
const uint16_t FRONT_AXLE_OFFSET_ADJUST_TIME_LENGTH = 4000;
const uint16_t FRONT_AXLE_OFFSET_LOWER_POT_LIMIT = 50;
const uint16_t FRONT_AXLE_OFFSET_HIGER_POT_LIMIT = 950;
// Tank parameters:
const uint16_t TANKPRESSURE_BLINK_LIMIT = 3000; //[Tank pressure storage unit]
const uint16_t TANK_PRESS_BLINK_DELAY = 3000; //[ms]
const float BITS_TO_PSIUNIT_MXP5700 = 11.0135; // 1 bit = 0,110135 psi
const uint16_t OFFSET_MPX5700 = 35; // 0 - 1024, raw ADC unit
// Front panel parameters:
const uint16_t POT_NONLINEAR_THRES = 700; // range (0-1023)
const uint16_t FRONT_PANEL_TIME_THRES_PERIOD = 500;
uint16_t MAX_POT_COUNT = 1020; //(Not constant) Max output from POT ATH hĂ©r ĂŸarf aĂ° lĂĄta lesa Ășr EEPROM
uint16_t MIN_POT_COUNT = 0; //(Not constant) Min output from POT ATH hĂ©r ĂŸarf aĂ° lĂĄta lesa Ășr EEPROM
const uint8_t SETPOINT_MAXIMUM_PSI = 35;
const uint8_t PIN_GREEN_LED = V10;
const uint8_t PIN_ALL_INDI = 0;
//const uint8_t PIN_POT = A5;
// Control pins deceleration
const uint8_t PIN_VALVE0 = 5;
const uint8_t PIN_VALVE1 = 6;
const uint8_t PIN_VALVE2 = 7;
const uint8_t PIN_VALVE3 = 8;
const uint8_t PIN_VALVE4 = 9;
const uint8_t PIN_VALVE5 = 3;
const uint8_t PIN_PUMP = 1;
// Sensors
const uint8_t PIN_MPX4250 = A2;
const uint8_t PIN_MPX5700 = A1;
// EEPROM and control parameters
const uint8_t SINGLE_CHANNEL_DEFLATION_PARAM_ADDRESS = 0;
const uint8_t SINGLE_CHANNEL_INFLATION_PARAM_ADDRESS = 4;
const uint8_t FRONT_CHANNELS_DEFLATION_PARAM_ADDRESS = 8;
const uint8_t FRONT_CHANNELS_INFLATION_PARAM_ADDRESS = 12;
const uint8_t REAR_CHANNELS_DEFLATION_PARAM_ADDRESS = 16;
const uint8_t REAR_CHANNELS_INFLATION_PARAM_ADDRESS = 20;
const uint8_t ALL_CHANNELS_DEFLATION_PARAM_ADDRESS = 24;
const uint8_t ALL_CHANNELS_INFLATION_PARAM_ADDRESS = 28;
// Other constants:
const uint16_t SERIAL_BAUDRATE = 9600;
////////// GLOBAL VARIABLES /////
// Enum:
enum valveControlCommand {CLOSE_ALL, MEASURE, INFLATE, DEFLATE, CALIBRATION};
enum tireControlState {firstMeasurementOngoing, allWithinTolWaiting, firstMeasurementDone, inflationDeflationDone, secondMeasurementOngoing, secondMeasurementDone};
// Tire pressure control - global variables:
uint8_t activeTire = 0; //Four tires: 0-3
tireControlState tireState = allWithinTolWaiting; //Enum
uint16_t tireSensorOffset; //Raw ADC value
int16_t setPoint = 0; //[Tire pressure storage unit]
uint16_t currentPotRaw; //Current set point POT raw value
int16_t withinTolSetPoint; //[Tire pressure storage unit]
int16_t summedPressure; //Temp variable - used to accumulate measurements
boolean isAllWithinTol = false; //Are all channels within tolerance
uint8_t allWithinTolCounter = 0; //How many channels have been found in row within tolerance
uint8_t numOfMeasCounter = 0; //Current number of measurements taken
uint32_t TireTimeThres = 0; //Tire control time threshold
boolean isChBelow10PSI[4] = {true, true, true, true};
uint16_t firstMeasurementPressure = 0;
uint16_t secondMeasurementPressure = 0;
boolean isDeflating = false;
boolean isInflating = true;
uint16_t deflationTime = 0;
uint16_t inflationTime = 0;
boolean isSetPointChanged = true;
uint16_t numberOfMeasurementsInUse = NUM_OF_MEASUREMENTS_SHORT_FILTER;
int8_t frontAxleOffset = 0; // [psi*100] Range -4 to 4 psi ( -400 to 400)
int16_t maxPressureReading = 0;
int16_t minPressureReading = 1023;
uint8_t isShortFilterActive = true;
// Tank pressure control - global variables:
boolean isValve5Closed = true;
int16_t tankPress = 0; //[Tank pressure storage unit] Current tank pressure
uint32_t tankPressureLCDTimeThres = 0; //Tank pressure blink time threshold
uint32_t calibrationTankTimeThres = 0;
boolean tankBlink = false;
// EEPROM and control parameters - global variables:
uint16_t singleChannelDeflationParam = 11000;
uint16_t singleChannelInflationParam = 1200;
uint16_t frontChannelsDeflationParam = 11000;
uint16_t frontChannelsInflationParam = 1200;
uint16_t rearChannelsDeflationParam = 11000;
uint16_t rearChannelsInflationParam = 1200;
uint16_t allChannelsDeflationParam = 11000;
uint16_t allChannelsInflationParam = 1200;
uint32_t EEPROMTimeThres = 20000;
// Other - global variables:
uint32_t backgroundTasksTimeThres = 0; //Front panel time threshold
uint32_t blinkLEDTimeThres = 0; //Front panel LED blink time threshold
boolean isIndependentEnabled = true; //Independent channels enabled
uint16_t counter = 0; //Temp variable for performance test
uint16_t channe6 = 0;
uint16_t channe7 = 0;
uint16_t channe8 = 0;
uint16_t channe9 = 0;
boolean estadoBotao3;
boolean estadoBotao4;
boolean estadoBotao5;
boolean estadoBotao6;
boolean estadoBotao7;
boolean estadoBotao8;
boolean estadoBotao9;
SimpleTimer timer;
// Global objects:
WidgetLCD lcd(V1);
WidgetLCD lcd2(V2);
WidgetLED led3(V3);
WidgetLED led4(V4);
WidgetLED led5(V5);
WidgetLED led6(V6);
WidgetLED led7(V7);
WidgetLED led8(V8);
WidgetLED led9(V9);
// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "3295d2122335428a8a8877a04a64367b";
#define W5100_CS 10
#define SDCARD_CS 4
void setup()
{
Serial.begin(SERIAL_BAUDRATE);
pinMode(PIN_ALL_INDI, INPUT);
pinMode(PIN_GREEN_LED, OUTPUT);
pinMode(PIN_VALVE0, OUTPUT);
pinMode(PIN_VALVE1, OUTPUT);
pinMode(PIN_VALVE2, OUTPUT);
pinMode(PIN_VALVE3, OUTPUT);
pinMode(PIN_VALVE4, OUTPUT);
pinMode(PIN_VALVE5, OUTPUT);
pinMode(PIN_PUMP, OUTPUT);
pinMode(SDCARD_CS, OUTPUT);
digitalWrite(SDCARD_CS, HIGH); // Deselect the SD card
Blynk.begin(auth, IPAddress(192,168,10,2)); // For more options, see Boards_Ethernet/Arduino_Ethernet_Manual example
timer.setInterval(2000L, sendUptime);
tireSensorOffset = tireOffsetCalibration();
loadParamFromEEPROM();
}
BLYNK_CONNECTED()
{
Blynk.syncAll();
}
void loop()
{
if(backgroundTasksTimeThres < millis())
{
backgroundTasks();
}
if(TireTimeThres < millis())
{
tirePressureControl();
}
if(tankPressureLCDTimeThres < millis())
{
printTankPressureLCD();
}
Blynk.run();
timer.run();
bool isReady();
}
void sendUptime()
{
estadoBotao3 = digitalRead(1);
if (estadoBotao3 == HIGH ) {led3.on(); }else{led3.off();}
estadoBotao4 = digitalRead(3);
if (estadoBotao4 == HIGH ) {led4.on(); }else{led4.off();}
estadoBotao5 = digitalRead(5);
if (estadoBotao5 == HIGH ) {led5.on(); }else{led5.off();}
estadoBotao6 = digitalRead(6);
if (estadoBotao6 == HIGH ) {led6.on(); }else{led6.off();}
estadoBotao7 = digitalRead(7);
if (estadoBotao7 == HIGH ) {led7.on(); }else{led7.off();}
estadoBotao8 = digitalRead(8);
if (estadoBotao8 == HIGH ) {led8.on(); }else{led8.off();}
estadoBotao9 = digitalRead(9);
if (estadoBotao9 == HIGH ) {led9.on(); }else{led9.off();}
}
////////////// Support functions: ///////////////////////////
void backgroundTasks()
{
backgroundTasksTimeThres = millis() + FRONT_PANEL_TIME_THRES_PERIOD;
readTankPress();
updatingSetPoint();
updatingALLOrIndividualSwitch();
updatingFrontPanelLED();
// Method to capture set point changes in all-within-tolerance mode where the period is very slow
if (isAllWithinTol && (abs(setPoint - withinTolSetPoint) > WITHIN_TOL_SET_POINT_THRESHOLD))
{
TireTimeThres = 0; // Measure the next channel immediately
withinTolSetPoint = setPoint; // So that this is only caught once - not four times
}
// Tank functions - only read sensor when tankValve is closed
if (isValve5Closed == true)
{
readTankPress();
}
}
void tirePressureControl()
{
switch (tireState)
{
case firstMeasurementOngoing:
takeOneMoreMeasurement();
if (numOfMeasCounter >= numberOfMeasurementsInUse)
{
tireState = firstMeasurementDone;
}
break;
case firstMeasurementDone:
if (maxPressureReading - minPressureReading > FILTER_THRESHOLD && isShortFilterActive == true)
{
isShortFilterActive = false;
tireState = firstMeasurementOngoing;
numberOfMeasurementsInUse = NUM_OF_MEASUREMENTS_LONG_FILTER;
}
else
{
valveControl(CLOSE_ALL);
isShortFilterActive = true;
maxPressureReading = 0;
minPressureReading = 1023;
firstMeasurementPressure = calcAverage();
numberOfMeasurementsInUse = NUM_OF_MEASUREMENTS_SHORT_FILTER;
displayTirePress(firstMeasurementPressure);
decideWhatToDo(firstMeasurementPressure);
updateAllWithinTol();
}
break;
case allWithinTolWaiting:
valveControl(MEASURE);
TireTimeThres = millis() + SETTLING_TIME;
tireState = firstMeasurementOngoing;
break;
case inflationDeflationDone:
if (activeTire == 60)
{
tireState = firstMeasurementOngoing;
}
else
{
tireState = secondMeasurementOngoing;
}
valveControl(MEASURE);
TireTimeThres = millis() + SETTLING_TIME;
break;
case secondMeasurementOngoing:
takeOneMoreMeasurement();
if (numOfMeasCounter >= numberOfMeasurementsInUse)
{
tireState = secondMeasurementDone;
}
break;
case secondMeasurementDone:
if (maxPressureReading - minPressureReading > FILTER_THRESHOLD && isShortFilterActive == true)
{
isShortFilterActive = false;
tireState = secondMeasurementOngoing;
numberOfMeasurementsInUse = NUM_OF_MEASUREMENTS_LONG_FILTER;
}
else
{
isShortFilterActive = true;
maxPressureReading = 0;
minPressureReading = 1023;
secondMeasurementPressure = calcAverage();
numberOfMeasurementsInUse = NUM_OF_MEASUREMENTS_SHORT_FILTER;
displayTirePress(secondMeasurementPressure);
changeToNextChannel();
updatingControlParameters();
valveControl(MEASURE);
TireTimeThres = millis() + SETTLING_TIME;
tireState = firstMeasurementOngoing;
}
break;
}
}
//Read tankPress from MPX5700 sensor
void readTankPress()
{
tankPress = (float)(analogRead(PIN_MPX5700) - OFFSET_MPX5700) * BITS_TO_PSIUNIT_MXP5700;
}
void changeToNextChannel()
{
// 0 - 3 = independent channels, 4 = front (0-1 ch), 5 rear (2-3 ch), 6 all channels
if (isIndependentEnabled == true)
{
activeTire = (activeTire + 1) % 4;
}
else if (frontAxleOffset == 0)
{
activeTire = 6;
Serial.print(F("activeTire 6: "));
Serial.println(activeTire, 1);
}
else
{
if (activeTire == 5)
{
activeTire = 4;
Serial.print(F("activeTire 4: "));
Serial.println(activeTire, 1);
}
else
{
activeTire = 5;
Serial.print(F("activeTire 5: "));
Serial.println(activeTire, 1);
}
}
}
// Print tankPressure to LCD
void printTankPressureLCD()
{
tankPressureLCDTimeThres = millis() + TANK_PRESS_BLINK_DELAY;
if(tankPress > TANKPRESSURE_BLINK_LIMIT || tankBlink == false)
{
if(tankPress < 995)
{
lcd.print(11, 1, " ");
}
else if(tankPress < 9995)
{
lcd.print(11, 1, " ");
}
lcd.print(0, 1, "PSI Ă TANK >");
lcd.print(11, 1, (tankPress + 5)/100); // 5 is so the rounding will be correct and 100 is because of the way the pressure is stored
//Serial.print(F("TankPressure 3: "));
//Serial.println((tankPress + 5), 1);
tankBlink = true;
}
else
{
tankBlink = false;
lcd.print(11, 1, " ");
}
}
//Gets value from slider in Blynk app to choose SetPot
BLYNK_WRITE(V11) // Blynk press SET slider, where V11 is MY virtual pin (copy/paste)
{
int pinValue = param.asInt();
setPoint = constrain(pinValue, 200, 3500); //this is where you put your limits of psi, multiplied by 100 for increased resolution
delay(50); //you can omit this one - was needed in my specific case
String setPoint_str = String((float)setPoint/100, 1); //Function to display a number with one decimal and divide in order to get the correct psi
lcd.print( 0,0, "VALIĂ PSI >"); //Text for the selected psi
lcd.print(11,0, setPoint_str); //here you can send your setPoint to vLCD
if(setPoint < 995)
{
lcd.print(14,0, " "); // This is for clare of decimal point on screen
}
}
void updatingSetPoint()
{
uint16_t newPotRaw = setPoint;
if(abs(newPotRaw - currentPotRaw) > 10 ) // POT hysteresis
{
uint16_t newSetPoint = potToPSI(newPotRaw);
if( newSetPoint != setPoint)
{
setPoint = newSetPoint;
currentPotRaw = newPotRaw;
isSetPointChanged = true;
}
}
}
uint16_t potToPSI(uint16_t potRaw)
{
uint16_t output = 0;
if (potRaw < POT_NONLINEAR_THRES)
{
output = map(potRaw, MIN_POT_COUNT, POT_NONLINEAR_THRES - 1, 0, 499);
}
else
{
output = map(potRaw, POT_NONLINEAR_THRES, MAX_POT_COUNT, 500, SETPOINT_MAXIMUM_PSI * 100);
}
// Round of numbers higher than 500 (5 PSI)
if (output > 500)
{
output = (output / (int)100) * (int)100;
}
else
{
output = (output / (int)50) * (int)50;
}
if (output < 50)
{
output = 25;
}
return output;
}
void updatingALLOrIndividualSwitch()
{
boolean allIndiSwitchEnabled = digitalRead(PIN_ALL_INDI);
if (allIndiSwitchEnabled && !isIndependentEnabled)
{
activeTire = 0;
isIndependentEnabled = true;
TireTimeThres = 0;
allWithinTolCounter = 0;
isAllWithinTol = 0;
valveControl(CLOSE_ALL);
Serial.print(F("satt: "));
Serial.println(PIN_ALL_INDI, 1);
}
else if (!allIndiSwitchEnabled && isIndependentEnabled)
{
activeTire = 6;
isIndependentEnabled = false;
TireTimeThres = 0;
allWithinTolCounter = 0;
isAllWithinTol = 0;
valveControl(CLOSE_ALL);
Serial.print(F("falst: "));
Serial.println(PIN_ALL_INDI,1);
}
delay(500);
}
void updatingFrontPanelLED()
{
if (isAllWithinTol)
{
digitalWrite(PIN_GREEN_LED, 1);
}
else
{
digitalWrite(PIN_GREEN_LED, 0);
}
}
void takeOneMoreMeasurement()
{
uint16_t temp = analogRead(PIN_MPX4250) - tireSensorOffset;
if (temp > maxPressureReading)
{
maxPressureReading = temp;
}
if (temp < minPressureReading)
{
minPressureReading = temp;
}
summedPressure = summedPressure + temp;
numOfMeasCounter += 1;
TireTimeThres = millis() + TIME_BETW_MEAS;
}
uint16_t calcAverage()
{
numOfMeasCounter = 0;
int16_t currentPressure = (float)(summedPressure / numberOfMeasurementsInUse) * BITS_TO_PSIUNIT_MXP4250;
if ( currentPressure < 0 )
{
currentPressure = 0;
}
summedPressure = 0;
return currentPressure;
}
void displayTirePress(uint16_t currentPressure)
{
float printOutPress = (float)currentPressure/(float)100;
if(currentPressure > 37000) // This is to eliminate "negative" pressure
{
currentPressure = 0;
}
uint8_t isCurrentPressBelow10psi = currentPressure < 995;
uint8_t startChannel = 0;
uint8_t endChannel = 0;
switch (activeTire)
{
case 0:
channe6 = currentPressure;
startChannel = activeTire;
endChannel = activeTire;
isChBelow10PSI[activeTire] = isCurrentPressBelow10psi;
break;
case 1:
channe7 = currentPressure;
startChannel = activeTire;
endChannel = activeTire;
isChBelow10PSI[activeTire] = isCurrentPressBelow10psi;
break;
case 2:
channe8 = currentPressure;
startChannel = activeTire;
endChannel = activeTire;
isChBelow10PSI[activeTire] = isCurrentPressBelow10psi;
break;
case 3:
channe9 = currentPressure;
startChannel = activeTire;
endChannel = activeTire;
isChBelow10PSI[activeTire] = isCurrentPressBelow10psi;
break;
case 4:
channe6 = currentPressure;
channe7 = currentPressure;
startChannel = 0;
endChannel = 1;
isChBelow10PSI[0] = isCurrentPressBelow10psi;
isChBelow10PSI[1] = isCurrentPressBelow10psi;
break;
case 5:
channe8 = currentPressure;
channe9 = currentPressure;
startChannel = 2;
endChannel = 3;
isChBelow10PSI[2] = isCurrentPressBelow10psi;
isChBelow10PSI[3] = isCurrentPressBelow10psi;
break;
case 6:
channe6 = currentPressure;
channe7 = currentPressure;
channe8 = currentPressure;
channe9 = currentPressure;
startChannel = 0;
endChannel = 3;
isChBelow10PSI[0] = isCurrentPressBelow10psi;
isChBelow10PSI[1] = isCurrentPressBelow10psi;
isChBelow10PSI[2] = isCurrentPressBelow10psi;
isChBelow10PSI[3] = isCurrentPressBelow10psi;
break;
}
for(uint8_t i = startChannel; i < endChannel+1; i++)
{
String printOutPress_str = String((float)printOutPress, 1); //Function to display a number with one decimal
lcd2.print(7, 0, "<>"); //symbols lcd
lcd2.print(7, 1, "<>"); //symbols lcd
lcd2.print(3, 0, printOutPress_str); //Printed on lcd air pressure for tires
lcd2.print(0, 0, "VF"); //Which tire is measured in left front
lcd2.print(3, 1, printOutPress_str); //Printed on lcd air pressure for tires
lcd2.print(0, 1, "VA"); //Which tire is measured in left rear
lcd2.print(10, 0, printOutPress_str); //Printed on lcd air pressure for tires
lcd2.print(14, 0, "HF"); //Which tire is measured in right front
lcd2.print(10, 1, printOutPress_str); //Printed on lcd air pressure for tires
lcd2.print(14, 1, "HA"); //Which tire is measured in right back
}
}
void updateAllWithinTol()
{
uint8_t numberOfChannelsInUse = 0;
switch (activeTire)
{
case 0:
case 1:
case 2:
case 3:
numberOfChannelsInUse = 3;
break;
case 4:
case 5:
numberOfChannelsInUse = 2;
break;
case 6:
numberOfChannelsInUse = 1;
break;
}
if (allWithinTolCounter >= numberOfChannelsInUse && !isAllWithinTol)
{
isAllWithinTol = true;
withinTolSetPoint = setPoint;
isSetPointChanged = false;
}
else if (allWithinTolCounter < numberOfChannelsInUse)
{
isAllWithinTol = false;
}
}
uint16_t calculateDeflationTime(uint16_t currentPressure)
{
uint16_t deflationParamInUse = 0;
switch (activeTire)
{
case 0:
case 1:
case 2:
case 3:
deflationParamInUse = singleChannelDeflationParam;
break;
case 4:
deflationParamInUse = frontChannelsDeflationParam;
break;
case 5:
deflationParamInUse = rearChannelsDeflationParam;
break;
case 6:
deflationParamInUse = allChannelsDeflationParam;
break;
}
uint16_t timeMilliSec = ((deflationParamInUse * 10) / log( (float)currentPressure / (float)setPoint )) + VALVE_OPENING_TIME;
if (timeMilliSec > MAX_DEFLATION_TIME)
{
timeMilliSec = MAX_DEFLATION_TIME;
}
return timeMilliSec;
}
uint16_t calculateInflationTimeMS(uint16_t currentPressure)
{
uint16_t inflationParamInUse = 0;
switch (activeTire)
{
case 0:
case 1:
case 2:
case 3:
inflationParamInUse = singleChannelInflationParam;
break;
case 4:
inflationParamInUse = frontChannelsInflationParam;
break;
case 5:
inflationParamInUse = rearChannelsInflationParam;
break;
case 6:
inflationParamInUse = allChannelsInflationParam;
break;
}
uint16_t timeMilliSec = ((float)( setPoint - currentPressure ) * ( inflationParamInUse / 100 ) ) + VALVE_OPENING_TIME;
if (timeMilliSec > MAX_INFLATION_TIME)
{
timeMilliSec = MAX_INFLATION_TIME;
}
return timeMilliSec;
}
void decideWhatToDo(int16_t currentPressure)
{
int16_t difference = currentPressure - setPoint;
if (activeTire == 0 || activeTire == 1 || activeTire == 4)
{
difference = difference - frontAxleOffset;
}
if (abs(difference) > TOLERANCE) // Last measurement not within tolerance
{
allWithinTolCounter = 0;
if (difference > 0)
{
valveControl(DEFLATE);
deflationTime = calculateDeflationTime(currentPressure);
TireTimeThres = millis() + deflationTime;
}
else if (1) //tankPress > 0) // inflation only performed if tank press > 30 psi
{
valveControl(INFLATE);
inflationTime = calculateInflationTimeMS(currentPressure);
TireTimeThres = millis() + inflationTime;
}
tireState = inflationDeflationDone;
}
else // Last measurement within tolerance
{
allWithinTolCounter += 1;
changeToNextChannel();
if (isAllWithinTol && allWithinTolCounter > STAND_BY_THRESHOLD)
{
closeAllValves();
TireTimeThres = millis() + (STAND_BY_MULTIPLAYER * ALL_WITHIN_TOL_WAIT_TIME);
tireState = allWithinTolWaiting;
}
else if (isAllWithinTol)
{
closeAllValves();
if (activeTire == 6)
{
openActiveTireValve();
}
TireTimeThres = millis() + ALL_WITHIN_TOL_WAIT_TIME;
tireState = allWithinTolWaiting;
}
else
{
valveControl(MEASURE);
TireTimeThres = millis() + SETTLING_TIME;
tireState = firstMeasurementOngoing;
}
}
}
void openActiveTireValve()
{
switch (activeTire)
{
case 0:
digitalWrite(PIN_VALVE1, HIGH);
break;
case 1:
digitalWrite(PIN_VALVE2, HIGH);
break;
case 2:
digitalWrite(PIN_VALVE3, HIGH);
break;
case 3:
digitalWrite(PIN_VALVE4, HIGH);
break;
case 4:
digitalWrite(PIN_VALVE1, HIGH);
digitalWrite(PIN_VALVE2, HIGH);
break;
case 5:
digitalWrite(PIN_VALVE3, HIGH);
digitalWrite(PIN_VALVE4, HIGH);
break;
case 6:
digitalWrite(PIN_VALVE1, HIGH);
digitalWrite(PIN_VALVE2, HIGH);
digitalWrite(PIN_VALVE3, HIGH);
digitalWrite(PIN_VALVE4, HIGH);
break;
}
}
void closeAllValves()
{
digitalWrite(PIN_VALVE0, LOW);
digitalWrite(PIN_VALVE1, LOW);
digitalWrite(PIN_VALVE2, LOW);
digitalWrite(PIN_VALVE3, LOW);
digitalWrite(PIN_VALVE4, LOW);
digitalWrite(PIN_VALVE5, LOW);
}
void valveControl(int command)
{
closeAllValves();
isValve5Closed = true;
switch (command)
{
case CLOSE_ALL:
// Empty on purpose
break;
case MEASURE:
openActiveTireValve();
break;
case INFLATE:
isInflating = true;
openActiveTireValve();
digitalWrite(PIN_VALVE5, HIGH);
isValve5Closed = false;
break;
case DEFLATE:
isDeflating = true;
openActiveTireValve();
digitalWrite(PIN_VALVE0, HIGH);
break;
case CALIBRATION:
digitalWrite(PIN_VALVE0, HIGH);
break;
}
}
uint16_t tireOffsetCalibration()
{
valveControl(CALIBRATION);
//delay(250);
uint16_t temp = 0;
for (int8_t i = 0; i < NUM_OF_MEASUREMENTS_SHORT_FILTER; i = i + 1)
{
temp = temp + analogRead(PIN_MPX4250);
delay(TIME_BETW_MEAS);
}
uint16_t tireSensorOffset = (temp / NUM_OF_MEASUREMENTS_SHORT_FILTER);
valveControl(CLOSE_ALL);
//delay(250);
return tireSensorOffset;
}
void writeParamToEEPROM()
{
// Unfinished function
}
void loadParamFromEEPROM()
{
singleChannelDeflationParam = EEPROM.read(SINGLE_CHANNEL_DEFLATION_PARAM_ADDRESS);
singleChannelInflationParam = EEPROM.read(SINGLE_CHANNEL_INFLATION_PARAM_ADDRESS);
frontChannelsDeflationParam = EEPROM.read(FRONT_CHANNELS_DEFLATION_PARAM_ADDRESS);
frontChannelsInflationParam = EEPROM.read(FRONT_CHANNELS_DEFLATION_PARAM_ADDRESS);
rearChannelsDeflationParam = EEPROM.read(REAR_CHANNELS_DEFLATION_PARAM_ADDRESS);
rearChannelsInflationParam = EEPROM.read(REAR_CHANNELS_DEFLATION_PARAM_ADDRESS);
allChannelsDeflationParam = EEPROM.read(ALL_CHANNELS_DEFLATION_PARAM_ADDRESS);
allChannelsInflationParam = EEPROM.read(ALL_CHANNELS_DEFLATION_PARAM_ADDRESS);
}
void updatingControlParameters()
{
if (isDeflating && isInflating)
{
// Error: should not happen
}
else if (isDeflating && deflationTime > 0 && (firstMeasurementPressure - secondMeasurementPressure) > 0)
{
uint16_t newDeflationParam = deflationTime / log( (float)firstMeasurementPressure / (float)secondMeasurementPressure) / 10;
switch (activeTire)
{
case 0:
case 1:
case 2:
case 3:
singleChannelDeflationParam = newDeflationParam;
break;
case 4:
frontChannelsDeflationParam = newDeflationParam;
break;
case 5:
rearChannelsDeflationParam = newDeflationParam;
break;
case 6:
allChannelsDeflationParam = newDeflationParam;
break;
}
}
else if (isInflating && inflationTime > 0 && (secondMeasurementPressure > firstMeasurementPressure))
{
uint16_t newInflationParam = inflationTime / (float)(secondMeasurementPressure - firstMeasurementPressure) * 100;
switch (activeTire)
{
case 0:
case 1:
case 2:
case 3:
singleChannelInflationParam = newInflationParam;
break;
case 4:
frontChannelsInflationParam = newInflationParam;
break;
case 5:
rearChannelsInflationParam = newInflationParam;
break;
case 6:
allChannelsInflationParam = newInflationParam;
break;
}
}
isDeflating = false;
isInflating = false;
if ( EEPROMTimeThres < millis() )
{
EEPROMTimeThres = millis() + 5000;
writeParamToEEPROM();
}
}
int16_t updateFrontAxleOffset()
{
closeAllValves();
int16_t offset = 0;
for (uint8_t i = 0; i < 20; i++)
{
offset = map(analogRead(setPoint),0,1023,-8,8) * 50; // range from -4 to 4 psi with 0,5 psi resolution
if(offset >= 0)
{
lcd.print(11, 0, " ");
}
String offset_str = String((float)offset/100, 1);
lcd.print(11, 0, offset_str);
delay(250);
}
return offset;
}
OK, try if with this one the flood occurs.
A few quick notes:
- probably the flood occurred in
displayTirePress()
- You shouldnât have deleted the LCD_X[] and LCD_Y[] arrays. What you have done with multiple
lcd2.print(..)
withinfor
loop was not correct (try to figure out why ) - why enabled the
updatingSetPoint()
? this one was for manual pot input. Disabled here. - you have included wdt101 (a watchdog timer) but no wdt handling in code. Either disable it (not include the wdt101) or complete basing on provided examples (at github for example)
#define BLYNK_DEBUG
#define BLYNK_PRINT Serial // Comment this out to disable prints and save space
#include <SPI.h>
#include <Ethernet.h>
#include <BlynkSimpleEthernet.h>
#include <EEPROM.h>
#include <wdt101.h>
#include <inttypes.h>
#include <Wire.h>
#include <SimpleTimer.h>
//////////////////////////////////////
// Tire pressure : 1 bit = 0.01 PSI //
// Tank pressure : 1 bit = 0.01 PSI //
//////////////////////////////////////
//////// GLOBAL PARAMETERS /////
// Tire pressure control parameters:
const uint8_t TOLERANCE = 5; //[Tire pressure storage unit] set point tolerance
const uint16_t ALL_WITHIN_TOL_WAIT_TIME = 8000; //[ms]
const uint8_t TIME_BETW_MEAS = 50; //[ms]
const uint8_t NUM_OF_MEASUREMENTS_SHORT_FILTER = 6; //Number of measurements averaged
const uint8_t NUM_OF_MEASUREMENTS_LONG_FILTER = 50; //Number of measurements averaged
const uint16_t MAX_DEFLATION_TIME = 6000; //[ms]
const uint16_t MAX_INFLATION_TIME = 6000; //[ms]
const uint16_t WITHIN_TOL_SET_POINT_THRESHOLD = 10; //[raw set point bits]
const uint8_t STAND_BY_THRESHOLD = 10; //Stand by threshold
const uint8_t STAND_BY_MULTIPLAYER = 4; //Stand by multiplier
const uint16_t SETTLING_TIME = 100; //[ms] pressure settling time
const uint16_t VALVE_OPENING_TIME = 7; //[ms]
const float BITS_TO_PSIUNIT_MXP4250 = 2.5360; // 1 bit = 0,038425 psi
const int16_t FILTER_THRESHOLD = 100; // raw ADC value
const uint16_t FRONT_AXLE_OFFSET_ADJUST_TIME_LENGTH = 4000;
const uint16_t FRONT_AXLE_OFFSET_LOWER_POT_LIMIT = 50;
const uint16_t FRONT_AXLE_OFFSET_HIGER_POT_LIMIT = 950;
// Tank parameters:
const uint16_t TANKPRESSURE_BLINK_LIMIT = 3000; //[Tank pressure storage unit]
const uint16_t TANK_PRESS_BLINK_DELAY = 3000; //[ms]
const float BITS_TO_PSIUNIT_MXP5700 = 11.0135; // 1 bit = 0,110135 psi
const uint16_t OFFSET_MPX5700 = 35; // 0 - 1024, raw ADC unit
// Front panel parameters:
const uint16_t POT_NONLINEAR_THRES = 700; // range (0-1023)
const uint16_t FRONT_PANEL_TIME_THRES_PERIOD = 500;
uint16_t MAX_POT_COUNT = 1020; //(Not constant) Max output from POT ATH hĂ©r ĂŸarf aĂ° lĂĄta lesa Ășr EEPROM
uint16_t MIN_POT_COUNT = 0; //(Not constant) Min output from POT ATH hĂ©r ĂŸarf aĂ° lĂĄta lesa Ășr EEPROM
const int LCD_X[] = {3, 10, 3, 10}; // The position coordinates of the tire pressure on the screen
const int LCD_Y[] = {0, 0, 1, 1};
const uint8_t SETPOINT_MAXIMUM_PSI = 35;
const uint8_t PIN_GREEN_LED = V10;
const uint8_t PIN_ALL_INDI = 0;
//const uint8_t PIN_POT = A5;
// Control pins deceleration
const uint8_t PIN_VALVE0 = 5;
const uint8_t PIN_VALVE1 = 6;
const uint8_t PIN_VALVE2 = 7;
const uint8_t PIN_VALVE3 = 8;
const uint8_t PIN_VALVE4 = 9;
const uint8_t PIN_VALVE5 = 3;
const uint8_t PIN_PUMP = 1;
// Sensors
const uint8_t PIN_MPX4250 = A2;
const uint8_t PIN_MPX5700 = A1;
// EEPROM and control parameters
const uint8_t SINGLE_CHANNEL_DEFLATION_PARAM_ADDRESS = 0;
const uint8_t SINGLE_CHANNEL_INFLATION_PARAM_ADDRESS = 4;
const uint8_t FRONT_CHANNELS_DEFLATION_PARAM_ADDRESS = 8;
const uint8_t FRONT_CHANNELS_INFLATION_PARAM_ADDRESS = 12;
const uint8_t REAR_CHANNELS_DEFLATION_PARAM_ADDRESS = 16;
const uint8_t REAR_CHANNELS_INFLATION_PARAM_ADDRESS = 20;
const uint8_t ALL_CHANNELS_DEFLATION_PARAM_ADDRESS = 24;
const uint8_t ALL_CHANNELS_INFLATION_PARAM_ADDRESS = 28;
// Other constants:
const uint16_t SERIAL_BAUDRATE = 9600;
////////// GLOBAL VARIABLES /////
// Enum:
enum valveControlCommand {CLOSE_ALL, MEASURE, INFLATE, DEFLATE, CALIBRATION};
enum tireControlState {firstMeasurementOngoing, allWithinTolWaiting, firstMeasurementDone, inflationDeflationDone, secondMeasurementOngoing, secondMeasurementDone};
// Tire pressure control - global variables:
uint8_t activeTire = 0; //Four tires: 0-3
tireControlState tireState = allWithinTolWaiting; //Enum
uint16_t tireSensorOffset; //Raw ADC value
int16_t setPoint = 0; //[Tire pressure storage unit]
uint16_t currentPotRaw; //Current set point POT raw value
int16_t withinTolSetPoint; //[Tire pressure storage unit]
int16_t summedPressure; //Temp variable - used to accumulate measurements
boolean isAllWithinTol = false; //Are all channels within tolerance
uint8_t allWithinTolCounter = 0; //How many channels have been found in row within tolerance
uint8_t numOfMeasCounter = 0; //Current number of measurements taken
uint32_t TireTimeThres = 0; //Tire control time threshold
boolean isChBelow10PSI[4] = {true, true, true, true};
uint16_t firstMeasurementPressure = 0;
uint16_t secondMeasurementPressure = 0;
boolean isDeflating = false;
boolean isInflating = true;
uint16_t deflationTime = 0;
uint16_t inflationTime = 0;
boolean isSetPointChanged = true;
uint16_t numberOfMeasurementsInUse = NUM_OF_MEASUREMENTS_SHORT_FILTER;
int8_t frontAxleOffset = 0; // [psi*100] Range -4 to 4 psi ( -400 to 400)
int16_t maxPressureReading = 0;
int16_t minPressureReading = 1023;
uint8_t isShortFilterActive = true;
// Tank pressure control - global variables:
boolean isValve5Closed = true;
int16_t tankPress = 0; //[Tank pressure storage unit] Current tank pressure
uint32_t tankPressureLCDTimeThres = 0; //Tank pressure blink time threshold
uint32_t calibrationTankTimeThres = 0;
boolean tankBlink = false;
// EEPROM and control parameters - global variables:
uint16_t singleChannelDeflationParam = 11000;
uint16_t singleChannelInflationParam = 1200;
uint16_t frontChannelsDeflationParam = 11000;
uint16_t frontChannelsInflationParam = 1200;
uint16_t rearChannelsDeflationParam = 11000;
uint16_t rearChannelsInflationParam = 1200;
uint16_t allChannelsDeflationParam = 11000;
uint16_t allChannelsInflationParam = 1200;
uint32_t EEPROMTimeThres = 20000;
// Other - global variables:
uint32_t backgroundTasksTimeThres = 0; //Front panel time threshold
uint32_t blinkLEDTimeThres = 0; //Front panel LED blink time threshold
boolean isIndependentEnabled = true; //Independent channels enabled
uint16_t counter = 0; //Temp variable for performance test
uint16_t channe6 = 0;
uint16_t channe7 = 0;
uint16_t channe8 = 0;
uint16_t channe9 = 0;
boolean estadoBotao3;
boolean estadoBotao4;
boolean estadoBotao5;
boolean estadoBotao6;
boolean estadoBotao7;
boolean estadoBotao8;
boolean estadoBotao9;
SimpleTimer timer;
// Global objects:
WidgetLCD lcd(V1);
WidgetLCD lcd2(V2);
WidgetLED led3(V3);
WidgetLED led4(V4);
WidgetLED led5(V5);
WidgetLED led6(V6);
WidgetLED led7(V7);
WidgetLED led8(V8);
WidgetLED led9(V9);
// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "3295d2122335428a8a8877a04a64367b";
#define W5100_CS 10
#define SDCARD_CS 4
void setup()
{
Serial.begin(SERIAL_BAUDRATE);
pinMode(PIN_ALL_INDI, INPUT);
pinMode(PIN_GREEN_LED, OUTPUT);
pinMode(PIN_VALVE0, OUTPUT);
pinMode(PIN_VALVE1, OUTPUT);
pinMode(PIN_VALVE2, OUTPUT);
pinMode(PIN_VALVE3, OUTPUT);
pinMode(PIN_VALVE4, OUTPUT);
pinMode(PIN_VALVE5, OUTPUT);
pinMode(PIN_PUMP, OUTPUT);
pinMode(SDCARD_CS, OUTPUT);
digitalWrite(SDCARD_CS, HIGH); // Deselect the SD card
Blynk.begin(auth, IPAddress(192,168,10,2)); // For more options, see Boards_Ethernet/Arduino_Ethernet_Manual example
timer.setInterval(2000L, sendUptime);
tireSensorOffset = tireOffsetCalibration();
loadParamFromEEPROM();
}
BLYNK_CONNECTED()
{
Blynk.syncAll();
}
void loop()
{
if(backgroundTasksTimeThres < millis())
{
backgroundTasks();
}
if(TireTimeThres < millis())
{
tirePressureControl();
}
if(tankPressureLCDTimeThres < millis())
{
printTankPressureLCD();
}
Blynk.run();
timer.run();
bool isReady();
}
void sendUptime()
{
estadoBotao3 = digitalRead(1);
if (estadoBotao3 == HIGH ) {led3.on(); }else{led3.off();}
estadoBotao4 = digitalRead(3);
if (estadoBotao4 == HIGH ) {led4.on(); }else{led4.off();}
estadoBotao5 = digitalRead(5);
if (estadoBotao5 == HIGH ) {led5.on(); }else{led5.off();}
estadoBotao6 = digitalRead(6);
if (estadoBotao6 == HIGH ) {led6.on(); }else{led6.off();}
estadoBotao7 = digitalRead(7);
if (estadoBotao7 == HIGH ) {led7.on(); }else{led7.off();}
estadoBotao8 = digitalRead(8);
if (estadoBotao8 == HIGH ) {led8.on(); }else{led8.off();}
estadoBotao9 = digitalRead(9);
if (estadoBotao9 == HIGH ) {led9.on(); }else{led9.off();}
}
////////////// Support functions: ///////////////////////////
void backgroundTasks()
{
backgroundTasksTimeThres = millis() + FRONT_PANEL_TIME_THRES_PERIOD;
readTankPress();
//updatingSetPoint();
updatingALLOrIndividualSwitch();
updatingFrontPanelLED();
// Method to capture set point changes in all-within-tolerance mode where the period is very slow
if (isAllWithinTol && (abs(setPoint - withinTolSetPoint) > WITHIN_TOL_SET_POINT_THRESHOLD))
{
TireTimeThres = 0; // Measure the next channel immediately
withinTolSetPoint = setPoint; // So that this is only caught once - not four times
}
// Tank functions - only read sensor when tankValve is closed
if (isValve5Closed == true)
{
readTankPress();
}
}
void tirePressureControl()
{
switch (tireState)
{
case firstMeasurementOngoing:
takeOneMoreMeasurement();
if (numOfMeasCounter >= numberOfMeasurementsInUse)
{
tireState = firstMeasurementDone;
}
break;
case firstMeasurementDone:
if (maxPressureReading - minPressureReading > FILTER_THRESHOLD && isShortFilterActive == true)
{
isShortFilterActive = false;
tireState = firstMeasurementOngoing;
numberOfMeasurementsInUse = NUM_OF_MEASUREMENTS_LONG_FILTER;
}
else
{
valveControl(CLOSE_ALL);
isShortFilterActive = true;
maxPressureReading = 0;
minPressureReading = 1023;
firstMeasurementPressure = calcAverage();
numberOfMeasurementsInUse = NUM_OF_MEASUREMENTS_SHORT_FILTER;
displayTirePress(firstMeasurementPressure);
decideWhatToDo(firstMeasurementPressure);
updateAllWithinTol();
}
break;
case allWithinTolWaiting:
valveControl(MEASURE);
TireTimeThres = millis() + SETTLING_TIME;
tireState = firstMeasurementOngoing;
break;
case inflationDeflationDone:
if (activeTire == 60)
{
tireState = firstMeasurementOngoing;
}
else
{
tireState = secondMeasurementOngoing;
}
valveControl(MEASURE);
TireTimeThres = millis() + SETTLING_TIME;
break;
case secondMeasurementOngoing:
takeOneMoreMeasurement();
if (numOfMeasCounter >= numberOfMeasurementsInUse)
{
tireState = secondMeasurementDone;
}
break;
case secondMeasurementDone:
if (maxPressureReading - minPressureReading > FILTER_THRESHOLD && isShortFilterActive == true)
{
isShortFilterActive = false;
tireState = secondMeasurementOngoing;
numberOfMeasurementsInUse = NUM_OF_MEASUREMENTS_LONG_FILTER;
}
else
{
isShortFilterActive = true;
maxPressureReading = 0;
minPressureReading = 1023;
secondMeasurementPressure = calcAverage();
numberOfMeasurementsInUse = NUM_OF_MEASUREMENTS_SHORT_FILTER;
displayTirePress(secondMeasurementPressure);
changeToNextChannel();
updatingControlParameters();
valveControl(MEASURE);
TireTimeThres = millis() + SETTLING_TIME;
tireState = firstMeasurementOngoing;
}
break;
}
}
//Read tankPress from MPX5700 sensor
void readTankPress()
{
tankPress = (float)(analogRead(PIN_MPX5700) - OFFSET_MPX5700) * BITS_TO_PSIUNIT_MXP5700;
}
void changeToNextChannel()
{
// 0 - 3 = independent channels, 4 = front (0-1 ch), 5 rear (2-3 ch), 6 all channels
if (isIndependentEnabled == true)
{
activeTire = (activeTire + 1) % 4;
}
else if (frontAxleOffset == 0)
{
activeTire = 6;
Serial.print(F("activeTire 6: "));
Serial.println(activeTire, 1);
}
else
{
if (activeTire == 5)
{
activeTire = 4;
Serial.print(F("activeTire 4: "));
Serial.println(activeTire, 1);
}
else
{
activeTire = 5;
Serial.print(F("activeTire 5: "));
Serial.println(activeTire, 1);
}
}
}
// Print tankPressure to LCD
void printTankPressureLCD()
{
tankPressureLCDTimeThres = millis() + TANK_PRESS_BLINK_DELAY;
if(tankPress > TANKPRESSURE_BLINK_LIMIT || tankBlink == false)
{
if(tankPress < 995)
{
lcd.print(11, 1, " ");
}
else if(tankPress < 9995)
{
lcd.print(11, 1, " ");
}
lcd.print(0, 1, "PSI Ă TANK >");
lcd.print(11, 1, (tankPress + 5)/100); // 5 is so the rounding will be correct and 100 is because of the way the pressure is stored
//Serial.print(F("TankPressure 3: "));
//Serial.println((tankPress + 5), 1);
tankBlink = true;
}
else
{
tankBlink = false;
lcd.print(11, 1, " ");
}
}
//Gets value from slider in Blynk app to choose SetPot
BLYNK_WRITE(V11) // Blynk press SET slider, where V11 is MY virtual pin (copy/paste)
{
int pinValue = param.asInt();
setPoint = constrain(pinValue, 200, 3500); //this is where you put your limits of psi, multiplied by 100 for increased resolution
delay(50); //you can omit this one - was needed in my specific case
String setPoint_str = String((float)setPoint/100, 1); //Function to display a number with one decimal and divide in order to get the correct psi
lcd.print( 0,0, "VALIĂ PSI >"); //Text for the selected psi
lcd.print(11,0, setPoint_str); //here you can send your setPoint to vLCD
if(setPoint < 995)
{
lcd.print(14,0, " "); // This is for clare of decimal point on screen
}
isSetPointChanged = true;
}
/*
void updatingSetPoint()
{
uint16_t newPotRaw = setPoint;
if(abs(newPotRaw - currentPotRaw) > 10 ) // POT hysteresis
{
uint16_t newSetPoint = potToPSI(newPotRaw);
if( newSetPoint != setPoint)
{
setPoint = newSetPoint;
currentPotRaw = newPotRaw;
isSetPointChanged = true;
}
}
}
uint16_t potToPSI(uint16_t potRaw)
{
uint16_t output = 0;
if (potRaw < POT_NONLINEAR_THRES)
{
output = map(potRaw, MIN_POT_COUNT, POT_NONLINEAR_THRES - 1, 0, 499);
}
else
{
output = map(potRaw, POT_NONLINEAR_THRES, MAX_POT_COUNT, 500, SETPOINT_MAXIMUM_PSI * 100);
}
// Round of numbers higher than 500 (5 PSI)
if (output > 500)
{
output = (output / (int)100) * (int)100;
}
else
{
output = (output / (int)50) * (int)50;
}
if (output < 50)
{
output = 25;
}
return output;
}
*/
void updatingALLOrIndividualSwitch()
{
boolean allIndiSwitchEnabled = digitalRead(PIN_ALL_INDI);
if (allIndiSwitchEnabled && !isIndependentEnabled)
{
activeTire = 0;
isIndependentEnabled = true;
TireTimeThres = 0;
allWithinTolCounter = 0;
isAllWithinTol = 0;
valveControl(CLOSE_ALL);
Serial.print(F("satt: "));
Serial.println(PIN_ALL_INDI, 1);
}
else if (!allIndiSwitchEnabled && isIndependentEnabled)
{
activeTire = 6;
isIndependentEnabled = false;
TireTimeThres = 0;
allWithinTolCounter = 0;
isAllWithinTol = 0;
valveControl(CLOSE_ALL);
Serial.print(F("falst: "));
Serial.println(PIN_ALL_INDI,1);
}
delay(500);
}
void updatingFrontPanelLED()
{
if (isAllWithinTol)
{
digitalWrite(PIN_GREEN_LED, 1);
}
else
{
digitalWrite(PIN_GREEN_LED, 0);
}
}
void takeOneMoreMeasurement()
{
uint16_t temp = analogRead(PIN_MPX4250) - tireSensorOffset;
if (temp > maxPressureReading)
{
maxPressureReading = temp;
}
if (temp < minPressureReading)
{
minPressureReading = temp;
}
summedPressure = summedPressure + temp;
numOfMeasCounter += 1;
TireTimeThres = millis() + TIME_BETW_MEAS;
}
uint16_t calcAverage()
{
numOfMeasCounter = 0;
int16_t currentPressure = (float)(summedPressure / numberOfMeasurementsInUse) * BITS_TO_PSIUNIT_MXP4250;
if ( currentPressure < 0 )
{
currentPressure = 0;
}
summedPressure = 0;
return currentPressure;
}
void displayTirePress(uint16_t currentPressure)
{
float printOutPress = (float)currentPressure/(float)100;
if(currentPressure > 37000) // This is to eliminate "negative" pressure
{
currentPressure = 0;
}
uint8_t isCurrentPressBelow10psi = currentPressure < 995;
uint8_t startChannel = 0;
uint8_t endChannel = 0;
switch (activeTire)
{
case 0:
channe6 = currentPressure;
startChannel = activeTire;
endChannel = activeTire;
isChBelow10PSI[activeTire] = isCurrentPressBelow10psi;
break;
case 1:
channe7 = currentPressure;
startChannel = activeTire;
endChannel = activeTire;
isChBelow10PSI[activeTire] = isCurrentPressBelow10psi;
break;
case 2:
channe8 = currentPressure;
startChannel = activeTire;
endChannel = activeTire;
isChBelow10PSI[activeTire] = isCurrentPressBelow10psi;
break;
case 3:
channe9 = currentPressure;
startChannel = activeTire;
endChannel = activeTire;
isChBelow10PSI[activeTire] = isCurrentPressBelow10psi;
break;
case 4:
channe6 = currentPressure;
channe7 = currentPressure;
startChannel = 0;
endChannel = 1;
isChBelow10PSI[0] = isCurrentPressBelow10psi;
isChBelow10PSI[1] = isCurrentPressBelow10psi;
break;
case 5:
channe8 = currentPressure;
channe9 = currentPressure;
startChannel = 2;
endChannel = 3;
isChBelow10PSI[2] = isCurrentPressBelow10psi;
isChBelow10PSI[3] = isCurrentPressBelow10psi;
break;
case 6:
channe6 = currentPressure;
channe7 = currentPressure;
channe8 = currentPressure;
channe9 = currentPressure;
startChannel = 0;
endChannel = 3;
isChBelow10PSI[0] = isCurrentPressBelow10psi;
isChBelow10PSI[1] = isCurrentPressBelow10psi;
isChBelow10PSI[2] = isCurrentPressBelow10psi;
isChBelow10PSI[3] = isCurrentPressBelow10psi;
break;
}
lcd2.print(0, 0, "VF <> HF"); //Which tire is measured in left front
lcd2.print(0, 1, "VA <> HA"); //Which tire is measured in left rear
for(uint8_t i = startChannel; i < endChannel+1; i++)
{
String printOutPress_str = String((float)printOutPress, 1); //Function to display a number with one decimal
lcd2.print(LCD_X[i], LCD_Y[i], printOutPress_str); //Printed on lcd air pressure for tires
delay(50);
}
}
void updateAllWithinTol()
{
uint8_t numberOfChannelsInUse = 0;
switch (activeTire)
{
case 0:
case 1:
case 2:
case 3:
numberOfChannelsInUse = 3;
break;
case 4:
case 5:
numberOfChannelsInUse = 2;
break;
case 6:
numberOfChannelsInUse = 1;
break;
}
if (allWithinTolCounter >= numberOfChannelsInUse && !isAllWithinTol)
{
isAllWithinTol = true;
withinTolSetPoint = setPoint;
isSetPointChanged = false;
}
else if (allWithinTolCounter < numberOfChannelsInUse)
{
isAllWithinTol = false;
}
}
uint16_t calculateDeflationTime(uint16_t currentPressure)
{
uint16_t deflationParamInUse = 0;
switch (activeTire)
{
case 0:
case 1:
case 2:
case 3:
deflationParamInUse = singleChannelDeflationParam;
break;
case 4:
deflationParamInUse = frontChannelsDeflationParam;
break;
case 5:
deflationParamInUse = rearChannelsDeflationParam;
break;
case 6:
deflationParamInUse = allChannelsDeflationParam;
break;
}
uint16_t timeMilliSec = ((deflationParamInUse * 10) / log( (float)currentPressure / (float)setPoint )) + VALVE_OPENING_TIME;
if (timeMilliSec > MAX_DEFLATION_TIME)
{
timeMilliSec = MAX_DEFLATION_TIME;
}
return timeMilliSec;
}
uint16_t calculateInflationTimeMS(uint16_t currentPressure)
{
uint16_t inflationParamInUse = 0;
switch (activeTire)
{
case 0:
case 1:
case 2:
case 3:
inflationParamInUse = singleChannelInflationParam;
break;
case 4:
inflationParamInUse = frontChannelsInflationParam;
break;
case 5:
inflationParamInUse = rearChannelsInflationParam;
break;
case 6:
inflationParamInUse = allChannelsInflationParam;
break;
}
uint16_t timeMilliSec = ((float)( setPoint - currentPressure ) * ( inflationParamInUse / 100 ) ) + VALVE_OPENING_TIME;
if (timeMilliSec > MAX_INFLATION_TIME)
{
timeMilliSec = MAX_INFLATION_TIME;
}
return timeMilliSec;
}
void decideWhatToDo(int16_t currentPressure)
{
int16_t difference = currentPressure - setPoint;
if (activeTire == 0 || activeTire == 1 || activeTire == 4)
{
difference = difference - frontAxleOffset;
}
if (abs(difference) > TOLERANCE) // Last measurement not within tolerance
{
allWithinTolCounter = 0;
if (difference > 0)
{
valveControl(DEFLATE);
deflationTime = calculateDeflationTime(currentPressure);
TireTimeThres = millis() + deflationTime;
}
else if (1) //tankPress > 0) // inflation only performed if tank press > 30 psi
{
valveControl(INFLATE);
inflationTime = calculateInflationTimeMS(currentPressure);
TireTimeThres = millis() + inflationTime;
}
tireState = inflationDeflationDone;
}
else // Last measurement within tolerance
{
allWithinTolCounter += 1;
changeToNextChannel();
if (isAllWithinTol && allWithinTolCounter > STAND_BY_THRESHOLD)
{
closeAllValves();
TireTimeThres = millis() + (STAND_BY_MULTIPLAYER * ALL_WITHIN_TOL_WAIT_TIME);
tireState = allWithinTolWaiting;
}
else if (isAllWithinTol)
{
closeAllValves();
if (activeTire == 6)
{
openActiveTireValve();
}
TireTimeThres = millis() + ALL_WITHIN_TOL_WAIT_TIME;
tireState = allWithinTolWaiting;
}
else
{
valveControl(MEASURE);
TireTimeThres = millis() + SETTLING_TIME;
tireState = firstMeasurementOngoing;
}
}
}
void openActiveTireValve()
{
switch (activeTire)
{
case 0:
digitalWrite(PIN_VALVE1, HIGH);
break;
case 1:
digitalWrite(PIN_VALVE2, HIGH);
break;
case 2:
digitalWrite(PIN_VALVE3, HIGH);
break;
case 3:
digitalWrite(PIN_VALVE4, HIGH);
break;
case 4:
digitalWrite(PIN_VALVE1, HIGH);
digitalWrite(PIN_VALVE2, HIGH);
break;
case 5:
digitalWrite(PIN_VALVE3, HIGH);
digitalWrite(PIN_VALVE4, HIGH);
break;
case 6:
digitalWrite(PIN_VALVE1, HIGH);
digitalWrite(PIN_VALVE2, HIGH);
digitalWrite(PIN_VALVE3, HIGH);
digitalWrite(PIN_VALVE4, HIGH);
break;
}
}
void closeAllValves()
{
digitalWrite(PIN_VALVE0, LOW);
digitalWrite(PIN_VALVE1, LOW);
digitalWrite(PIN_VALVE2, LOW);
digitalWrite(PIN_VALVE3, LOW);
digitalWrite(PIN_VALVE4, LOW);
digitalWrite(PIN_VALVE5, LOW);
}
void valveControl(int command)
{
closeAllValves();
isValve5Closed = true;
switch (command)
{
case CLOSE_ALL:
// Empty on purpose
break;
case MEASURE:
openActiveTireValve();
break;
case INFLATE:
isInflating = true;
openActiveTireValve();
digitalWrite(PIN_VALVE5, HIGH);
isValve5Closed = false;
break;
case DEFLATE:
isDeflating = true;
openActiveTireValve();
digitalWrite(PIN_VALVE0, HIGH);
break;
case CALIBRATION:
digitalWrite(PIN_VALVE0, HIGH);
break;
}
}
uint16_t tireOffsetCalibration()
{
valveControl(CALIBRATION);
//delay(250);
uint16_t temp = 0;
for (int8_t i = 0; i < NUM_OF_MEASUREMENTS_SHORT_FILTER; i = i + 1)
{
temp = temp + analogRead(PIN_MPX4250);
delay(TIME_BETW_MEAS);
}
uint16_t tireSensorOffset = (temp / NUM_OF_MEASUREMENTS_SHORT_FILTER);
valveControl(CLOSE_ALL);
//delay(250);
return tireSensorOffset;
}
void writeParamToEEPROM()
{
// Unfinished function
}
void loadParamFromEEPROM()
{
singleChannelDeflationParam = EEPROM.read(SINGLE_CHANNEL_DEFLATION_PARAM_ADDRESS);
singleChannelInflationParam = EEPROM.read(SINGLE_CHANNEL_INFLATION_PARAM_ADDRESS);
frontChannelsDeflationParam = EEPROM.read(FRONT_CHANNELS_DEFLATION_PARAM_ADDRESS);
frontChannelsInflationParam = EEPROM.read(FRONT_CHANNELS_DEFLATION_PARAM_ADDRESS);
rearChannelsDeflationParam = EEPROM.read(REAR_CHANNELS_DEFLATION_PARAM_ADDRESS);
rearChannelsInflationParam = EEPROM.read(REAR_CHANNELS_DEFLATION_PARAM_ADDRESS);
allChannelsDeflationParam = EEPROM.read(ALL_CHANNELS_DEFLATION_PARAM_ADDRESS);
allChannelsInflationParam = EEPROM.read(ALL_CHANNELS_DEFLATION_PARAM_ADDRESS);
}
void updatingControlParameters()
{
if (isDeflating && isInflating)
{
// Error: should not happen
}
else if (isDeflating && deflationTime > 0 && (firstMeasurementPressure - secondMeasurementPressure) > 0)
{
uint16_t newDeflationParam = deflationTime / log( (float)firstMeasurementPressure / (float)secondMeasurementPressure) / 10;
switch (activeTire)
{
case 0:
case 1:
case 2:
case 3:
singleChannelDeflationParam = newDeflationParam;
break;
case 4:
frontChannelsDeflationParam = newDeflationParam;
break;
case 5:
rearChannelsDeflationParam = newDeflationParam;
break;
case 6:
allChannelsDeflationParam = newDeflationParam;
break;
}
}
else if (isInflating && inflationTime > 0 && (secondMeasurementPressure > firstMeasurementPressure))
{
uint16_t newInflationParam = inflationTime / (float)(secondMeasurementPressure - firstMeasurementPressure) * 100;
switch (activeTire)
{
case 0:
case 1:
case 2:
case 3:
singleChannelInflationParam = newInflationParam;
break;
case 4:
frontChannelsInflationParam = newInflationParam;
break;
case 5:
rearChannelsInflationParam = newInflationParam;
break;
case 6:
allChannelsInflationParam = newInflationParam;
break;
}
}
isDeflating = false;
isInflating = false;
if ( EEPROMTimeThres < millis() )
{
EEPROMTimeThres = millis() + 5000;
writeParamToEEPROM();
}
}
int16_t updateFrontAxleOffset()
{
closeAllValves();
int16_t offset = 0;
for (uint8_t i = 0; i < 20; i++)
{
offset = map(analogRead(setPoint),0,1023,-8,8) * 50; // range from -4 to 4 psi with 0,5 psi resolution
if(offset >= 0)
{
lcd.print(11, 0, " ");
}
String offset_str = String((float)offset/100, 1);
lcd.print(11, 0, offset_str);
delay(250);
}
return offset;
}
ok thanks
I was trying :)[quote=âmarvin7, post:163, topic:12034â]
3) why enabled the updatingSetPoint() ? this one was for manual pot input. Disabled here.
[/quote]
I was trying to find these errors and I forget to take out :)[quote=âmarvin7, post:163, topic:12034â]
4) you have included wdt101 (a watchdog timer) but no wdt handling in code. Either disable it (not include the wdt101) or complete basing on provided examples (at github for example)
[/quote]
If disable this then come errors we put the code into the Arduino
so I think Iâll leave this to be in!
No error now begin testing in the next few days or week,
But and again thanks for your help
That is strange⊠On my setup it compiles just fine without wdt⊠(see the shoot)
But OK, it doesnât hurt the code, just not necessary until properly implemented.
yes this is weird but this function now!
I tried again and it works, probably lies this with me, sorry