Timer program to control two outputs with variable settings

Hello,

I am currently designing a device that will control a fan output and a solenoid (water valve). The on time and off time will be set by potentiometers and the values will be in minutes. The values are displayed on a liquid crystal display. Currently I am having a difficult time understanding the timer programs and how I could use them to control what would be 4 independent and variable timers. Another issue I am having is if I use the line float sensorValue0 = 0; the value will be 6 sig. digits, however, if I use int sensorValue0 = 0; the result is unreliable if I max out the potentiometer then return it to a lower level. This device will be used to control the humidity and fresh air exchange in a room used to grow oyster mushrooms.

http://www.flickr.com/photos/80287430@N04/7371939266/in/photostream

 #include <ArduinoTestSuite.h>
#include <avr_cpunames.h>

/*
 
 
 Demonstrates the use a 16x2 LCD display.  The LiquidCrystal
 library works with all LCD displays that are compatible with the 
 Hitachi HD44780 driver. There are many of them out there, and you
 can usually tell them by the 16-pin interface.
 
 http://www.arduino.cc/en/Tutorial/LiquidCrystal
 */

// include the library code:
#include <LiquidCrystal.h>
#include <EventFuse.h>
#include <MsTimer2.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
int sensorPin0 = A0;
int sensorPin1 = A1;
int sensorPin2 = A2;
int sensorPin3 = A3;
float sensorValue0 = 0;
float sensorValue1 = 0;
float sensorValue2 = 0;
float sensorValue3 = 0;
int FAN = 6;      // sets pin 6 for solid state relay
int MIST = 5;  //sets pin 5 for mist solenoid
int MISTLED = 4;  //sets pin 4 for mist LED indicator
int FANLED = 3;  //sets pin 3 for fan LED indicator

void setup() {

  lcd.begin(16, 2);  // set up the LCD's number of columns and rows:
  lcd.print(" MORGAN  INDUSTRIES MIST ON             FAN ON");
  pinMode(FAN, OUTPUT);
  pinMode(MIST, OUTPUT);
  pinMode(MISTLED, OUTPUT);
  pinMode(FANLED, OUTPUT);
  //MsTimer2::set(1000, timerTick );   // One second intervals, for testing
  //MsTimer2::start();
}

void loop() {

  // (note: line 1 is the second row, since counting begins with 0):
  sensorValue0 = analogRead(sensorPin0)/10; 
  sensorValue1 = analogRead(sensorPin1)/10; 
  sensorValue2 = analogRead(sensorPin2)/10; 
  sensorValue3 = analogRead(sensorPin3)/10;

  digitalWrite(MISTLED, HIGH);
  digitalWrite(FANLED, HIGH);
  digitalWrite(FAN, HIGH);
  lcd.setCursor(7, 1);
  lcd.print(sensorValue0);
  lcd.setCursor(8, 2);
  lcd.print(sensorValue1);
  lcd.setCursor(13, 1);
  lcd.print(sensorValue2);
  lcd.setCursor(14, 2);
  lcd.print(sensorValue3);
}

Also...any advice for getting my code to post properly? I think I tried just about everything.

rodmo1:
Also...any advice for getting my code to post properly? I think I tried just about everything.

Don't use the copy to forum feature, just manually copy all of your code from you sketch, paste it into your web browser and surround it by the code tags

Guess I didn't try that...thanks

rodmo1:
Currently I am having a difficult time understanding the timer programs and how I could use them to control what would be 4 independent and variable timers.

You can take a look at the Blink without Delay code to give you an idea on how to "schedule" an action to occur at specific intervals. You also may want to expand on what you are trying to achieve with these timers.

Another issue I am having is if I use the line float sensorValue0 = 0; the value will be 6 sig. digits, however, if I use int sensorValue0 = 0; the result is unreliable if I max out the potentiometer then return it to a lower level.

analogRead returns an integer between 0 and 1023, not a float. If you set it as a float and divide it by 10, then the best case scenario is preceision to the tenths place. I recommend avoiding floats unless you absolutely have to use them as they are more taxing with instructions and memory. Perhaps give us some more information on what you are trying to do with these values and what they represent.

Thanks for helping Arrch...The numbers will represent the minutes that the output(s) will stay on and also stay off for. Example...I want to run the circulation fan in a cycle consisting of 25 minutes on followed by 35 minutes off repeating. The potentiometers will adjust the amount of minutes for each function. The problem I am encountering when I use the int function for the analog values is when displayed on the LCD the values are initially accurate (0-120) until I increase the value to 100 or greater. At this point the value is constantly 3 significant digits regardless of potentiometer position. Example...25 becomes 250. The only way to go back to the correct value is to reset the controller. I am currently modifying code to use the blink without delay example. It should help. Will post with results.

Rod

rodmo1:
The problem I am encountering when I use the int function for the analog values is when displayed on the LCD the values are initially accurate (0-120) until I increase the value to 100 or greater. At this point the value is constantly 3 significant digits regardless of potentiometer position. Example...25 becomes 250. The only way to go back to the correct value is to reset the controller.

That sounds like it's just the LCD displaying the extra character from the previous reading, rather than the actual value being off.

Say you write "1234" to the LCD. If you go back to the same position and write "43", your result would be "4334" because you have left over digits from the previous print. To verify that's the case, you can print your data to the serial monitor and compare it with your LCD value.

You are correct. Unfortunately I can't find a command that would clear specific locations on the LCD. lcd.clear() works however it also clears the permanent parts of the display and also creates an awful appearance of the variables. I may be able to come up with a conditional argument that would insert one or two blank spaces after the value if it is less than 10 or 100. The blink without delay is working well with my program...I just need to spend some time so I can adjust both on and off. As currently written it will have a 50% duty cycle regardless of inputs. Will continue to work on device in a few hours. Must move on to other project for a bit.

Rod

rodmo1:
You are correct. Unfortunately I can't find a command that would clear specific locations on the LCD. lcd.clear() works however it also clears the permanent parts of the display and also creates an awful appearance of the variables.

Assuming you know the maximum number of spaces it can take up, you can just write a bunch of spaces with that length and then move the cursor back and write the value.

I did what you recommended for the LCD issue and it worked well. There is only a slight amount of flickering now. In using the blink without delay function I have encountered a real head scratcher. It works great for controlling either the time on or time off coupled together but I am having a heck of a time doing the two values independently. Attached is what I have so far. It does not work very well. I am not getting a steady blink.

 #include <ArduinoTestSuite.h>
#include <avr_cpunames.h>

/*
 
 
 Demonstrates the use a 16x2 LCD display.  The LiquidCrystal
 library works with all LCD displays that are compatible with the 
 Hitachi HD44780 driver. There are many of them out there, and you
 can usually tell them by the 16-pin interface.
 
 http://www.arduino.cc/en/Tutorial/LiquidCrystal
 */

// include the library code:
#include <LiquidCrystal.h>
#include <EventFuse.h>
#include <MsTimer2.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
int sensorPin0 = A0;
int sensorPin1 = A1;
int sensorPin2 = A2;
int sensorPin3 = A3;
int sensorValue0 = 0;
int sensorValue1 = 0;
int sensorValue2 = 0;
int sensorValue3 = 0;
int FAN = 6;      // sets pin 6 for solid state relay
int MIST = 5;  //sets pin 5 for mist solenoid
int MISTLED = 3;  //sets pin 4 for mist LED indicator
int FANLED = 4;  //sets pin 3 for fan LED indicator
long previousMillisFANOFF = 0; 
long previousMillisFANON = 0;
int FANState = LOW;

void setup() {

  lcd.begin(16, 2);  // set up the LCD's number of columns and rows:
  lcd.print(" MORGAN  INDUSTRIES MIST ON    OFF      FAN  ON    OFF");
  pinMode(FAN, OUTPUT);
  pinMode(MIST, OUTPUT);
  pinMode(MISTLED, OUTPUT);
  pinMode(FANLED, OUTPUT);



}

void loop() {


  sensorValue0 = analogRead(sensorPin0)/10; 
  sensorValue1 = analogRead(sensorPin1)/10; 
  sensorValue2 = analogRead(sensorPin2)/10; 
  sensorValue3 = analogRead(sensorPin3)/10;

  unsigned long currentMillis = millis();
  long intervalFANON = sensorValue0*10; //converts sensor value to milliseconds
  long intervalFANOFF = sensorValue2*10; //converts sensor value to milliseconds

  if(currentMillis - previousMillisFANON > intervalFANON) //The following two if statements should make it possible
  {  
    previousMillisFANON = currentMillis;    // save the last time you blinked the LED
    FANState = HIGH;
    digitalWrite(FAN, FANState);
    digitalWrite(FANLED, FANState);
  }

  if(currentMillis - previousMillisFANOFF > intervalFANOFF) 
  {
    previousMillisFANOFF = currentMillis;    // save the last time you blinked the LED
    FANState = LOW;
    digitalWrite(FAN, FANState);
    digitalWrite(FANLED, FANState);  // set the LED with the ledState of the variable:
  }


  lcd.setCursor(9, 1);
  lcd.print("  ");
  lcd.setCursor(8, 1);
  lcd.print(sensorValue0);
  lcd.setCursor(9, 2);
  lcd.print("  ");
  lcd.setCursor(8, 2);
  lcd.print(sensorValue1);
  lcd.setCursor(16, 1);
  lcd.print("  ");
  lcd.setCursor(15, 1);
  lcd.print(sensorValue2);
  lcd.setCursor(16, 2);
  lcd.print("  ");
  lcd.setCursor(15, 2);
  lcd.print(sensorValue3);
}

rodmo1:
There is only a slight amount of flickering now.

The problem is that you're rewriting it on every loop, you may want to consider only writing it if the data changes.

It works great for controlling either the time on or time off coupled together but I am having a heck of a time doing the two values independently. Attached is what I have so far. It does not work very well. I am not getting a steady blink.

Psuedocode would look something like this:

if state is high and it's been longer than the ON interval
  reset the timer
  set state to low
  write the new state

if state us low and it's been longer than the OFF interval
  reset timer
  set state to high
  write the new state

Got it working. Thanks for the help! Here is the code in case you or anyone else is interested. I haven't got around to putting your suggestion regarding the LCD display to work but for now it is good enough.

#include <ArduinoTestSuite.h>
#include <avr_cpunames.h>

/*
 
 
 Demonstrates the use a 16x2 LCD display.  The LiquidCrystal
 library works with all LCD displays that are compatible with the 
 Hitachi HD44780 driver. There are many of them out there, and you
 can usually tell them by the 16-pin interface.
 
 http://www.arduino.cc/en/Tutorial/LiquidCrystal
 */

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
int sensorPin0 = A0;
int sensorPin1 = A1;
int sensorPin2 = A2;
int sensorPin3 = A3;
int sensorValue0 = 0;
int sensorValue00 = 0;
int sensorValue1 = 0;
int sensorValue2 = 0;
int sensorValue3 = 0;
int FAN = 6;      // sets pin 6 for solid state relay
int MIST = 5;  //sets pin 5 for mist solenoid
int MISTLED = 3;  //sets pin 4 for mist LED indicator
int FANLED = 4;  //sets pin 3 for fan LED indicator
long previousMillisFANOFF = 0; 
long previousMillisFANON = 0;
long previousMillisMISTOFF = 0; 
long previousMillisMISTON = 0;
int FANState = LOW;
int FANON = 0;
int FANOFF = 0;
int MISTState = LOW;
int MISTON = 0;
int MISTOFF = 0;

void setup() {

  lcd.begin(16, 2);  // set up the LCD's number of columns and rows:
  lcd.print(" MORGAN  INDUSTRIES MIST ON     OFF     FAN  ON     OFF");
  pinMode(FAN, OUTPUT);
  pinMode(MIST, OUTPUT);
  pinMode(MISTLED, OUTPUT);
  pinMode(FANLED, OUTPUT);



}

void loop() {


  sensorValue0 = analogRead(sensorPin0)/10; 
  sensorValue1 = analogRead(sensorPin1)/10; 
  sensorValue2 = analogRead(sensorPin2)/10; 
  sensorValue3 = analogRead(sensorPin3)/10;

  unsigned long currentMillis = millis();
  long intervalFANON = sensorValue0*10; //converts sensor value to milliseconds
  long intervalFANOFF = sensorValue2*10; //converts sensor value to milliseconds
  long intervalMISTON = sensorValue1*10; //converts sensor value to milliseconds
  long intervalMISTOFF = sensorValue3*10; //converts sensor value to milliseconds


  if(currentMillis - previousMillisFANON > intervalFANON && FANState == HIGH)
  {
    previousMillisFANOFF = currentMillis;    // save the last time you blinked the LED
    FANState = LOW;
    digitalWrite(FAN, FANState);
    digitalWrite(FANLED, FANState);
  }


  if(currentMillis - previousMillisFANOFF > intervalFANOFF && FANState == LOW)
  {
    previousMillisFANON = currentMillis;    // save the last time you blinked the LED
    FANState = HIGH;
    digitalWrite(FAN, FANState);
    digitalWrite(FANLED, FANState);  // set the LED with the ledState of the variable:
  }

  
  
  if(currentMillis - previousMillisMISTON > intervalMISTON && MISTState == HIGH)
  {
    previousMillisMISTOFF = currentMillis;    // save the last time you blinked the LED
    MISTState = LOW;
    digitalWrite(MIST, MISTState);
    digitalWrite(MISTLED, MISTState);
  }


  if(currentMillis - previousMillisMISTOFF > intervalMISTOFF && MISTState == LOW)
  {
    previousMillisMISTON = currentMillis;    // save the last time you blinked the LED
    MISTState = HIGH;
    digitalWrite(MIST, MISTState);
    digitalWrite(MISTLED, MISTState);  // set the LED with the ledState of the variable:
  }

  lcd.setCursor(9, 1);
  lcd.print("  ");
  lcd.setCursor(8, 1);
  lcd.print(sensorValue0);
  lcd.setCursor(9, 2);
  lcd.print("  ");
  lcd.setCursor(8, 2);
  lcd.print(sensorValue1);
  lcd.setCursor(17, 1);
  lcd.print("  ");
  lcd.setCursor(16, 1);
  lcd.print(sensorValue2);
  lcd.setCursor(17, 2);
  lcd.print("  ");
  lcd.setCursor(16, 2);
  lcd.print(sensorValue3);
}