Control PWM motor running time with millis

Hey!

I'm new to this Arduino, and my first project is an automatic watering system for a plant of mine.
I've got most of the program working, only problem is i cant stop my motor aka. pump, unless i read my water level again. I'm trying to only have the pump running for 10 secs, to not make the plant overflow.

Any inputs, or assistance is very much appreciated!

(some of the int's are in danish)

Regards Pefi

#include <Wire.h>  // Comes with Arduino IDE
#include <LiquidCrystal_I2C.h>

const int vand_niveau = A3;    // Vand niveau i reservoir.
const int vand = 8;           // Spændings kontrol for vand lavt niveau.
const int fugtighed = 4;      // Spændings kontrol for jord fugtighed.
const int jord = A0;    // Jord fugtighed.
int motor_pwm = 9;    // Kontrol af pumpe mængde.
int output_vand;      // Vand niveau skrives hertil.
int output_jord;      // Jord fugt skrives hertil


unsigned long int_tim = 0;
unsigned long pump_tim = 0;
unsigned long pump_tim_cur_millis = 0;
unsigned long display_tim = 0;   // Serial or display timer
unsigned long display_backlight_tim = 0;


LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // LCD I2C addresse (0x3F)

void setup() {
  Serial.begin(9600);     // Kommunikations vindue
  lcd.begin(16, 2);   // Initialize the LCD 16 Char 2 Lines, turn on backlight

  for (int i = 0; i < 6; i++) // ------- Quick 6 blinks of backlight  ---------
  {
    lcd.backlight();
    delay(150);
    lcd.noBacklight();
    delay(150);
  }
  lcd.backlight();    // Finish with backlight on

  pinMode (vand, OUTPUT);
  pinMode (fugtighed, OUTPUT);
  pinMode (motor_pwm, OUTPUT);
  pinMode (LED_BUILTIN, OUTPUT);


  Serial.begin(9600);
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("Analyserer fugt");
  lcd.setCursor(0, 1);
  lcd.print("vent venligst");
  Serial.println("Analyserer fugt:");
  delay(2000);
  lcd.clear();



}

void loop() {
  // when characters arrive over the serial port...
  if (Serial.available()) {
    // wait a bit for the entire message to arrive
    //delay(100);
    // clear the screen
    lcd.clear();
    // read all the available characters
    while (Serial.available() > 0) {
      // display each character to the LCD
      lcd.write(Serial.read());
    }
  }
  // Turns on the VCC for the humidity sensor once sensor every hour, and then reads the value - also check water level in holding tank
  if (millis() - int_tim >= 6000) {   // OBS_1 <- Den her tid skal ændres i forbindelse med test, men ikke til mindre end 2000

    digitalWrite(vand, HIGH);
    digitalWrite(fugtighed, HIGH);
    if (millis() - int_tim >= 6250) {  // OBS <- Den her tid skal være 250 ms større end OBS_1

      output_vand = analogRead(vand_niveau);
      output_vand = map(output_vand, 0, 400, 0, 100);
      output_jord = analogRead(jord);
      output_jord = map(output_jord, 1023, 400, 0, 100);
      //Serial.print("Moisture : ");
      //lcd.print("Fugt:");
      //lcd.print(output_vand);
      //lcd.print("%");
      //lcd.setCursor(0, 1);
      //lcd.print("Plante:");
      //lcd.print(output_jord);
      //lcd.print("%");
      //Serial.print(output_vand);
      //Serial.print("%");
      //lcd.clear();
      int_tim = millis();
      digitalWrite(vand, LOW);
      digitalWrite(fugtighed, LOW);
    }
  }
  //unsigned long currentMillis = millis();

  if (output_jord < 40       // Fugtighed I plante under 40% start motor
      && output_vand > 40) {   // Fugtighed I reservoir over 40% start motor
    analogWrite(motor_pwm, 200);
  }
  else {
    analogWrite (motor_pwm, 0);
  }
  pump_tim_cur_millis = millis();
  // If the pump is "ON" and 1000 ms have elapsed, turn off the pump
  if (motor_pwm, 200); {
    if (millis() - pump_tim_cur_millis >= 2000) {
      analogWrite (motor_pwm, 0);
    }
  }
    //  If water level in tank is below threshold, blink the display with 1000 ms cycle
    if (output_vand < 40) {
      if (millis() - display_backlight_tim >= 1000) {
        lcd.backlight();
      }
      if (millis() - display_backlight_tim >= 2000) {
        lcd.noBacklight();
        display_backlight_tim = millis();
      }
    }

    // Write to the display every 1000 ms
    if (millis() - display_tim >= 1000) {
      lcd.clear();
      Serial.print("Moisture : ");
      lcd.print("Fugt:");
      lcd.print(output_vand);
      lcd.print("%");
      lcd.setCursor(0, 1);
      lcd.print("Plante:");
      lcd.print(output_jord);
      lcd.print("%");
      Serial.print(output_vand);
      Serial.print("%");
      display_tim = millis();
    }

  }

Test.ino.ino (4.11 KB)

  if (motor_pwm, 200);Whatever this is supposed to do I bet it does not work

You are correct, i've been trying alot of things, and that was a remnant of one. Now deleted. Thx :slight_smile:

Where do you set pump_tim_cur_millis?

Just above the line which should turn the pump off.

I'm trying to accomplish the PWM motor running for 10 secs, and the turn off.

  if (output_jord < 40       // Fugtighed I plante under 40% start motor
      && output_vand > 40) {   // Fugtighed I reservoir over 40% start motor
    analogWrite(motor_pwm, 200);
  }
  else {
    analogWrite (motor_pwm, 0);
  }
  pump_tim_cur_millis = millis();
  // If the pump is "ON" and 1000 ms have elapsed, turn off the pump
  if (millis() - pump_tim_cur_millis >= 2000) {
    analogWrite (motor_pwm, 0);
  }

It looks like you're setting pump_tim_cur_millis every time loop() is run. And then immediately you check to see if 2000 milliseconds have passed. I don't think this is the right place to set pump_tim_cur_millis.

It looks like pump_tim_cur_millis is a time stamp that is supposed to contain the time that the pump was turned on. Maybe you should move that line to the place where you turn on the pump.

So moving it up in the enclosed loop where i decide the pump to run would be more suitable?

Pefi:
So moving it up in the enclosed loop where i decide the pump to run would be more suitable?

If you renamed the variable to pumpStartTime it would be more obvious where in the code you should set its value

I have now changed the name of the variable for the timing of the pump, and moves it to where i start it, but again it only turns off the pump if it read the output value again.

if (millis() - int_tim >= 6000) {   // OBS_1 <- Den her tid skal ændres i forbindelse med test, men ikke til mindre end 2000

    digitalWrite(vand, HIGH);
    digitalWrite(fugtighed, HIGH);
    if (millis() - int_tim >= 6250) {  // OBS <- Den her tid skal være 250 ms større end OBS_1

      output_vand = analogRead(vand_niveau);
      output_vand = map(output_vand, 0, 400, 0, 100);
      output_jord = analogRead(jord);
      output_jord = map(output_jord, 1023, 400, 0, 100);
      //Serial.print("Moisture : ");
      //lcd.print("Fugt:");
      //lcd.print(output_vand);
      //lcd.print("%");
      //lcd.setCursor(0, 1);
      //lcd.print("Plante:");
      //lcd.print(output_jord);
      //lcd.print("%");
      //Serial.print(output_vand);
      //Serial.print("%");
      //lcd.clear();
      int_tim = millis();
      digitalWrite(vand, LOW);
      digitalWrite(fugtighed, LOW);
    }
  }
  //unsigned long currentMillis = millis();

  if (output_jord < 40       // Fugtighed I plante under 40% start motor
      && output_vand > 40) {   // Fugtighed I reservoir over 40% start motor
    analogWrite(motor_pwm, 200);
    pumpStartTime = millis();
  }
  else {
    analogWrite (motor_pwm, 0);
  }
  // If the pump is "ON" and 1000 ms have elapsed, turn off the pump
  if (millis() - pumpStartTime >= 1000) {
    analogWrite (motor_pwm, 0);
  }

Please post the whole program as it is now

Here it is:

#include <Wire.h>  // Comes with Arduino IDE
#include <LiquidCrystal_I2C.h>

const int vand_niveau = A3;    // Vand niveau i reservoir.
const int vand = 8;           // Spændings kontrol for vand lavt niveau.
const int fugtighed = 4;      // Spændings kontrol for jord fugtighed.
const int jord = A0;    // Jord fugtighed.
int motor_pwm = 9;    // Kontrol af pumpe mængde.
int output_vand;      // Vand niveau skrives hertil.
int output_jord;      // Jord fugt skrives hertil


unsigned long int_tim = 0;
unsigned long pump_tim = 0;
unsigned long pumpStartTime = 0;
unsigned long display_tim = 0;   // Serial or display timer
unsigned long display_backlight_tim = 0;


LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // LCD I2C addresse (0x3F)

void setup() {
  Serial.begin(9600);     // Kommunikations vindue
  lcd.begin(16, 2);   // Initialize the LCD 16 Char 2 Lines, turn on backlight

  for (int i = 0; i < 6; i++) // ------- Quick 6 blinks of backlight  ---------
  {
    lcd.backlight();
    delay(150);
    lcd.noBacklight();
    delay(150);
  }
  lcd.backlight();    // Finish with backlight on

  pinMode (vand, OUTPUT);
  pinMode (fugtighed, OUTPUT);
  pinMode (motor_pwm, OUTPUT);
  pinMode (LED_BUILTIN, OUTPUT);


  Serial.begin(9600);
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("Analyserer fugt");
  lcd.setCursor(0, 1);
  lcd.print("vent venligst");
  Serial.println("Analyserer fugt:");
  delay(2000);
  lcd.clear();



}

void loop() {
  // when characters arrive over the serial port...
  if (Serial.available()) {
    // wait a bit for the entire message to arrive
    //delay(100);
    // clear the screen
    lcd.clear();
    // read all the available characters
    while (Serial.available() > 0) {
      // display each character to the LCD
      lcd.write(Serial.read());
    }
  }
  // Turns on the VCC for the humidity sensor once sensor every hour, and then reads the value - also check water level in holding tank
  if (millis() - int_tim >= 6000) {   // OBS_1 <- Den her tid skal ændres i forbindelse med test, men ikke til mindre end 2000

    digitalWrite(vand, HIGH);
    digitalWrite(fugtighed, HIGH);
    if (millis() - int_tim >= 6250) {  // OBS <- Den her tid skal være 250 ms større end OBS_1

      output_vand = analogRead(vand_niveau);
      output_vand = map(output_vand, 0, 350, 0, 100);
      output_jord = analogRead(jord);
      output_jord = map(output_jord, 1023, 400, 0, 100);
      //Serial.print("Moisture : ");
      //lcd.print("Fugt:");
      //lcd.print(output_vand);
      //lcd.print("%");
      //lcd.setCursor(0, 1);
      //lcd.print("Plante:");
      //lcd.print(output_jord);
      //lcd.print("%");
      //Serial.print(output_vand);
      //Serial.print("%");
      //lcd.clear();
      int_tim = millis();
      digitalWrite(vand, LOW);
      digitalWrite(fugtighed, LOW);
    }
  }
  //unsigned long currentMillis = millis();

  if (output_jord < 40       // Fugtighed I plante under 40% start motor
      && output_vand > 40) {   // Fugtighed I reservoir over 40% start motor
    analogWrite(motor_pwm, 200);
    pumpStartTime = millis();
  }
  else {
    analogWrite (motor_pwm, 0);
  }
  // If the pump is "ON" and 1000 ms have elapsed, turn off the pump
  if (millis() - pumpStartTime >= 1000) {
    analogWrite (motor_pwm, 0);
  }
  //  If water level in tank is below threshold, blink the display with 1000 ms cycle
  if (output_vand < 40) {
    if (millis() - display_backlight_tim >= 1000) {
      lcd.noBacklight();
    }
    if (millis() - display_backlight_tim >= 2000) {
      lcd.backlight();
      display_backlight_tim = millis();
    }
  }

  // Write to the display every 1000 ms
  if (millis() - display_tim >= 1000) {
    lcd.clear();
    Serial.print("Moisture : ");
    lcd.print("Fugt:");
    lcd.print(output_vand);
    lcd.print("%");
    lcd.setCursor(0, 1);
    lcd.print("Plante:");
    lcd.print(output_jord);
    lcd.print("%");
    Serial.print(output_vand);
    Serial.print("%");
    display_tim = millis();
  }

}

What values do you get for output_vand and output_jord when the sensors are turned off ?
Why are you turning them off ? Just read them when you need to, otherwise don't

There may be other problems but it looks like one is that every time you come through loop() if the conditions for switching the pump on are still true you switch it on again and reset pumpStartTime.

Try checking whether the pump is already on before you switch it on. Then you will only reset pumpStartTime when it actually needed starting not every time round the loop().

Steve

I get no value, reason being if i have the probes with constant VCC on, the value decreases beacuse the voltage makes an electrolysis.

If you've got a better idea, it's muc appreciated.

slipstick:
There may be other problems but it looks like one is that every time you come through loop() if the conditions for switching the pump on are still true you switch it on again and reset pumpStartTime.

Try checking whether the pump is already on before you switch it on. Then you will only reset pumpStartTime when it actually needed starting not every time round the loop().

Steve

I see your point, but i'm aiming to only check the moisture in he soil once every 2-4 hour, and i dont want the pump to be running for the entire time.