Go Down

Topic: RTC Timer, LED staying on (Read 153 times) previous topic - next topic

dfitz1000

Hi guys,

First off a warning that I am pretty much a beginner with arduino so the way I have coded this may be a bit cumbersome.

Anyway, I am making a controller that will turn an electric blanket on/off either manually or at certain times of day depending on the shift that I am working. I'm using a button to select "manually on", "manually off", "night shift" or "day shift". All of that is working nicely however I am struggling to get the relay (I'm using an LED instead of a relay for testing) to switch off by default.

When I switch on manually the LED comes ON, off manually the LED goes OFF, however in the other states "night shift" and "day shift" the LED remains in the previous state which is ON.

I know that this is because I'm not forcing it off after leaving the "manually on" state, however I cannot seem to come up with a way to make it OFF by default. I can force it off in the loop, but that will just switch it off immediately after the BlanketOn function is run.

Any ideas would be most welcome. Thanks.

Code: [Select]

// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
#include <Wire.h>
#include "RTClib.h"
#include <Time.h>
#include <TimeAlarms.h>
#include <LiquidCrystal.h>

RTC_DS1307 rtc;

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};


// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

// variable to store the state of the led
int ledState;

// a variable to store the state of the button
int buttonState = 0;

// previous state of the button
int lastButtonState = 0;     

// a counter that will increase with button presses
int counter = 0;

// an led will be on pin 10
const int led = 10;

// a button on pin 6
const int buttonPin = 6;

void setup() {
 
  while (!Serial); // for Leonardo/Micro/Zero

  Serial.begin(57600);
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
 
  // led is set as an output
  pinMode(led, OUTPUT);

  // the button is set as an input
  pinMode(buttonPin, INPUT);

  // the counter is set to zero to begin with
  counter = 0;
}

void loop() {

    DateTime now = rtc.now();

    // print to the top line of the LCD display
    lcd.setCursor(0,0);
    lcd.print(now.hour(), DEC);
    lcd.print(':');
    lcd.print(now.minute(), DEC);
   
    // check if the button is pressed or not
    buttonState = digitalRead(buttonPin);

    // move the LCD cursor to the next row
    lcd.setCursor(0, 1);
     
     // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH) {
      // if the current state is LOW then the button went from off to on:
      counter++;     
    }
    }
   
    // 4 different "states" which can be toggled with a button press
    if (counter == 0) {
      lcd.print("OFF");
      BlanketOff();
      //digitalWrite (led, LOW);
      }
   
    else if (counter == 1) {
      lcd.print("ON");
      BlanketOn();
      //digitalWrite (led, HIGH);
      }
   
    else if (counter == 2) {
      lcd.print("6pm Night");
      Alarm.alarmRepeat(6,0,0,BlanketOn);
      Alarm.alarmRepeat(7,30,0,BlanketOff);
      }
   
    else if (counter == 3) {
      lcd.print("6am Day");
      Alarm.alarmRepeat(20,00,0,BlanketOn);
      Alarm.alarmRepeat(22,00,0,BlanketOff);
      }
   
    // reset back to state 0 and start the loop again
    if (counter > 3) {
      counter = 0;
      }
   
    // check if led is on
    ledState = digitalRead (led);
   
    // print ledState to LCD screen
    lcd.setCursor(8, 0);
    if (ledState == 0){
    lcd.print("OFF");}
    else if (ledState == 1){
    lcd.print ("ON");
    }

    // wait 0.5 seconds and clear the screen
    delay(500);
    lcd.clear();
    }

void BlanketOn(){
      digitalWrite (led, HIGH);
      Serial.println("BlanketOn");
      }
void BlanketOff(){
      digitalWrite (led, LOW);
      Serial.println("BlanketOff");
      }

MorganS

You need to add more variables to record if the blanket is off (in manual mode) but it's within the timer period so switching to auto mode would put it on.

I would have your alarm timers call different functions which record that state. Then those functions will call the blanketOn() or blanketOff() as required. Then the user-interface code will need to call other functions which look at the auto/manual state plus the timer state to decide to turn it on or off.

Try to split apart the reading of buttons and timers from the actual output functions. Your main loop should look something like:

Code: [Select]
void loop() {
  checkButtons();
  checkTimers();
  setOutputs();
}
"The problem is in the code you didn't post."

dfitz1000

I sort of get what you are saying, but I am struggling to implement it.

I am looking now at using start and end times rather than alarms, something like is used here.

But I am still finding that "manual mode" and "auto mode" are not entirely separate i.e. the led will stay in it's last "manual" state when entering "auto".

Perhaps there is an elegant if not strictly correct solution in simply swapping the manual ON/OFF making

counter==0 ON and

counter==1 OFF

That way, when the counter ticks over to 2 and "auto mode" is set the led will remain in the counter==1 state (OFF).

MorganS

More variables are cheap. Give them descriptive names. The long names are never downloaded to the Arduino so they don't take up space on the device.

Code: [Select]
bool TheAutoSystemSaysTheThingShouldBeOn = false;
bool TheSystemIsInAutoMode = false;
bool ManualON = true;


Can you tell from those variable names if it's on now? Can you see what the state of the device is going to be when you change TheSystemIsInAutoMode from manual to auto?

Can you see that it could come on "automatically" but it's still in manual mode and still on but changing out of manual mode will then have a different result?
"The problem is in the code you didn't post."

Go Up