Showering system with time-limit of 5 minutes...

Hello,

I’m want to make an timer (or call it an alarm clock) witch starts on the moment you push an button. I make an shouwering-system witch gives the person who want to shower 5 minutes of showering-time. This 5 minutes will start on te moment a pushbutton is pressed. The programming i was thinking on is:

time_t stoptime = DateTime.Minute + (5) // the 5 minutes is the showering-time

if (DateTime.Minute < stoptime)
{
let flow water
}
else
{
stop flowing water
}

I’m not sure to use DateTime.Minute or .now()

Is there anyone who can help me?

Kind regards,

Jorrit

In Arduino land we use millis() instead of dateTime.

To do things as you propose, the Arduino needs a RTC (“real time clock”).

Now… you can ADD rtc’s, but the basic Arduino doesn’t have one.

But for what you want to do, it doesn’t need one.

I’d be inclined to use the millis function to detect the passing of seconds, and have a count-down from 5 x 60 x 60 (the number of seconds in 5 minutes) to be at “the heart” of your program.

You could work directly with millis, but that seems to get tangled up. Nothing wrong with the Arduino’s management of millis… it is programmer confusion that leads to “problems”.

(There’s a nice RTC built into the nuelectronics shield…

http://sheepdogguides.com/arduino/ar3ne1rtc.htm

… only about $16 + p&p from UK)

Someone's got a very similar problem here: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1280929346/0#0

tkbyd,

How can i set an sort of alarm clock with millis()?

long stoptime = millis() + 5000; //5000 ms to use as example

if (millis() < stoptime)
{
do this
}
else
{
do this
}

“millis()” is the way to go, as it’s counting anyway (without extra code).

ie.

  if(button_pushed == HIGH) {
    unsigned long start_time;
    unsigned long current_time;
    unsigned long elapsed_time;

    start_time = millis();

    do {

      current_time = millis();
      elapsed_time = current_time - start_time;

    } 
    while(elapsed_time < 300000); // (5min) * (60s/min) * (1000ms/s)

  }

However, if you really want to use the “DateTime” class, you would need to show us the code for it. I made one called that, but it didn’t have a “now” method.

If you are unsure how to use any class and you can’t find any help on it, you can open the class and look at the code. Have a look at what “minute” is saved as (int, uint16_t, char,…) and when you save current time (in minutes), make the variable the same. You should also have an “if” statement catching the case when minutes >= 55 (as the result in 5 minutes won’t be current time > recorded time in minutes). The value that “now” will return will be in front of the method “now”.

ie.

int now() {
  ...
}

for an integer…

char now() {
  ...
}

for a char…

uint16_t now() {
  ...
}

for an uint16_t (unsigned 16bit integer)…

The way that the integer (for example) is calculated should be in the comments. If not, you’ll need to go through the code and find out for yourself.

Also if you are going to be using the Arduino in the shower, make sure you make it is water-proof :stuck_out_tongue:

There is an coin-machine who gives a pulse and a switch must be set. You can only shower if these two are set.

    if (digitalRead(mvm) == HIGH && digitalRead(mv1) == HIGH)
    {     
      set1 = 1;
    }

Now is my problem: the code below only must work when the code above is true and the 5 minutes of time is nog reached. The time must start when the coin (code above) is trown into the machine.

    if (set1 == 1)
    {
        reading1 = digitalRead(sch1);
      
        // if the input just went from LOW and HIGH and we've waited long enough
        // to ignore any noise on the circuit, toggle the output pin and remember
        // the time
        if (reading1 == HIGH && previous1 == LOW && millis() - time1 > debounce1) {
          if (state1 == HIGH)
            state1 = LOW;
          else
            state1 = HIGH;
            
            time1 = millis();
        }
          
        digitalWrite(klep1, state1);
          
        previous1 = reading1;
    }

I'm already busy for days with this, so if anyone could help me...

Bear in mind that I am pretty much a complete beginner at arduino and the flavour of C that it uses. Assuming I have interpreted what you want correctly, I would do something like this.

const byte coinSlotPin = 4;
const byte buttonPin = 2;
const byte outPin = 7; //connected to your relay
boolean coinReady = 0; //allows for latching of coin op switch

void setup()
{
  pinMode(buttonPin, INPUT);
  pinMode(coinSlotPin, INPUT);
  pinMode(outPin, OUTPUT);
}

void loop()
{
  if (digitalRead(coinSlotPin) == HIGH)  //assuming your coin slot gives a high pulse on activation.
    {
      coinReady = 1; //yup! Latch on.
    }
  
  if (coinReady ==1 && digitalRead(buttonPin)==HIGH)
    {
      runShower();   //wonder what this function does?
    }
}

void runShower()
{
  long nowMillis = millis(); //not sure if I should have initialised this here. Anyone?
  while (millis()-nowMillis < 300000)   // 300000 milliseconds is 5 mins.
    {
      digitalWrite(outPin, HIGH);
    }
  digitalWrite(outPin, LOW); //shower off
  coinReady=0; //reset coin slot latch.
  return;
}

Forget the switch debouncing. Provided you have tied the inputs to ground you shouldn’t get any false positives and the bounce should be irrelevant in this case.

Probably not the thing to say on an Arduino forum but I would not waste a good arduino when you could get away with a much cheaper circuit partswise.
I would have the coin slot latch a thyristor, run that and your push switch through an AND gate triggering a 555 monostable configured for 5 mins, the output running a relay via a beefy transistor.

If you want a buzzer to go off after 5 minutes I have that exact program. It also makes an LED light up.

It doesn’t use a button though, you plug the arduino in to start.

//BUZZER AT 5 MINUTES

int speaker = 9; //the piezo buzzer on pin 9
int tone = 1500;

int LED = 14;



long unsigned Present = 0;


void setup () {

pinMode (speaker, OUTPUT);
Serial.begin(9600);
pinMode (LED, OUTPUT);

}

void loop ()
{
  
Present = millis();
if (Present > 270000 && Present < 270200){ // 5 MINUTES, buzzes for .2 seconds
digitalWrite (speaker, HIGH);
delayMicroseconds (tone / 2);
digitalWrite (speaker, LOW);
delayMicroseconds (tone / 2);
tone = 1500;
tone = map(tone, 0, 1023, 1000, 5000);

digitalWrite(LED, HIGH);


} else { 
  digitalWrite(speaker, LOW);
}



}

Hey there:

I would split the program into sections that makes sure that all the parts are working.

You can then get creative with functions…

/***********************************************/
//inputs
const byte _coin_read = 2;
const byte _button_read = 3;

//output
const byte _shower_write = 4; //connected to your relay
/***********************************************/
//flags
uint8_t _coin_flag;
uint8_t _button_flag;
/***********************************************/
//time keepers
unsigned long start_time;
unsigned long current_time;
unsigned long elapsed_time;

/***********************************************/
void setup() {

  //setup pin I/O
  pinMode(_coin_read, INPUT);
  pinMode(_button_read, INPUT);
  pinMode(_shower_write, OUTPUT);

}
/***********************************************/
void loop () {
/***********************************************/
  //reset everything
  digitalWrite(_shower_write, LOW);  
  _button_flag = _coin_flag = LOW;
/***********************************************/
  //if sensed...
  if(digitalRead(_coin_read) == HIGH) {

    //wait for bouncing to stop...
    delay(20);

    //if still sensed, set flag...
    if(digitalRead(_coin_read) == HIGH) {
      _coin_flag = HIGH;
    }
  }
/***********************************************/
  //if sensed...
  if(digitalRead(_button_read) == HIGH) {

    //wait for bouncing to stop...
    delay(20);

    //if still sensed, set flag and wait for 
    //button to be released...
    while(digitalRead(_button_read) == HIGH) {
      _button_flag = HIGH;
    }
  }
/***********************************************/
  //If both the conditions for "shower on" are true...
  if((_button_flag == HIGH) && (_coin_flag == HIGH)) {

    //record start time...
    start_time = millis();

    //turn on shower
    digitalWrite(_shower_write, HIGH);  

    //Continuosly check for finish time...
    do {

      current_time = millis();
      elapsed_time = current_time - start_time;

    }
    while(elapsed_time < 300000); // (5min) * (60s/min) * (1000ms/s)   

  }//end of if...
  
}//end of loop()...

Thanx a lot for your help everybody so far, but my problem is the 5 minutes of time to set up. I can’t get anything like that working in my current code. As soon as someone throws a coin in the machine, the may only have 5 minutes of showering-time. Is there someone who can help me coding a timer? It doens’t make a difference for me how it works, i just need a timer.

If it makes no difference how the timer works, then just use delay() to wait for 5 minutes after the water is turned on. Then, turn it off.

If it does matter, then using millis() to create a timer is pretty simple. On each pass through loop, see if coins have been inserted (does adding more coins extend the shower time?). If so, set a flag, coinsEntered, to true. If coins have been inserted and coinsEntered is true, you would set (or reset) the water on time (showerTime).

See if the start button has been pushed. If so, set a flag startPressed to true.

See if coinsEntered and startPressed are both true. If so, set a flag, waterRunning to true. Turn the water on. Set the time that the water was turned on, waterOn = millis().

If the water is running, see if its time to turn it off (now - waterOn time exceeds showerTime). If so, turn the water off, set coinsEntered to false, set waterOn to false, and set startPressed to false.

If it is not time to turn the water off, there is nothing to do - no else clause is needed.

This approach allows for additional coins to extend the time that the water is on.

Use unsigned long for all time-related variables (waterOn, showerTime, etc.)

Delay() would be the most basic thing if that's what you want.

if (coin inserted){

  //turn water on here

 delay(300000);//5 minutes

 //turn water off here
  
}

@ Jorritmans:

but my problem is the 5 minutes of time to set up. I can't get anything like that working in my current code. As soon as someone throws a coin in the machine, the may only have 5 minutes of showering-time. Is there someone who can help me coding a timer?

I think that you need to be specific about what you don't like about the code that I have gave you. The code that I gave you is a timer that only starts after a coin has been inserted and the button has been pushed. I'm trying to help you, but it seemed (correct me if I am wrong) that you didn't even look at the code I gave you?...

@InvalidApple This is one reason why just giving someone a block of code doesn't work.

Describing HOW to code the solution, unless you have a COMPLETE solution gives the OP something to try, something to learn, and a sense of accomplishment when they get code working.

Providing the OP with a code snippet that they have to figure out where to insert in code that is not well organized, indented properly, and commented correctly isn't teaching them anything.

It's great that you always seem to have some code that does what the poster wants, but as a first reply giving that code to the OP is not always the best thing to do.

Just my humble opinion.

@PaulS Your opinion seems to be more than right, and I will try to do this in the future.

I'm sorry, I did read all of the reply's and appreciate it.

I will explain my problem better.

The part of the code for the coin-machine and cabin-switch is been written already by myself. Now is my issue:

A person pushes a pulseswitch for turning on the shower, and with this same pulseswitch the person can turn of the shower, shown in the code below:

int state1 = LOW;      // the current state of the output pin
int reading1;           // the current reading from the input pin
int previous1 = LOW;    // the previous reading from the input pin


long time1 = 0;         // the last time the output pin was toggled
long debounce1 = 200;   // the debounce time, increase if the output flickers
    if (digitalRead(mvm) == HIGH) // the coinmachine
    {
      if (digitalRead(mv1) == HIGH) // the switchbutton for the specific shower
      {
        set1 = 1;
      }

    if (set1 == 1)
    {
        reading1 = digitalRead(sch1);
      
        // if the input just went from LOW and HIGH and we've waited long enough
        // to ignore any noise on the circuit, toggle the output pin and remember
        // the time
        if (reading1 == HIGH && previous1 == LOW && millis() - time1 > debounce1) {
          if (state1 == HIGH)
            state1 = LOW;
          else
            state1 = HIGH;
            
            time1 = millis();
        }
          
        digitalWrite(klep1, state1); // set valve to state
          
        previous1 = reading1;
    }

And now my problem:

As soon as someone throws a coin in the machine and so the shower is set to work, a timer has to count from 0 till 5 minutes or countdown from 5 to 0. After the time is runned out, the shower will not give anymore water and they have to throw another coin into the coin-machine.

The system works perfect as far as I am now, but I really need the timer, or else the people can shower as long as the want. The difficulty is in the pulseswitch I supose.

So the coin-machine and the showeringsystem works, but I need a timer. Also a thing that makes it more difficult is that there are 3 showers wich all work thesame. The code above is repeated 3 times in my entire code. I hope you understand my problem, and I'm sorry for my bad English.

Yes, we understand your problem. There was nothing wrong with your English.

You want someone else to write the code for you.

You've been given plenty of information about how to implement a timer, been asked several questions, and been given suggestions on how to better organize the code. Yet, you keep posting the same code fragment, and making no attempt to even add a comment that says "// Start timing".

Your previous post is the first that mentions that there are three showers. Nice to add details like this late in the dialog.

Are there three coin machines? Or just one? Is there a switch for each shower, or just one?

If there are 3 showers, 3 coin machines, and 3 "start the water" switches, why are there no arrays in sight?

So, ok...

You have 3 digital inputs in your code:

  • mvm - the coinmachine
  • mv1 - the switchbutton for the specific shower
  • sch1v - ????

... And one output

  • klep1 - output to valve

None of your inputs actually use de-bouncing:

    if (digitalRead(mvm) == HIGH) // the coinmachine
    {
      if (digitalRead(mv1) == HIGH) // the switchbutton for the specific shower
      {
        set1 = 1;
      }

You only check the button when the coin input is high, which will probably go against you when you extend the functionality. If you wanted to not do that, you would have to put in another "}" at the end of the code above. In fact, because the "{" does not equal the amount of "}" in the code you posted, I'm guessing that this was your intention.


if (reading1 == HIGH && previous1 == LOW && millis() - time1 > debounce1) {

I don't think this will ever work, because the first time you go though "millis() - time1 > debounce1" will be false and the next time through "previous1 == LOW" will be false.


I think that the only way forward is to sit down and type up some pseudo code.

ie.

start check to see if coin has been inserted if so, check button 1 if button 1 is on and timer 1 off turn timer 1 on turn valve 1 on check button 2 if button 2 is on and timer 2 off turn timer 2 on turn valve 1 on

... and so on

By writing out what you want your code to do step by step, you can then quite easily see if your "coding strategy" is going to work; you may be able to spot some places where you could insert a loop; or see if there are any redundancies in what you are doing.


If you have any questions on writing some pseudo, I'm sure that we would have no problems in answering them.

The coin-machine part and the pulseswitch of the code works perfect. (I forgot to close the if)

I'll explain my idea in Pseude code;

mvm = main coin-detector (connects 2 wires) mv1 = choiseswitch for shower 1 (connects 2 wires) mv2 = choiseswitch for shower 2 (connects 2 wires) mv3 = choiseswitch for shower 3 (connects 2 wires)

set1 = 1 if mvm == high and choiseswitch == mv1 set2 = 1 if mvm == high and choiseswitch == mv2 set3 = 1 if mvm == high and choiseswitch == mv3

sch1 = pulseswitch for setting valve 1 open or closed sch2 = pulseswitch for setting valve 2 open or closed sch3 = pulseswitch for setting valve 3 open or closed

So..

void loop()

if (mvm == HIGH) // is only during a short time high, so this sets (set 1, 2 or 3 (depends on the choiseswitch on the row here below)) to 1 if (mv1 == HIGH) set timer on 5 minutes

if (set1 == 1) if (timer != 5 minutes) if (sch1 == high) open valve else // belongs to the switch sch1 close valve else // belongs to the if for the timer set 1 = 0;

// the valve can be set on and off during the 5 minutes of showering-time with a pulseswitch. (ie. for soaping in)

// the if code above in the loop() is repeated 3 times. For each shower 1 time.

// The the problem is in the timer. I don't get anything working in combination with the pulseswitch. I tried a lot of suggestions but in some cases the showers can't be stopped anymore or the are not working at all.

If there is something not entirely clear, please say so..