Automatic Control and User Interface for Central Tire Inflation System

also the above might mess with the new code. Not sure what it does, but will not check it today… It got late, even for me (a 2:30 here)

same here, good night, see this tomorrow

@marvin7
So I should put this in the code

BLYNK_WRITE(V11) { // Blynk press SET slider, where V11 is MY virtual pin (copy/paste)
	int pinValue = param.asInt();
	pinValue = constrain(pinValue, 100, 500); //this is where you put your limits of psi, multiplied by 10 for increased resolution
	setPoint = (float)pinValue / 10.0;
	delay(100);  //you can omit this one - was needed in my specific case
	lcd.print (x,y, setPoint);   //here you can send your setPoint to vLCD
	Serial.print(F("new preset setPoint: "));
	Serial.println(setPoint, 1);
}

and delete this code ?

void updatingSetPoint()
{
  uint16_t newPotRaw = analogRead(PIN_POT); // 
  
  if(abs(newPotRaw - currentPotRaw) > 10 ) // POT hysteresis
  {
    uint16_t newSetPoint = potToPSI(newPotRaw);
    if( newSetPoint != setPoint) 
    {
      setPoint = newSetPoint;
      currentPotRaw = newPotRaw;
      isSetPointChanged = true;
      if(setPoint < 995)
      {
        lcd.print(0, 0, " "); // This is for alignment of decimal point on screen
      } 
      lcd.print(0, 0, ((float)setPoint));
      Serial.println(setPoint, 3);
    }
  }
}

Basically yes, but instead delete enclose it within comments for safety :wink: (i.e this /* … */)
and add to it this line isSetPointChanged = true; for example after the setPoint= line. Also the V11 here should be changed to suit your case

This works, do not bring errors at least
had to put BLYNK_WRITE(V11); into this parameter instead of this updatingSetPoint();

void backgroundTasks()
{
  backgroundTasksTimeThres = millis() + FRONT_PANEL_TIME_THRES_PERIOD;
  readTankPress();
  BLYNK_WRITE(V11);
  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();
  }
}

actually this line should be empty (commented out) as the BLYNK_WRITE() is called automatically, when receives changed parameter from app (it’s like changing the pot): http://docs.blynk.cc/#blynk-firmware-virtual-pins-control-blynk_writevpin
and the V11? are you sure you had set slider to this vPin?

Yes du have V11 :)[quote=“marvin7, post:87, topic:12034”]
actually this line should be empty (commented out) as the BLYNK_WRITE() is called automatically, when receives changed parameter from app (it’s like changing the pot): http://docs.blynk.cc/#blynk-firmware-virtual-pins-control-blynk_writevpin
[/quote]
Done :slight_smile:

This is connected to this relay now to see if inflation or deflation compared to SetPos.

It is working, it will open and close the relay compared to SetPos :sunglasses:

@marvin7 Thanks for this help.

Nice! Keep going!
Ah, one note: don’t forget to set min/max for slider in app. The constrain() is just for security (i.e it will never exceed those limits, regardless off possible erroneously set min/max in slider).

1 Like

Then there is next on the list, led for each relay when it is open or closed.
Has been to get them to work, but think this is not done that way :slight_smile:
but you learn only when you try. so I probably is missing Simple Timers here and more:slight_smile:

My coed.

#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 <inttypes.h>
#include <Wire.h>
#include <SimpleTimer.h>

//////// 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 = 3.8425; // 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);
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_POT, 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 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();}
}


void loop()
{
  if(backgroundTasksTimeThres < millis())
  {
    backgroundTasks();
  } 
  if(TireTimeThres < millis())
  { 
    tirePressureControl();      
  }
  if(tankPressureLCDTimeThres < millis())
  {
    printTankPressureLCD();
  }

Blynk.run();
timer.run();
}
////////////// 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;
  }
  else
  {
    if (activeTire == 5)
    {
      activeTire = 4;
    }
    else
    {
      activeTire = 5;
    }
  }
}

// Print tankPressure to LCD
void printTankPressureLCD()
{
  tankPressureLCDTimeThres = millis() + TANK_PRESS_BLINK_DELAY;
  
  if(tankPress > TANKPRESSURE_BLINK_LIMIT || tankBlink == false)
  { 
    if(tankPress < 995)
    {
      lcd.print(0, 1, "  ");
    }
    else if(tankPress < 9995)
    {
      lcd.print(0, 1, " ");
    }
    
    lcd.print(0, 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(0, 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();
  pinValue = constrain(pinValue, 2, 350); //this is where you put your limits of psi, multiplied by 10 for increased resolution
  setPoint = (float)pinValue / 1.0;
  isSetPointChanged = true;
  //delay(100);  //you can omit this one - was needed in my specific case
  lcd.print (0, 0, setPoint);   //here you can send your setPoint to vLCD
  //Serial.print(F("new preset setPoint: "));
  //Serial.println(setPoint, 1);
}


/*void updatingSetPoint()
{
  uint16_t newPotRaw = analogRead(PIN_POT);
  
  if(abs(newPotRaw - currentPotRaw) > 10 ) // POT hysteresis
  {
    uint16_t newSetPoint = potToPSI(newPotRaw);
    if( newSetPoint != setPoint) 
    {
      currentPotRaw = newPotRaw;
      isSetPointChanged = true;
      if(setPoint < 9.95)
      {
        lcd.print(0, 0, " "); // This is for alignment of decimal point on screen
      } 
      lcd.print(0, 0, ((float)setPoint));
    }
  }
}*/

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);
  }
  else if (!allIndiSwitchEnabled && isIndependentEnabled)
  {
    activeTire = 6;
    isIndependentEnabled = false;
    TireTimeThres = 0;
    allWithinTolCounter = 0;
    isAllWithinTol = 0;
    valveControl(CLOSE_ALL);
  }
}

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++)
  {
    //if(printOutPress < 9.95) // This is for alignment of decimal point on screen
    
    lcd.print(4, 0, printOutPress);
    lcd.print(4, 1, printOutPress);
    lcd.print(11, 0, printOutPress);
    lcd.print(11, 1, printOutPress);
    //Serial.print(F("new preset printOutPress: "));
    //Serial.println(printOutPress, 1);
    
  }
}


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 > 3000) // 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(2 * SETTLING_TIME);
  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(2 * SETTLING_TIME);
  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((setPoint), 0, 1023, -8, 8) * 50; // range from -4 to 4 psi with 0,5 psi resolution
    if (offset >= 0)
    lcd.print(3, 1, (float)offset);
    //delay(250);
  }
  return offset;
}

Need help with this is to get troubleshooting-flood-error sometimes, but more often.
Has been looking at this back and forth and try to spread and improve.

Code above

[2694] IP:192.168.10.4
[2715] 
    ___  __          __
       / _ )/ /_ _____  / /__
      / _  / / // / _ \/  '_/
     /____/_/\_, /_//_/_/\_\
            /___/ v0.4.6 on Arduino 101

    [5001] Connecting to 192.168.10.2
    [5063] Ready (ping: 4ms).
    [27095] Trouble detected: http://docs.blynk.cc/#troubleshooting-flood-error
    [30848] Connecting to 192.168.10.2
    [30975] Ready (ping: 6ms).

Is possibility to use Blynk Slider to give me half a value, for example 2.5, 3, 3.5? or is it just 2 or 3 or 4?

no, it is not possible. but just use values 10 X bigger than what you need on slider, then divide them by 10 in code

@wanek

and it functions but then I get this number 254 when I want to get a 2.54 and I get 256 when I want to get something is 25.6 can be put to fix it?

can you send me how you implemented this? i do not really understand what you mean… please elaborate.

I am using this coid and this did not work :pensive:
or I’m not doing this right :wink:

BLYNK_WRITE(V11) { // Blynk press SET slider, where V11 is MY virtual pin (copy/paste)
  int pinValue = param.asInt();
  pinValue = constrain(pinValue /10); //this is where you put your limits of psi, multiplied by 10 for increased resolution
  setPoint = (float)pinValue;
  isSetPointChanged = true;
  //delay(100);  //you can omit this one - was needed in my specific case
  if(setPoint < 9)
      {
        lcd.print(0, 0,"  "); // This is for alignment of decimal point on screen
      }
  lcd.print (0, 0, setPoint);   //here you can send your setPoint to vLCD
  //Serial.print(F("new preset setPoint: "));
  //Serial.println(setPoint, 1);
}

this code returns me value to decide what PSI to be in my tires and to get a more accurate value it would be good to choose wading for example 2.5 psi instead can only choose 2 or 3 psi.
need half value
By placing Slider to 20 (10x2 psi) and 350 (10x35psi) and divide 10 into the code, then come out 3-digit numbers need to see like this number of 2.0 or 2.5psi and then I got a more accurate psi for this equipment, but now I get 20 and 25psi which is not the correct value inside code because he works only from 2 to 35 psi.
Top left number

Do not know if this is enough

declare pinValue as float, not int. for simplicity, just write instead of:

int pinValue = param.asInt();
  pinValue = constrain(pinValue /10);  // 10 is not correct. when using floats should be 10.0!!!

this:

float pinValue = constrain(param.asInt() / 10.0);

also, please post the constrain function here, to see what happening in there.

urhleypibunadur:442: error: macro “constrain” requires 3 arguments, but only 1 given

float pinValue = constrain(param.asInt() / 10.0);

                                            ^

replace these 2 lines:

with this:

and see if it helps.
and search for the void constrain() function, and share here, for information.

1 Like

but did get an error :slight_smile:
thanks