screw compressor control module

dears,

i'm new with programming and arduino,a week i was working on little project.
control module for screw air compressor.

itead Rboard (atmel328) the module with lcd to display information,running status,motor temperature (used ds18b20),pressure status (used 4-20ma pressure transmitter)

so the idea is press boutton start motor (3 phase 380V)in delta star mode,pressed again stop.

during ranning status if pressure reach 9Bars it stop in idle mode until pressure drops to 4 bars it star again.
also during running if temperature reach 90degree it stop and restart if temp drop to 80degres.

also use eeprom library in order to display total running hours during power on (for maintenance).
electrovalve for unload ,to be used after start and litle while before stop.

actually the module works great,but if any advice is welcome,othewise hope that help somebody as i found usefull other projects.

Thanks to all.

/* ADTS
    Code By fouad
    For Mahle Compressor -MSK-G
*/

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <EEPROM.h>

//Eeprom variable
long RunTime ;
long PRunTime = 0;
//int address = 0;

//RunCouter Variables
unsigned long startMillis;  //some global variables available anywhere in the program
unsigned long currentMillis;
const unsigned long period = 60000;  //the value is a number of milliseconds


// Temp Sensor
#define ONE_WIRE_BUS 8
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
int SensorTemp;
int cooldown = 0;
int PidMax = 90;//temperature high set ponit
int PidMin = 80;//temperature low setpoint
//Temp Smoothing
const int numReadings = 10;
int readings[numReadings];      // the readings from the analog input temperature
int readIndex = 0;              // the index of the current reading temperature
int total = 0;                  // the running total temperature
int average = 0;                // the average temperature
//Pressure Smoothing
const int PnumReadings = 10;
int Preadings[PnumReadings];      // the readings from the analog input pressure
int PreadIndex = 0;              // the index of the current reading pressure
int Ptotal = 0;                  // the running total pressure
int Paverage = 0;                // the average pressure



//const byte POWER_LED = 2;

//Input Output variable Definitons
int Halted = 0;
const byte BUTTON_1 = 9;//pin 3 on 24l01
const byte RELAY_1 = 4;//Main Contactor
const byte RELAY_2 = 5;//Star Contactor
const byte RELAY_3 = 6;//Delta Contactor
const byte RELAY_4 = 7;//Valve Contactor
//Sensor Configuration
const int P1pin = A0;
//const int P2pin= A1;
int netP = 0;
//int ledpin=7;
int P1analogreading; //read from sensor
const int PidMaxPr = 9;//max pressure set point
const int PidMinPr = 6;//low pressure set point
int PidStb = 0;//variable for standby stature ,0 not in standby
//const int pmax_current = 20 ;
//const int pmin_current = 4;
const int pmax = 2500 ;//sensor max pressure
const int pmin = 0;//sensor minimum pressure
const int sensorhigh = 901;//max adc value when sensor at 40ma,with 220ohm resistor 
const int sensorlow = 190;//minimum adc value when sensor at 4ma(0 bar)
int last_button_state = 0;
byte BUTTON_STATE[15];
byte RELAY_STATE[15];
/* number of milliseconds to enable RELAY_2 after start button has been pressed */
const int START_MS = 3000;//delay time for change status delta start
//LCD Code
//Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);


void setup() {

  //Temp Sensor Initialisation
  sensors.begin();
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;//smoother initialisation
  }
  //LCD Initialisation
  lcd.begin();
  lcd.backlight();
  RunTime = 0;//initialis variable for working hours.
  //RunCounter Timer Initialisation
  startMillis = millis();  //initial start time
  //pressur sensor
  lcd.setCursor(6, 0);
  EEPROM.get( 0, RunTime );//get working hours stored in eepron
  PRunTime = RunTime / 60;//calculate working hours,working hours are stored in minutes
  lcd.print(PRunTime);
  lcd.setCursor(0, 1);
  lcd.print("A.D.T.S");
  delay(5000);
  lcd.setCursor(0, 1);
  lcd.print("Pret     ");//ready

  //Output define
  pinMode(RELAY_1, OUTPUT);
  pinMode(RELAY_2, OUTPUT);
  pinMode(RELAY_3, OUTPUT);
  pinMode(RELAY_4, OUTPUT);
  pinMode(BUTTON_1, INPUT);
  //Set All State to 0
  for (int n = 0; n <= sizeof(BUTTON_STATE); n++) {
    BUTTON_STATE[n] = 0;
  }
  for (int n = 0; n <= sizeof(RELAY_STATE); n++) {
    RELAY_STATE[n] = 0;
  }

  UpdateRelay();
  last_button_state = 1;

}



void SetRelayStop()
{
  RELAY_STATE[RELAY_4] = 0;
  UpdateRelay();
  delay(500);//pressure valve opened before stop motor
  RELAY_STATE[RELAY_1] = 0;
  RELAY_STATE[RELAY_2] = 0;
  RELAY_STATE[RELAY_3] = 0;
  lcd.setCursor(0, 1);
  lcd.print("Arret           ");//stop
  UpdateRelay();
  delay (1000);//Delay for Stop motor from 2000 to 0 rpm.
}

void UpdateRelay()
{
  digitalWrite(RELAY_1, RELAY_STATE[RELAY_1]);
  digitalWrite(RELAY_2, RELAY_STATE[RELAY_2]);
  digitalWrite(RELAY_3, RELAY_STATE[RELAY_3]);
  digitalWrite(RELAY_4, RELAY_STATE[RELAY_4]);

}

void SetRelayStarting()
{
  RELAY_STATE[RELAY_1] = 1;
  RELAY_STATE[RELAY_2] = 0;
  RELAY_STATE[RELAY_3] = 1;
  lcd.setCursor(0, 1);
  lcd.print("Demarrage ");//starting
  UpdateRelay();
  
}

void SetRelayRunning()
{
  RELAY_STATE[RELAY_3] = 0;
  RELAY_STATE[RELAY_1] = 0;//used this metode because no protection on contators,so little while that can be adjuted to prevent short circuit betwen delta contactor and star contactor.
  UpdateRelay();
  delay (500);
  RELAY_STATE[RELAY_1] = 1;
  RELAY_STATE[RELAY_2] = 1;
  UpdateRelay();
  lcd.setCursor(0, 1);
  lcd.print("Marche     ");//running
  RELAY_STATE[RELAY_4] = 1;
  UpdateRelay();
}

void Monitor () {
      //using smoothing value for both pressure and temperature
      total = total - readings[readIndex];
      // read from the sensor:
      SensorTemp = sensors.getTempCByIndex(0);
      readings[readIndex] = SensorTemp;
      // add the reading to the total:
      total = total + readings[readIndex];
      // advance to the next position in the array:
      readIndex = readIndex + 1;
      // if we're at the end of the array...
      if (readIndex >= numReadings) {
        // ...wrap around to the beginning:
        readIndex = 0;
      }
      // calculate the average:
      average = total / numReadings;
      sensors.requestTemperatures();
      //Pressure Read
      Ptotal = Ptotal - Preadings[PreadIndex];
      P1analogreading = analogRead (P1pin);
      Preadings[PreadIndex] =  P1analogreading;
      Ptotal = Ptotal + Preadings[PreadIndex];
      PreadIndex = PreadIndex + 1;
       if (PreadIndex >= PnumReadings) {
        PreadIndex = 0;
      }
      Paverage = Ptotal / PnumReadings;
      Paverage = map(P1analogreading, sensorhigh, sensorlow, pmax, pmin);
      Paverage = Paverage /100;//to display xx pressure in bar
      //Pressure Readin
      lcd.print ("                ");
      lcd.setCursor (0, 0);
      lcd.print ("PR:");//pressure display
      lcd.print (Paverage);
      lcd.print (" TP:");//temperature disply
      lcd.print (average);
  
}


void TempPid()
{
  if ((average >= PidMax) && (average != -127)) {
    SetRelayStop();
    cooldown = 1;
    while (cooldown == 1) {
      lcd.setCursor(0, 1);
      lcd.print ("Temp Haute     ");//high temperature
      lcd.setCursor (0, 0);
      Monitor ();
      if (average <= PidMin) {
        cooldown = 0;
        Halted = 1;
      }
    }
  }
  if (average == -127) {
    SetRelayStop();
    lcd.setCursor(0, 1);
    lcd.print("ERREUR TEMP 01  ");//error temp sensor
  }
}

void PressurePid ()
{
  Monitor ();  
  if (Paverage >= PidMaxPr)  {
    SetRelayStop();
    PidStb = 1;
  }
  while (PidStb == 1){
    Monitor ();
    if (Paverage < PidMinPr) {
      PidStb = 0;
      Halted = 1;
     }
   }
   if ( Paverage < 0 ){
     SetRelayStop();
     lcd.setCursor(0, 1);
     lcd.print("ERREUR Pr 01    ");//pressure sensor error
   }
}





//initializ variable for button and running state
int last_state_change = 0;
int STATE = 0;
int last_bounce = 0;

4-20 ma.png

the other part of code

void loop() {

  Monitor();
  PressurePid ();
  TempPid ();
  /*if (average == -127) {
    SetRelayStop();
    lcd.setCursor(0, 1);
    lcd.print("ERREUR TEMP 01 ");
  }*/
  int m = millis();
  if ((Halted == 1) && (STATE != 0)) {
    STATE = 1;
    Halted = 0;
    last_state_change = m;
    SetRelayStarting();
    lcd.setCursor(0, 1);
    lcd.print("Demarrage ");
  }

  switch (STATE) {
    case 1:
      /* starting up */
      if (m - last_state_change > START_MS) {
        /* timer for both relays has now expired - alter state */
        STATE = 2;
        //TempPid ();
        SetRelayRunning();
      }
      break;
      ;;
  }

  //Run Counter Timr
  
  currentMillis = millis();  //get the current "time" (actually the number of milliseconds since the program started)
  if ((currentMillis - startMillis >= period) && (STATE != 0))  //test whether the period has elapsed
  {
    RunTime++;
    EEPROM.put( 0, RunTime );
    startMillis = currentMillis; 
  }

  /* check buttons */
  int button_1 = digitalRead(BUTTON_1);
  if (button_1 != last_button_state) {
    /* reset bounce timer */
    last_bounce = m;
  }

  if (m - last_bounce > 50) {
    /* button really changed (debounce) */
    if (BUTTON_STATE[BUTTON_1] != button_1) {
      BUTTON_STATE[BUTTON_1] = button_1;
      if (button_1) {
        /* button has been released */
        //Serial.println("Button released");
      } else {
        /* button has been pressed */
        //Serial.println("Button pressed");
        switch (STATE) {
          case 0:
            /* change to state 1 - power on */
            STATE = 1;
            last_state_change = m;
            SetRelayStarting();
            lcd.setCursor(0, 1);
            lcd.print("Demarrage ");
            break;
            ;;
          default:
            /* button press in any other state
               results in everything turning off */

            /* turn off relays */
            last_state_change = m;
            STATE = 0;
            SetRelayStop();
            lcd.setCursor(0, 1);
            lcd.print("Arret           ");
            SetRelayStop();
            ;;
        }
      }
    }
  }
  last_button_state = button_1;
  char buf[100];
}

What is troubeling You? There is no specific question.

nothing wrong,just wondering if any optimisation or idea to make better.

Keep on working on Your project. A working code needs not to be optmized, just only do what You want it to do.

Now you can add in a oil level / pressure sensor to make sure you don’t run the compressor too low.

You could control cooling fans instead of just shutting down.

There is no oil level sensor on this compressor,just a little transparent little pipe ,pehaps a color detector will do the job.for the cooling fans are mecanical attached directly to motor, however the cooling mode ithinks whenn unload via closing electrovalve (inlet valve) and keep motor running.

here is more optimized code.

after some test ,the compressor oil temperature rise up to 100degres,so i modify the code the way that the compressor do not stop runnig,just close inlet valve to reduce the load from motor ,this mode allow the compressor to cooldown the oil (fan and oilpump stil running)

compressor_controller_v1.9.ino (10.3 KB)

But You wil run out of air, don't You? Okej, saving the compressor is of coarse neccessary.

You use the EEPROM. Are You aware of the limited number of Writings to such memory?

in this kind of compressor there is inlet electrovalve ,open or close input of air ,when opened let air in to be compressed and send to air tank ,if closed do not unload the air tank because there is mechanical check valve ,do not allow reverse ,in this case no significant load applied ,only fan and oil pump works wich cause cooling of the compressor

Yes I understand but the compressor air tank is supplying some compressed air consumers so preasure is going down when the comprressor is in iddl, not filling the tank with more air. Did You read my remark about the limited life of EEPROMs?

yes using eeprom to save unasigned long to store 32 bits,and each time its update,minutes that converted to hours when display.

unasigned long 4,294,967,295 / 60 = 71,082,788 hours,i think that enough.

for the air,the compressor work at full load untill reach 9 bars,and enter onto cooling mode waiting for pressure to drop below 6 bars (enough to supply other machines )and re-enter onto full load mode.

for eeprom i have no idea,it will be great if help or illustrate.

I just read that atmel 328 eeprom life is 100000 read/write times!!!!!

Thats not enough.

The Itead rboard include sd card reader,i guess that alternativ way to save data.

I probably misunderstood Your sketch. I just copied it into an Arduino window and took a closer look. You read the EEPROM but You never write to it. Then EEPROM life is no problem. You have a well organized code but I find no loop(). That is normaly the main running code. Setup is mostly used for setting things up at startup. Then the ongoing work is done in loop(), called "Main()" in some environments. Never mind! If Your code is doing the job You want it is good code!

Did you download the compressor controller v1.9 ino file attached?

Yes. Then I could search for variable names and understand better.

I'm sorry, it was the very first code You sent in code tags I was downloading. NOW I have downloaded the proper code I Think.

This forum is limited in code size,firt i pasted 1/3 of the code,when i whant to paste more ,it display warning that inhave to wait 5 minutes to post more,since im new i have less that 100 post.