I hope to get some information about adding a feature to my current Arduino project.
I am currently using the following code in which I had help from users on this forum, My Project is able to take a single input of either a HIGH or LOW to turn on different Solenoid valves.
Arduino Code.
void setup() {
// put your setup code here, to run once:
//serial.begin(9600);
pinMode(2, INPUT); // Machine sendings signal to this Pin..
pinMode(3, OUTPUT); // Connects to Solenoid 1
pinMode(7, OUTPUT); // Connects to Solenoid 2A
pinMode(8, OUTPUT); // Connects to Solenoid 2B
}
void loop() {
// put your main code here, to run repeatedly:
int value = digitalRead(2); // This Input can send HIGH or LOW Signals for upto 5 Seconds
//SOLENOID 1 (When Input Signal is LOW, Solenoid 1 Activates)
if(value == 1)
{
digitalWrite(3, HIGH);
} else {
digitalWrite(3, LOW);
}
//SOLENOID 2A (When Input Signal is HIGH, Solenoid 2A Activates)
if(value == 0)
{
digitalWrite(7, HIGH);
} else {
digitalWrite(7, LOW);
}
//SOLENOID 2B (When Input Signal is HIGH, Solenoid 2B Activates)
if(value == 0)
{
digitalWrite(8, HIGH);
} else {
digitalWrite(8, LOW);
}
}
I would like to add some kind of external control (Maybe a Volume Knob, like what a stereo has) to set a limit of maximum turned on time for the Solenoid.
(My input signal can vary the HIGH and LOW pulse quickly and slowly. It is automatically controlled by another computer system. I sometimes have seen that 1 of the solenoids, "Solenoid 2B" is staying on too long)
I need to via an external volume knob, to set a MAXIMUM staying on time for "Solenoid 2B"
Can someone let me know if this is possible? I read something about the analog inputs but don't know where to start.
Start by reading about analogRead here, and look at this example to see how to read a pot and map its output. That would enable you to convert the pot's actual value to a range of times.
Then it gets a bit tricky. I think you would need to use the method shown here in State Change Detection to monitor when the button becomes pressed. (edit: by which I mean in your case, when "value" becomes 0.) At that moment, capture the time with millis() (reference). Continuously compare the new, ever-increasing millis() to that captured one and turn off if it's been on too long.
Looking at your code, It's confusing me.
Is the machine input high or low on power up ?
Your trying to control 3 solenoids with one input ?
My understanding from your logic is
If the input is high on power up Solenoid_2A & Solenoid_2B and will be on and Solenoid_1 will be off
If the input is low on power up only Solenoid_1 will be on.
Also when your writing code avoid using just pin numbers and name the variables to make it easier to debug.
Try this code below, If the input been low on power up only solenoid 1 is on then when the input is taken high then to low solenoid 2A comes on then off but solenoid 2B stays on for 5 seconds then goes off.
There may be a better way of doing and if you wanted it make the interval variable you could just read a pot then use the map function to set the interval time.
#define Machine_Input 2 // Machine sendings signal to this Pin..
#define Solenoid_1 3 // Connects to Solenoid 1
#define Solenoid_2A 7 // Connects to Solenoid 2A
#define Solenoid_2B 8 // Connects to Solenoid 2B
unsigned long previousMillis = 0; // will store last time LED was updated
unsigned long previousMillis1 = 0; // will store last time LED was updated
const long interval = 5000; // interval at which to blink (milliseconds)
unsigned long currentMillis = 0;
unsigned long currentMillis1 = 0;
int Solenoid_2B_state = LOW;
void setup() {
// put your setup code here, to run once:
//serial.begin(9600);
pinMode(Machine_Input, INPUT_PULLUP); // Machine sendings signal to this Pin..
pinMode(Solenoid_1, OUTPUT); // Connects to Solenoid 1
pinMode(Solenoid_2A , OUTPUT); // Connects to Solenoid 2A
pinMode(Solenoid_2B, OUTPUT); // Connects to Solenoid 2B
digitalWrite(Solenoid_1, LOW);
digitalWrite(Solenoid_2A, LOW);
digitalWrite(Solenoid_2B, LOW);
}
void loop() {
// put your main code here, to run repeatedly:
int value = digitalRead(Machine_Input); // This Input can send HIGH or LOW Signals for upto 5 Seconds
//SOLENOID 1 (When Input Signal is LOW, Solenoid 1 Activates)
if (value == 1)
{
digitalWrite(Solenoid_1, HIGH); //This will be on If machine input is high on power up ?
} else {
digitalWrite(Solenoid_1, LOW);
}
//SOLENOID 2A (When Input Signal is HIGH, Solenoid 2A Activates)
if (value == 0)
{
digitalWrite(Solenoid_2A, HIGH); //This will be off If machine input is high on power up ?
} else {
digitalWrite(Solenoid_2A, LOW);
}
currentMillis = millis();
//SOLENOID 2B (When Input Signal is HIGH, Solenoid 2B Activates)
if (value == 0)
{
Solenoid_2B_state = HIGH; //This will be off If machine input is high on power up ?
}
if (currentMillis - previousMillis <= interval && Solenoid_2B_state == HIGH ) {
// save the last time you blinked the LED
previousMillis = currentMillis;
Solenoid_2B_state = HIGH;
// if the LED is off turn it on and vice-versa:
if (Solenoid_2B_state == HIGH) {
Solenoid_2B_state = HIGH;
}
digitalWrite(Solenoid_2B, Solenoid_2B_state);
Solenoid_2B_state = LOW;
}
currentMillis1 = millis();
if (currentMillis1 - previousMillis1 >= interval) {
previousMillis1 = currentMillis1;
Solenoid_2B_state = LOW;
digitalWrite(Solenoid_2B, Solenoid_2B_state);
}
}
I forgot it may be better to add button debounce which there is plenty of information on the web, This will help stopping in false triggering.
Your trying to control 3 solenoids with one input ?
Yes,
Is the machine input high or low on power-up ?
the system is currently not bothered by the startup state,
sometimes the Arduino turns on with the signal being high, and sometimes being low.
my issue is I have sometimes seen that one of the solenoids stays on for too long and I like the idea of having external physical control. allowing me to limit how long the solenoid can stay on.
The code has become a bit more complex now with the additional solenoids hahaha
but I hoped to publish my simpler code in O.P.
I might need some help with coding up a volume knob.
I will look deeper at the analog input link you have sent through
I still need to know the code that would add a limitation to the solenoid's on time.
Happy NY everyone
P.S.
I have seen the 2.5k/5k/10k potentiometer is a good choice. I will grab one.
the most important thing would be that the code will read the Potentiometer via analog input,
and if set to say time 1 Second,
I would need the solenoid to turn off after 1 second, even though the next solenoid is schedules to turn on in 4 more seconds,
The system still needs to read the input. (after being stopped by the external time trimming) the system is not to continue until the next pulse.
This new revision of the code, allows for a total of 4 Solenoids to be used. and speed detection for auto cyclic of Solenoids 2A/2B/2C. It detects rapid speeds and starts the cycling which allows for pressure to build, as I had a pressure loss issue.
I require Solenoid 1 to be further modified by way of the external trimming Potentiometer.
NEW Code, please expand the code via the aarow at the very left.
//BLOCK COMMENT
//https://forum.arduino.cc/t/cyclic-relay2a-2b/889080/10
#define ProjectName "Solenoids"
// CONSTANT DEFINITION
// you need to change these constants to your hardware
const byte Relays[] {3, 7, 8, 4};
const byte Buttons[] {2};
// VARIABLE DECLARATION
enum {One, TwoA, TwoB, TwoC};
struct BUTTON
{
byte pin;
int pressedState; // LOW for Active Low
bool wasPressed;
int counter;
unsigned long lastStateChangeTime;
unsigned long debounceInterval;
} button {Buttons[One], 1, 0, 0, 20};
void setup()
{
Serial.begin(9600);
Serial.println(F("."));
Serial.print(F("File : ")), Serial.println(__FILE__);
Serial.print(F("Date : ")), Serial.println(__DATE__);
Serial.print(F("Project: ")), Serial.println(ProjectName);
pinMode (LED_BUILTIN, OUTPUT);
for (auto Relay : Relays) pinMode ( Relay, OUTPUT);
for (auto Button : Buttons) pinMode ( Button, INPUT_PULLUP);
}
void loop ()
{
unsigned long currentTime = millis();
digitalWrite(LED_BUILTIN, (currentTime / 500) % 2);
bool buttonIsPressed = digitalRead(button.pin) == button.pressedState;
if (buttonIsPressed != button.wasPressed &&
currentTime - button.lastStateChangeTime >= button.debounceInterval)
{
// State Change Detected
button.wasPressed = buttonIsPressed;
button.lastStateChangeTime = currentTime;
{
// Button was just pressed
button.counter = (button.counter + 1) % 6;
static unsigned long TimeOfLastButtonPress = 0;
unsigned long timeBetweenButtonPresses = currentTime - TimeOfLastButtonPress;
TimeOfLastButtonPress = currentTime;
for (auto Relay : Relays)
digitalWrite ( Relay, LOW);
if (timeBetweenButtonPresses > 200) // longer than a second and a half
SlowPressCycle(button.counter);
else if (timeBetweenButtonPresses > 100) // Longer than half a second
MediumPressCycle(button.counter);
else
StandardCycle(button.counter);
}
}
}
// When the Pulse is SLOW (like every 2 Seconds)
// I would like all Relays (TwoA, B & C) same time
void SlowPressCycle(int count)
{
switch (count)
{
case 0:
digitalWrite ( Relays[One] , HIGH);
break;
case 1:
digitalWrite ( Relays[TwoA] , HIGH);
digitalWrite ( Relays[TwoB] , HIGH);
digitalWrite ( Relays[TwoC] , HIGH);
break;
case 2:
digitalWrite ( Relays[One] , HIGH);
break;
case 3:
digitalWrite ( Relays[TwoA] , HIGH);
digitalWrite ( Relays[TwoB] , HIGH);
digitalWrite ( Relays[TwoC] , HIGH);
break;
case 4:
digitalWrite ( Relays[One] , HIGH);
break;
case 5:
digitalWrite ( Relays[TwoA] , HIGH);
digitalWrite ( Relays[TwoB] , HIGH);
digitalWrite ( Relays[TwoC] , HIGH);
break;
}
}
// When the Pulse is faster (every 1 second)
// to have cycle between TwoA,B then TwoB,C
void MediumPressCycle(int count)
{
switch (count)
{
case 0:
digitalWrite ( Relays[One] , HIGH);
break;
case 1:
digitalWrite ( Relays[TwoA] , HIGH);
digitalWrite ( Relays[TwoB] , HIGH);
break;
case 2:
digitalWrite ( Relays[One] , HIGH);
break;
case 3:
digitalWrite ( Relays[TwoB] , HIGH);
digitalWrite ( Relays[TwoC] , HIGH);
break;
case 4:
digitalWrite ( Relays[One] , HIGH);
break;
case 5:
digitalWrite ( Relays[TwoC] , HIGH);
digitalWrite ( Relays[TwoA] , HIGH);
break;
}
}
// When the Pulse is Fastest (faster than 1 second)
// Standard Cycle TwoA, then TwoB, then TwoC.
void StandardCycle(int count)
{
switch (count)
{
case 0: digitalWrite ( Relays[One] , HIGH); break;
case 1: digitalWrite ( Relays[TwoA] , HIGH); break;
case 2: digitalWrite ( Relays[One] , HIGH); break;
case 3: digitalWrite ( Relays[TwoB] , HIGH); break;
case 4: digitalWrite ( Relays[One] , HIGH); break;
case 5: digitalWrite ( Relays[TwoC] , HIGH); break;
}
}
Special Thanks to user here 'johnwasser' for huge assistance. This code update has been absolutely amazing