Hi all.
I'm working on a project that uses a hall effect sensor to control the timing of some 12V solenoid valves. The problem I had used LEDs to indicate the valves back in the early stages when I was working on the valve sequence, but now that I've connected up the valves they're playing havoc with the interrupt - I suspect it's interference.
I also noted that just touching the wire that runs to the interrupt pin causes massive interference with the valves...
I've attached two videos below - one showing the sequence working (sans valves), the other NOT working (with valves) - In both videos, note the yellow LED is showing when the hall effect sensor is triggered. This is when I expect the valves will move along their sequence.
Valve sequence working: Valve Sequence Working Well - YouTube
Valve sequence NOT working: Valve Sequence NOT working - YouTube
Any idea what I can do to ensure that the sequence works correctly and reliably? I've spent way too much time trying to figure this out myself...
The schematic and code is also shown below.
EDIT: In the schematic below I forgot to connect the two grounds. They are in fact common grounds.
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // select the pins used on the LCD panel
//LCD Variables
int lcd_key = 0;
int adc_key_in = 0;
int led_on = 0;
int timer;
int btn_count = 0;
int btnDelay =200;
//int ledDelay =0;
unsigned long prevBtnMillis=0;
unsigned long prevLedMillis=0;
int ledState = LOW;
//Interrupt Variables
const byte interruptPin = 2; //Sensor pin attached
volatile byte cyl1 = LOW;
volatile bool newISR = false;
//Valve Variables //if cyl1 = true then toggle valve 1, else toggle valve 2. the interrupt will toggle cyl1.
//boolean cyl1 = true;
boolean valve1 = true;
boolean valve3 = true; // only declare boolean variables for valve 1 and 3, since 2 and 4 are just the opposite.
int V1Pin = 3;
int V2Pin = 11;
int V3Pin = 12;
int V4Pin = 13;
//Sensor Variables
int IPM = 4; //sensed intervals per revolution
volatile unsigned long prevSigTime; //Time (ms) when the last signal was received
volatile unsigned long currSigTime;
unsigned long nextSigTime; //Prediction for next interval.
unsigned long prevInterval;
unsigned long nextInterval;
//RPMVariables
unsigned int currRPM;
unsigned int setRPM = 50;
#define btnRIGHT 0
#define btnUP 1
#define btnDOWN 2
#define btnLEFT 3
#define btnSELECT 4
#define btnNONE 5
int read_LCD_buttons(){ // read the buttons
adc_key_in = analogRead(0); // read the value from the sensor
if (adc_key_in > 1000) return btnNONE;
// For V1.1 us this threshold
if (adc_key_in < 50) return btnRIGHT;
if (adc_key_in < 250) return btnUP;
if (adc_key_in < 450) return btnDOWN;
if (adc_key_in < 650) return btnLEFT;
if (adc_key_in < 850) return btnSELECT;
return btnNONE; // when all others fail, return this.
}
void setup(){
Serial.begin(9600);
lcd.begin(16, 2); // start the library
lcd.setCursor(0,0); // set the LCD cursor position
lcd.print("G-Steam 0.1"); // print a simple message on the LCD
lcd.setCursor(0,1);
lcd.print("rpm:");
// pinMode(led_pin,OUTPUT);
timer=millis()/1000;
// pinMode(interruptLed, OUTPUT);
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin),toggle,RISING);
}
void loop(){
if (newISR){
calcInterval();
}
//NEED TO FIGURE OUT HOW TO TRIGGER THE VALVES BASED ON SENSOR READING OR PREDICTION, WITHOUT UPSETTING THE SEQUENCE (ON/OFF)
//CODE BELOW IS TO ENSURE THAT THE VALVE FROM A PAIR IS TURNED OFF BEFORE THE OTHER ONE IS TURNED ON. THE POWER SUPPLY (PROBABLY)
//ONLY HAS ENOUGH POWER FOR A MAXIMUM OF 2 VALVES...
if (valve1){
digitalWrite(V2Pin, !valve1);
digitalWrite(V1Pin, valve1);
}
else{
digitalWrite(V1Pin, valve1);
digitalWrite(V2Pin, !valve1);
}
if (valve3){
digitalWrite(V3Pin, valve3);
digitalWrite(V4Pin, !valve3);
}
else{
digitalWrite(V4Pin, !valve3);
digitalWrite(V3Pin, valve3);
}
updateLCD();
}
void toggle(){
prevSigTime = currSigTime;
currSigTime = millis();
newISR = true;
if (cyl1)
{
cyl1 = !cyl1;
valve1=!valve1;
}
else
{
cyl1 = !cyl1;
valve3=!valve3;
}
//Serial.print(String(currRPM) + "; " + String(prevInterval));
//Serial.println();
}
void updateLCD(){
/* lcd.setCursor(9,1); // move cursor to second line "1" and 9 spaces over
lcd.print (btn_count);
lcd.setCursor(0,1); // move to the begining of the second line
*/
lcd_key = read_LCD_buttons(); // read the buttons
unsigned long currBtnMillis = millis();
unsigned long currLedMillis = millis();
lcd.setCursor(5,1);
lcd.print(String(currRPM) + "->" + setRPM + " ");
switch (lcd_key){ // depending on which button was pushed, we perform an action
case btnRIGHT:{ // push button "RIGHT" and show the word on the screen
//lcd.print("RIGHT ");
break;
}
case btnLEFT:{
//lcd.print("LEFT "); // push button "LEFT" and show the word on the screen
break;
}
case btnUP:{
//lcd.print("UP "); // push button "UP" and show the word on the screen
if (currBtnMillis - prevBtnMillis >= btnDelay){
setRPM = ++setRPM;
lcd.setCursor(11,1);
lcd.print (" ");
lcd.setCursor(11,1);
lcd.print (setRPM);
lcd.setCursor(0,1);
prevBtnMillis=millis();
}
break;
}
case btnDOWN:{
//lcd.print("DOWN "); // push button "DOWN" and show the word on the screen
if(currBtnMillis-prevBtnMillis>=btnDelay){
setRPM = --setRPM;
lcd.setCursor(11,1);
lcd.print (" ");
lcd.setCursor(11,1);
lcd.print(setRPM);
lcd.setCursor(0,1);
prevBtnMillis=millis();
}
break;
}
case btnSELECT:{
//lcd.print("SELECT"); // push button "SELECT" and show the word on the screen
if(currBtnMillis-prevBtnMillis>=btnDelay){
prevBtnMillis=millis();
}
break;
}
case btnNONE:{
//lcd.print("NONE "); // No action will show "None" on the screen
break;
}
}
}
void calcInterval(){
prevInterval = currSigTime-prevSigTime;
currRPM = 60000/((long)IPM*prevInterval); //equivalent to 1/interval * number of intervals per rev
newISR = false;
}