Help me to include interrupt inputs and PID Relay swiching in my project.

Hi, I am Building a Relay Controller for my garage which is intended to fill compressed air
to tire as presets values selectable with a dial (potentiometer) and a small 16x2 LCD display with I2C Interface. ,(easy to use for users working there) and a push button.
I designed a digital pressure sensor using mechanical pressure gauge and an high resolution optical encoder strip and encoder, which I found in an old printer head (Pics attached) which got A and B Signal out and +5v and GND. (tested sketches & working!)
I then thought it can be used to determine the HIGH,LOW state. and record the small changed in the mechanical gauge with optical strip attached and tell the adrino the output air state or count or pressure (as you can make suggestions) and if the signal reading from the sensor tells adrino a low out pressure and set point set with potentiometer for high pressure the adrino activates the swithing of relays as PID (more difference in set value and actual value long switching. Gradually short swithing and when the set range reached off).
Hardware:
adrino Uno R3
4 relay module
16x2 lcd with I2C interface.
potentiometer
Optical Encoder (2 Channel)
LED
Push Button
Resitors
Bread Board
Jumper Wires.
Mechanical part of air Pressure Gauge (moves optical strip up and down.)

My uncompleted code(attached) which is now showing display, different presets while turning the potentiometer is below. although i included relays and leds ,no loop is created i lost here,

PID RELAY CODE attached as remarks it was for my workouts when i saw PID relay example in new adrino IDE version all these concept got more interesting for me.
Code pasted here inside code tags.

Some Pics: attached.

Any help/Suggestions appreciated. Thanks.

My Project Code.txt (8.18 KB)

I can't see any question apart from the title and that is very vague.

What will be causing the interrupts?
Why do you think interrupts will be needed? The process you are controlling does not seem like one that needs an instantaneous response.

Please say if the following is a correct statement of your situation
Your Arduino can read the tyre pressure gauge
You can display the required pressure on an LCD
You can alter the required pressure using a potentiometer

And this is what I think you want to achieve
When the tyre-hose is attached to a tyre with a pressure below the required value
The Arduino will activate a relay to allow some air in for a period of time
It will then shut off the relay so it can re-test the tyre pressure
It will then repeat the air/test process if necessary
As the tyre pressure gets closer to the required pressure the inflation periods should get shorter

How much of this have you implemented and what does your latest the code actually do?

You may get some ideas from my own PID explorations. It's a long Thread but I did get a working system out of it.

...R

PS. Can your system deflate an over-pressure tyre? It's a few years since I had a car but my recollection is that if you slightly over-inflate a tyre you can read the pressure constantly while deflating it and stop at the exact point you want.

Hi Robin
Appriciate your Quick view on my post
I am not so familier with complicated codes. call me newbie in adrino. in the internet I read interrupt is used in optical sensor data,with high resolution, i don't know how to interpret that signals into pressure(PSI) your advise is needed., and I was not mentioned what the relay for: it is for solinoid valve activating it allows air to flow in to the air horse & sensor.
Into your questions:-
Your Arduino can read the tyre pressure gauge ----NO not yet configured for that
You can display the required pressure on an LCD---yes it is now displaying required pressure.
it can alter the required pressure using a potentiometer.

And this is what I think you want to achieve ---- Yes,
When the tyre-hose is attached to a tyre with a pressure below the required value
The Arduino will activate a relay to allow some air in for a period of time------yes
It will then shut off the relay so it can re-test the tyre pressure----- yes
It will then repeat the air/test process if necessary-----yes
As the tyre pressure gets closer to the required pressure the inflation periods should get shorter----exactly

My latest code (Please see attachment) after switching on displys "booting" counts 1% to 100% and shows
welcome Message, then Shows Set Pressure PSI, second line SET VALUE by rotating potentiometer it changes. thats all, Help me to include optical sensor in my code which can read tire pressure,and appropriate switching of relay. (I don't know interrupt is needed or not but I request for a better solution)

Your Question is valid in the case of over inflated tire i will later include a servo motor. if the tire pressure reads higher than the set value the servo will sweep and pull a air exhaust value and decrease the pressure. (but this concept is not considered in this project.)
Thank You once again,

In general a complex computer project is a collection of small pieces of code that work together.

You say

Your Arduino can read the tyre pressure gauge ----NO not yet configured for that

so let's just focus on getting that part working and ignore everything else for the moment.

You said in your Original Post

I designed a digital pressure sensor using mechanical pressure gauge and an high resolution optical encoder strip and encoder, which I found in an old printer head (Pics attached) which got A and B Signal out and +5v and GND. (tested sketches & working!)

That is what made me think you had the pressure measurement working.
Post that program and explain how you think it can be adapted to work with your tyre pressure gauge. In this case a picture of the encoder strip the tyre pressure gauge will be a big help.
Post a link to the datasheet for the encoder.

...R

Data Sheet of encoder:

sensor working: Air Pressure makes the curved part of the mechanical air gauge to move. I attached a optical strip at the end that will also move along , I think this optical sensor can somehow convert that data as my actual air pressure in the air horse. ( optical sensor High,low count code gives very exact numbers as we blow air , or even touch the sensor, 0 1 2 3 4 5 6 and return 6 5 4 3 2 1 0 .
pictures are attached
The code used for checking the sensor

/* read a rotary encoder with interrupts
   Encoder hooked up with common to GROUND,
   encoder0PinA to pin 2, encoder0PinB to pin 4 (or pin 3 see below)
   it doesn't matter which encoder pin you use for A or B  

   uses Arduino pull-ups on A & B channel outputs
   turning on the pull-ups saves having to hook up resistors 
   to the A & B channel outputs 

*/

#define encoder0PinA  2
#define encoder0PinB  3

volatile unsigned int encoder0Pos = 0;

void setup() { 
  
 
  pinMode(encoder0PinA, INPUT); 
  digitalWrite(encoder0PinA, HIGH);       // turn on pull-up resistor
  pinMode(encoder0PinB, INPUT); 
  digitalWrite(encoder0PinB, HIGH);       // turn on pull-up resistor

  attachInterrupt(0, doEncoder, CHANGE);  // encoder pin on interrupt 0 - pin 2
  Serial.begin (9600);
   Serial.println("start");                // a personal quirk

} 

void loop(){
// do some stuff here - the joy of interrupts is that they take care of themselves
}

void doEncoder() {
  /* If pinA and pinB are both high or both low, it is spinning
   * forward. If they're different, it's going backward.
   *
   * For more information on speeding up this process, see
   * [Reference/PortManipulation], specifically the PIND register.
   */
  if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)) {
    encoder0Pos++;
  } else {
    encoder0Pos--;
  }

  Serial.println (encoder0Pos, DEC);
  
  
}

/* See this expanded function to get a better understanding of the
 * meanings of the four possible (pinA, pinB) value pairs:
 */
void doEncoder_Expanded(){
  if (digitalRead(encoder0PinA) == HIGH) {   // found a low-to-high on channel A
    if (digitalRead(encoder0PinB) == LOW) {  // check channel B to see which way
                                             // encoder is turning
      encoder0Pos = encoder0Pos - 1;         // CCW
    } 
    else {
      encoder0Pos = encoder0Pos + 1;         // CW
    }
  }
  else                                        // found a high-to-low on channel A
  { 
    if (digitalRead(encoder0PinB) == LOW) {   // check channel B to see which way
                                              // encoder is turning  
      encoder0Pos = encoder0Pos + 1;          // CW
    } 
    else {
      encoder0Pos = encoder0Pos - 1;          // CCW
    }

  }
  Serial.println (encoder0Pos, DEC);          // debug - remember to comment out
                                              // before final program run
  // you don't want serial slowing down your program if not needed
}

/*  to read the other two transitions - just use another attachInterrupt()
in the setup and duplicate the doEncoder function into say, 
doEncoderA and doEncoderB. 
You also need to move the other encoder wire over to pin 3 (interrupt 1). 
*/

Agilent_Optical_Encoders.pdf (246 KB)

Image from Reply #4 so we don't have to download it. See this Image Guide

...R

I think if this was my project and my principal objective was a working air-delivery system I would get a ready-made linear encoder and remove all uncertainty from that part of the project.

However if you are able to read the encoder then I think all that is necessary to convert the encoder readings to pressure values is to figure out the formula that relates the encoder reading to the pressure. If you are lucky it will be a linear relationship so, for example if 10psi = a reading of 120 and 100psi = a reading of 870 you can figure that a reading halfway between (495) represents 50psi.

You will need to take a lot of measurements to check the relationship. And you will need to make sure that it is the same after a few days, or you may need a daily calibration routine.

Have you given any thought to how you will deal with the situation if the Arduino crashes and fails to turn off the air?

...R

Hi
I will reconstruct the Sensor part on a isolated & vibration free platform. (pics was from testing platform).

linear relationship you explained above is exactly I want to include in my code. I know I have to take regular
readings and go through calibration routine. I only need the code which relates linear movement into psi . can you please go through my project code and include this part in it, and include if analog set point > actual value ,activate switching of relay ,which will stop at analog setpoint= actual value. with Proportional Switching delay (Which is in my subject referred as PID).
My Project Code see below;

//sensor input(interepts pin 2,3). (no idea how to include this)
//value reads from the optical sensor with A-ch,B-ch and matches within the range of analog range from potentiometer will shut the relay off.
//pushButton assigned will turn on the relay swithing for set value by potentiometer.
// push to fill preset turn on relay second press turn off the relay
//Manual mode keep the relay on.....
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

#define I2C_ADDR    0x27  // Define I2C Address where the PCF8574A is
#define BACKLIGHT_PIN     3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7


LiquidCrystal_I2C  lcd(I2C_ADDR, En_pin, Rw_pin, Rs_pin, D4_pin, D5_pin, D6_pin, D7_pin);
int sensorPin= A0;    // Potentiometer attached as human interface for selection of various states.this case air pressure.and swithing modes.
int buzzerPin= 4;     // attached for long
int relayLed= 5;       // GOES HIGH WHEN RELAY GOES HIGH.
int pushButton= 6;     // Select Button,(TO INITIATE THE RELAY SWITCHING) AS PER SELECTION (VALUE OR MODE)
int servoPin=7;        // assigned for later developments if required servo motor will be attached to a valve to release air. not considered now. 
int relayPin1= 8;      // 1st Relay           4 RELAY MODULE  I WILL USE ONLY relayPin1 in this project.although all pins are initiated.
int relayPin2= 9;      // 2nd Relay
int relayPin3= 10;     //3rd Relay
int relayPin4= 11;     //4th Relay
int ledPin1= 12; // HIGH WHEN SYSTEM IS READY (blinks when given loop in process after push button).
int ledPin2= 13; // POWER ON INDICATOR ON OUTSIDE PANNEL


void setup() {
pinMode(buzzerPin, OUTPUT);//declare buzzer ( beep per switching and long beep after pressure arrives at set point)
pinMode(relayLed, OUTPUT);//declare the ledPin as an output
pinMode(pushButton, OUTPUT); //declare the pushbutton attached 
pinMode(servoPin, OUTPUT); // SERVO MOTOR WILL BE ATTACHED AT LATER STAGE. NOT NOW.
pinMode(relayPin1, OUTPUT);//ONLY ONE RELAY IS USED.PIN 8
pinMode(relayPin2, OUTPUT);//ONLY ONE RELAY IS USED.PIN 9
pinMode(relayPin3, OUTPUT);//ONLY ONE RELAY IS USED.PIN 10
pinMode(relayPin4, OUTPUT);//ONLY ONE RELAY IS USED.PIN 11
pinMode(ledPin1, OUTPUT);// declare the ledPin as an output
pinMode(ledPin2, OUTPUT);// declare the ledPin as an output
  lcd.begin(16, 2);
  lcd.setCursor(0, 0); //set cursor to top left corner
  lcd.print("Booting....:"); //print the text to the lcd
 lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE); // Switch on the backlight
  lcd.setBacklight(HIGH);
  for (int i = 0; i <= 100; i++) { // you can change the increment value here
    lcd.setCursor(12, 0);
    if (i < 100) lcd.print(" "); //print a space if the percentage is < 100
    if (i < 10) lcd.print(" "); //print a space if the percentage is < 10
    lcd.print(i);
    lcd.print("%");
    delay(100);  //change the delay to change how fast the boot up screen changes
  }
  lcd.setCursor(0, 0);// USES FIRST LINE TO PRINT WELCOME MESSAGE

  // Print a message to the LCD.
  lcd.print("WELCOME     USER:");
  lcd.setCursor(0, 1);//Second Line of the welcome message (0,1)
  lcd.print("PASSWORD: *****");
  delay(2000);
  lcd.clear();
   
}
void loop() {
  lcd.home();   //go home
  lcd.print("Set Air Pressure:");
  int sensorVal = analogRead (A0);
  // DispltCursor (0, 1);
  lcd.setCursor(0, 1);
  // Read sensor value
  float Pressure = sensorVal;
   if (sensorVal <= 120) // List of Preset values and analog reference for the project  <=120 analog Range
    lcd.print("PUSH TO FILL."); //puSH BUTTON WILL MAKE RELAY PIN HIGH next press low
  else if (sensorVal > 121 and sensorVal <= 160)  // 121-160 analog Range
    lcd.print("PSI 030 AUTO");
  else if (sensorVal > 161 and sensorVal <= 200)  // 161-200 analog Range
    lcd.print("PSI 032 AUTO");
  else if (sensorVal > 201 and sensorVal <= 240)  // 201-240 analog Range
    lcd.print("PSI 035 AUTO");
  else if (sensorVal > 241 and sensorVal <= 280)  // 241-280 analog Range
    lcd.print("PSI 040 AUTO");
  else if (sensorVal > 281 and sensorVal <= 320)  // 281-320 analog Range
    lcd.print("PSI 045 AUTO");
  else if (sensorVal > 321 and sensorVal <= 360)  // 321-360 analog Range
    lcd.print("PSI 050 AUTO");
  else if (sensorVal > 361 and sensorVal <= 400)  // 361-400 analog Range
    lcd.print("PSI 055 AUTO");
  else if (sensorVal > 401 and sensorVal <= 440)  // 401-440 analog Range
    lcd.print("PSI 060 AUTO");
  else if (sensorVal > 441 and sensorVal <= 480)  // 441-480 analog Range
    lcd.print("PSI 065 AUTO");
  else if (sensorVal > 481 and sensorVal <= 520)  // 481-520 analog Range
    lcd.print("PSI 070 AUTO");
  else if (sensorVal > 521 and sensorVal <= 560)  // 521-560 analog Range
    lcd.print("PSI 075 AUTO");
  else if (sensorVal > 561 and sensorVal <= 600)  // 561-600 analog Range
    lcd.print("PSI 080 AUTO");
  else if (sensorVal > 601 and sensorVal <= 640)  // 601-640 analog Range
    lcd.print("PSI 085 AUTO");
  else if (sensorVal > 641 and sensorVal <= 680)  // 641-680 analog Range
    lcd.print("PSI 090 AUTO");
  else if (sensorVal > 681 and sensorVal <= 720)  // 681-720 analog Range
    lcd.print("PSI 095 AUTO");
  else if (sensorVal > 721 and sensorVal <= 760)  // 721-760 analog Range
    lcd.print("PSI 100 AUTO");
  else if (sensorVal > 761 and sensorVal <= 800)  // 761-800 analog Range
    lcd.print("PSI 105 AUTO");
  else if (sensorVal > 801 and sensorVal <= 840)  // 801-840 analog Range
    lcd.print("PSI 110 AUTO");
  else if (sensorVal > 841 and sensorVal <= 880)  // 841-880 analog Range
    lcd.print("PSI 115 AUTO");
  else if (sensorVal > 881 and sensorVal <= 920)  // 881-920 analog Range
    lcd.print("PSI 120 AUTO");
  else if (sensorVal > 921 and sensorVal <= 960)  // 921-960 analog Range
    lcd.print("PSI 125 AUTO");
  else if (sensorVal > 961 and sensorVal <= 1000) // 961-1000 analog Range
    lcd.print("PSI 130 AUTO");
  else if (sensorVal > 1001 )                     //   > 1001 ,No sensor reference ( relay pin goes HIGH for ever)
    lcd.print("MANUAL--MODE"); 
  
}

Your question:
Have you given any thought to how you will deal with the situation if the Arduino crashes and fails to turn off the air?
Answer:
attaching a safety valve can avoid any accident. although such possibilities are minor as operator will always be present when filling air incase abnormality recognized by him he can manually shutoff the system . and buzzer is also high when relay is high so that would be helpful to recognize this.
if not Safety Valve calibrated at max PSI on the basis of regular use will automatically open and prevent any accident.

Please try to reply with code
Thanks.

If I take the mid points of your sensor readings then 140 corresponds with a pressure of 30p. and 940 corresponds with a pressure of 125psi. So, for a sensor range of 800 the pressure varies by 95 - and it is probably sufficiently accurate to call that 100. That means you can calculate the pressure like this

tyrePSI = (sensorValue - 140) / 8 + 30

but please check it carefully against actual values as it may need to be tweaked.

That would save all the IF statements.

And if you do want to use the IF statements they could be simplified like this

   if (sensorVal <= 120) // List of Preset values and analog reference for the project  <=120 analog Range
    lcd.print("PUSH TO FILL."); //puSH BUTTON WILL MAKE RELAY PIN HIGH next press low
  else if (sensorVal <= 160)  // 121-160 analog Range
    lcd.print("PSI 030 AUTO");
  // etc

Assuming you calculate the tyrePSI as above then you can decide to open the air valve with something like
if (tyrePSI < requiredPSI) {
// code to open air valve
// or, perhaps, code to restart the air-valve timer
}

You could also set the time (milliseconds) for the air-valve timer relative to the size of the difference inpressure - for example

airValveMillis = (requiredPSI - tyrePSI * nnnn);

where nnnn is some factor to get the value into the required range.

...R

Hi Robin,

That would save all the IF statements.

This was so helpful.for simplifying the code

"Sensor Range" was not the value from the sensor it is the Pot analog read,

I am collecting the Optical encoder data at every PSI for code. (Number of High to Low transitions and visa versa. from A output to B output of Optical encoder)

Will be back with a clean data and what i need out of it , I hope anybody could easily understand that way. and write a adrino code for that purpose,

I will be back with the data soon ,
Thanks for the help .