Hi everyone, I'm trying to make a greenhouse automated watering system with Arduino, but I'm having a problem with solenoid water valve. The valve is controlled by short electrical pulses, changing poles - opens or closes, it works with 4,5 volts, and sadly that is all information that I got about it. I am also using a soil humidity sensor, and I want that valve to be opened when humidity reaches, for example less than 100, and after certain amount of time, to be closed. I tried to solve this with digital pins (setting pin 8 high and pin9 low when I want to open, and pin8 low, pin9 high when I want to close) everything works fine with LED's except that I haven't figured out how to send impulse one time only (now it loops all the time when humidity is less than 100), but it does not work with solenoid valve, maybe because of the current that digital pins can handle? So could anyone give me some advises how to solve the issues with solenoid valve and how to make Arduino to send short impulse to valve one time without looping it? Sorry if my English is bad, hope you all understood what I'm trying to say.
I use a relay to operate the solenoid as the MCU I an using does not have enough drive current. Perhaps this may be the case with you thingy.
You could use millis() for timing.
Here vis how I am doing the thing.
{
//wait for a mqtt connection
while ( !MQTTclient.connected() )
{
vTaskDelay( 250 );
}
int TimeToPublish = 5000000; //5000000uS
int TimeForADreading = 100 * 1000; // 100mS
uint64_t TimePastPublish = esp_timer_get_time(); // used by publish
uint64_t TimeADreading = esp_timer_get_time();
TickType_t xLastWakeTime = xTaskGetTickCount();
const TickType_t xFrequency = 10; //delay for 10mS
float RemainingMoisture = 100.0f; //prevents pump turn on during start up
bool pumpOn = false;
uint64_t PumpOnTime = esp_timer_get_time();
int PumpRunTime = 11000000;
uint64_t PumpOffWait = esp_timer_get_time();
uint64_t PumpOffWaitFor = 60000000; //one minute
float lowMoisture = 23.0f;
float highMoisture = 40.0f;
for (;;)
{
//read AD values every 100mS.
if ( (esp_timer_get_time() - TimeADreading) >= TimeForADreading )
{
xEventGroupSetBits( eg, evtADCreading );
TimeADreading = esp_timer_get_time();
}
xQueueReceive(xQ_RM, &RemainingMoisture, 0 ); //receive queue stuff no waiting
//read gpio 0 is water level good. Yes: OK to run pump : no pump off. remaining moisture good, denergize water pump otherwise energize water pump.
if ( RemainingMoisture >= highMoisture )
{
WaterPump0_off();
}
if ( !pumpOn )
{
log_i( "not pump on ");
if ( gpio_get_level( GPIO_NUM_0 ) )
{
if ( RemainingMoisture <= lowMoisture )
{
//has one minute passed since last pump energize, if so then allow motor to run
if ( (esp_timer_get_time() - PumpOffWait) >= PumpOffWaitFor )
{
WaterPump0_on();
log_i( "pump on " );
pumpOn = !pumpOn;
PumpOnTime = esp_timer_get_time();
}
}
//xSemaphoreGive( sema_RemainingMoisture );
} else {
log_i( "water level bad " );
WaterPump0_off();
PumpOffWait = esp_timer_get_time();
}
} else {
/*
pump goes on runs for X seconds then turn off, then wait PumpOffWaitTime before being allowed to energize again
*/
if ( (esp_timer_get_time() - PumpOnTime) >= PumpRunTime )
{
log_i( "pump off " );
WaterPump0_off(); // after 5 seconds turn pump off
pumpOn = !pumpOn;
PumpOffWait = esp_timer_get_time();
}
}
// publish to MQTT every 5000000uS
if ( (esp_timer_get_time() - TimePastPublish) >= TimeToPublish )
{
xQueueOverwrite( xQ_RemainingMoistureMQTT, (void *) &RemainingMoisture );// data for mqtt publish
TimePastPublish = esp_timer_get_time(); // get next publish time
}
xLastWakeTime = xTaskGetTickCount();
vTaskDelayUntil( &xLastWakeTime, xFrequency );
}
vTaskDelete( NULL );
}// end fDoMoistureDetector()
esp_timer_get_time(); is the same as millis() on a ESP32.
but does the relay change the polarity?
could you give us details of the solenoid value being used?
usually the arduino drives a small 5V relay which operates a larger device such as a 20amp contactor or a large solenoid
Can you post a link to the solenoid you have?
Here is my valve
But I'm starting to think that I should use different solenoid valve with relay.
Hi, @Nawickaz
Welcome to the forum.
As well as a link to your valve could you please post a schematic of your project?
Please do not use a Fritzy picture, a hand drawn image will be fine.
Please include ALL power supplies, component names and pin labels.
Thanks.. Tom...
Post your code, please.
#define valve1 8
#define valve2 9
void setup() {
// put your setup code here, to run once:
Serial.begin (57600);
pinMode(valve1, OUTPUT);
pinMode(valve2, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.print("Dirvozemio dregme:");
Serial.println(analogRead(A0));
delay(100);
if(analogRead(A0) < 100) openValve();
}
void openValve() {
digitalWrite(valve1, HIGH);
digitalWrite(valve2, LOW);
delay (250);
digitalWrite(valve1, LOW);
digitalWrite(valve2, LOW);
}
Thanks for the code.
How long do you want the valve to be opened after the humidity hits 100?
You might consider using a data filter such as a rolling average filter to smooth out the readings. If you are using a Uno put a 103 ceramic cap into the Aref pin and ground, assists with data smoothing.
How long do you want the valve to be opened after the humidity hits 100?
I don't know yet, I will know later when I will test the whole thing, but for now it could be 1min.
You might consider using a data filter such as a rolling average filter to smooth out the readings. If you are using a Uno put a 103 ceramic cap into the Aref pin and ground, assists with data smoothing.
I'm using LEONARDO for this project, just because I found one in my supply box
not tested.
#define valve1 8
#define valve2 9
unsigned long previousMillis = millis();
unsigned int openTimeOfValve = 250;
bool openedValve = false;
//
void setup()
{
// put your setup code here, to run once:
Serial.begin (57600);
pinMode(valve1, OUTPUT);
pinMode(valve2, OUTPUT);
} //setup()
//
void loop() {
// put your main code here, to run repeatedly:
Serial.print("Dirvozemio dregme:");
Serial.println(analogRead(A0));
//delay(100);<< dont' use delay w millis()
if ( (analogRead(A0) < 100) && (!openedValve) )
{
openedValve = true;
previousMillis = millis();
openValve();
}
if ( openedValve )
{
if ( millis() - previousMillis >= openTimeOfValve )
{
closeValve();
openedValve = false;
}
}
} //loop()
//
void openValve()
{
digitalWrite(valve1, HIGH);
digitalWrite(valve2, LOW);
} //openValve()
//
void closeValve()
{
digitalWrite(valve1, LOW);
digitalWrite(valve2, LOW);
} //closeValve
This does not seem to do anything digitalWrite(valve2, LOW);
as both open and closed write a low to valve2.
How often do you want to print, as in once a second, once every 10 seconds, once every minute?
It takes a pulse, as in the OPs open routine. I expect close is the same but it puts the pulse on valve2.
I doubt that the Arduino pins would survive the experience, although the link doesn't actually specify how much current is pulled. A relay or MOSFET on each line will be required I expect.
I suggest using a moving average filter to smooth out the readings.
That's the valve on time, change that number to get your 1 minute. Post your code changes.
Unfortunately, that Web site is basically useless! It contains no meaningful description.
This valve clearly cannot be driven by an Arduino without suitable drive components such as a relay module or one or more FETs, depending on how it works. It clearly requires far more current than an Arduino can provide to be controlled.
And there is the problem. Without a proper description, we do not know how it works. There is a strong suggestion that it has a holding mechanism and will just require a short pulse to turn on and another to turn off - the black and red wires imply this - but in the absence of proper information this needs to be tested before you begin to consider how to use an Arduino to control it.
First step is to measure the resistance of the coil - accurately - with your multimeter.
That valve uses OPPOSITE polarity 30mS pulses. You need an H drive to make it work. Toggling a DO isn't going to get it to move both ways.
So it does appear but the description in the advertisement is completely useless (not surprisingly) with all important information absent.
I would use a DC motor controller like:
https://www.pololu.com/product/2990
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.