HOME  >>  ARDUINO HOW TO MENU >>  Delicious.Com Bookmark this on Delicious   Recommend to StumbleUpon

From concept to Completed System

Hallway Monitor: Example of system development

This tutorial will go through how I started with an idea and ended with a finished system, which I am calling my Hallway Monitor.

The point is not so much to provide you with the software and modest hardware to accomplish a task... although it also does that... but as to let you "sit at my elbow", and see how Arduino (or Pi, etc) projects are done, when you've had some experience.

It isn't polished. But it is free. And comes with downloadable sourcecode. (That's a .zip file, with an Arduino .ino file in it.) The final code works... but I haven't in every case ironed out bugs in the code leading to the final code.

Remeber: This is meant as a chance to learn about programming. It isn't (primarily) to "deliver" a "final product"... but there is good code, and programming practices, within what follows, which I hope you will want to incorporate in your own work.

The nominal objective

At the end of the day, when I leave my workroom, I am often confronted with a nuisance.

In the workroom, I usually have the lights on, and always have the door between it and the hallway it opens off of closed.

When I've worked from the time the sun is up into the darkness of the night, when I leave the workroom, I have to negotiate a stretch of hall in the dark... there is no switch for the hall light near the door to the workroom.

I've tried various solutions for the problem over the years. Trust me. For a variety of reasons, no answer was found until I went to the "extremes" of the solution presented here.

And, credit where due: Although I'd half thought of solving the problem with an Arduino, it wasn't until the article in the UK magazine Computer Shopper, the issue "for" December 14, I think, with just such a project that I Got Going, and fixed my "stumbling in the dark" problem as follows.

First steps

Always, always, think long and hard about where you are going before you start connecting hardware or writing software.

What do you want the system to do? Have you thought of EVERYTHING it ought, at least eventually, to do? And if you aren't building in all the features you want in the final product from the beginning, have you thought carefully about the stages you will break the project into.

In my case... basic needs:

A light to switch on in the hall when I go into it,
    AND it is dark at the time.

Light to switch itself off after a suitable interval.

... and, eventually,....

When someone "seen" going through door, trigger a
     security camera; take picture of the person

We'll look at the eventual want first, get it out of the way. The subject is beyond the scope of this article, but leaving that out would "dumb down" what I am presenting here to an academic article, instead of it being a "real world" example of design.

For years I've been playing with "automatic cameras", primarily in an attempt to capture pictures of wildlife. (The best answer is a Bushnell Trophy Cam... but where's the fun in just buying an answer?)

For the needs of the Hallway Monitor project, all we really need to know is that one of my cameras can be "told" to take a picture just by making a wire hold 12v for a moment, and then putting the voltage in that wire back to 0 volts, which is where it is normally.

That's it for the camera, for now.

Now we'll look again at the basic system requirements. So far, we have... which is a good starting point, overlooked by many, a fairly concise but complete statement of what we want it to do (above).

Making that statement accurate and complete is more complicated than you might think. It takes wisdom. And you get wisdom from experience. And experience is what you get before you have wisdom. I've done many, many projects badly because I didn't have a good "What It Will Do" statement at the start of the project. Thus, making those early projects took far longer than it should have, they were never really fully what I eventually realized I'd wanted them to do. I went down blind alleys, and had to rework things I thought were "done". Etc. Have A PLAN!

Once you know the WHAT of what you want, go through it, and think about the how...

"A light to switch on..."

This will need... duh... a light! What sort of light? (That will affect what is needed to turn it on and off, etc.) I decided on a bright LED, because I don't like working with household electricity. I was a firefighter for a while. Take my word for it: Household electricity needs lots of respect an knowledge.

The light only has to be enough to see me safely down the hall to where the hall light switches are, so the LED will be fine.

"Switch on when I go into the hall"

I am fortunate. For my wants, one of the resources available is the door between office and hall, and the fact that it is always closed, unless someone is passing through it. (The house has heating issues in the winter, and cooling and dehumidifying issues in the summer.)

I could use a PIR to detect the presence of someone near the door. But why do complicated when simple is available? A reed switch on the door frame, and a magnet on the door are simpler and less expensive than a PIR. The one downside is that they won't distinguish between someone entering the workroom and someone leaving it. But having thought about that, I can live with the consequences.

"Switch on the light IF it is dark at the time."

Hmmm... Dark in the hallway? Dark outside? Almost the same thing. Sometimes, of course, the hallway lights are on. But if I am going to hook up a light level sensor, I can get it to do two things for me. (For the 50 cents a simple sensor costs, it wouldn't kill me to have two sensors, but that would be too easy.)

I have a weather logging system. For a long time, I've wanted to add something to that to log the (outdoor) light levels. It was easy to add that to the weather logging system, and incorporate into that a digital output which says "it is day" or "it is night", based on light levels. (Making a day/ night indicator based on time of day CAN be done, but it is fraught with "stuff" I didn't want to get into.

Now, I hear you saying, "The heck with this... I don't want to have to build a weather monitor AND a hallway light switcher!". Fear not. Put that worry to one side. It will be answered... later. For now: We need a way to tell if the hall light should go on if someone goes through the door.

I said earlier that I had a statement of my wants. Well, as I thought about the "stuff" they would entail, it occurred to me that I sometimes forget to shut the door after passing through it. If I am building a system which has to know when the door is open, and it is a door I don't want open for protracted periods, then I could easily add a little beeper to beep at me if I left the door open. But so much better to add new wants at this stage, when you haven't started building the software and hardware.

Eventually, that beeper will have additional features. And they have to be pinned down before hardware building/ software writing begin!

There's a software issue to address in the planning stage, too, but first let's think about....

What hardware needs do my wants imply?

We've sort of answered this. But a "sort of" answer isn't good. During the planning stage, do a good, clear, complete answer to "What are my hardware needs?"

For what we want, we need the following. "Input" and "output": Relative to the Arduino. The "Take Picture" OUTPUT of the Arduino will be the "Take Picture" INPUT of the camera it drives, won't it?

Door open sensor: already covered.

Hallway dark: This can be placed in various places, and done various ways. Some will boil down to a digital signal, others to an analog signal. We'll see before long that I don't much care, at this stage, but only because I know that I can handle either. I have a separate page on ways to sense light levels, if you want to know more on that subject.<

Turn on hallway light: I know I said I didn't need a "bright" light, but a simple LED connected directly to the Arduino will probably not be enough. But a low voltage "bright" LED (or tow or three of them), connected to even 5v will probably "do", and that power supply can be controlled by a simple transistor circuit, so that the Arduino's capacity to drive high current loads isn't exceeded. This is the kind of detail that you need to think about. Do you know how to do exactly what you are thinking of doing to achieve gratification of each of your wants?

Beeper: I am planning to use one of the wonderful little low power, self contained, piezo sounders which run on 5v. Power on: They emit an ongoing tone. Power off: They go silent. When buying, look for "self-oscillating" or similar. There are "piezo elements" for sale out there, which are nothing more than something vaguely equivalent to a small speaker. What I am going to use is "speaker"+ amplifier+ circuit to make a tone.

Tell camera to take picture: This will be done by using one pin of the Arduino to send a voltage (high or low) to the base of a transistor which will "switch" on and off a 12v supply to the wire going to the camera's "take picture" input. TAKE CARE: NOT ALL "inputs" are VOLTAGE driven. Sometimes, the input only wants a SWITCH connected to it. But my camera needs to see a voltage. And I've just explained how I will provide that.

Plan, plan, plan. Don't start the hardware and software work until you are confident that you WILL be able to solve all the "bits" of what your wants dictate.

If you are a little uncertain about your ability to solve one of the subtasks, go ahead and build hardware and software to deal with JUST THAT. For instance, if I was uncertain about whether I could make a suitable light, I might set up the light circuit I thought might work, and see first if applying 5 volts at the right place does make it work. And if that worked, and I was still a little worried, I'd put an button on an Arduino, connect my "light" circuit to an output of the Arduino, and see if I could make the world's most expensive flashlight: Press the button= light on; release button= light off.

Those are our hardware needs considered. If we can't supply those needs, we can't build the system... as currently envisioned... to assuage our "light in the hallway" wants.

If you can't supply one of the needs, you can solve the problem two ways:

But!.. do it (learn or re-design) it now... before you get into hardware building or software writing!

Still not ready.

Sorry! We're still not ready to start making the Hallway Monitor. We've planned. We've made sure we can deal with the hardware needs. But we have a software need. We said that our system should...

Switch light off after a suitable interval.

Build a really simple little Arduino "thing", just to be sure you can deal with that. It will have a push button input and an LED output. When you press the button... briefly... the LED comes on. And stays on, even after you release the button. For, say, 5 seconds.

Okay... you can do that? Then, thank heavens, you are almost ready to start building the Hallway Monitor! "At last", you mutter. Trust me: My "plan first", and what that means, is very, very VERY frequently underestimated. And starting too quickly ALWAYS ends in tears.

One last bit of planning: Do a drawing... and make it part of a system, so that you can find it again later... which shows which pins you will be using for all of the inputs and outputs of which we have spoken.

Build the Hallway Monitor

Start a new Arduino program ("sketch"). Give yourself a blank page, to get things started.

Early in code, create the following globals....

#define bIsDoorOpenSensorPin 8//no ; here.
#define bHallwayLightPin 4//no ; here.

(I've set those to 8 and 4 because on the hardware side, I am going to wire the sensor that detects if the door is open to pin 8, and the output to control the hallway light to pin 4. These are the only place in my program where 8 and 4 (in this context) will appear.)

Anywhere else in the program that I want to refer to "the pin connected to the 'is the door open' sensor", I will use bIsDoorOpenSensorPin. Not only is this more informative than "8", but also, if I want to adapt this program, but put the door sensor on a different pin, I only have to make one change. That is easier than finding all the relevant 8s... but it is also, and this is the big advantage, more reliable. If I've remembered to always use bIsDoorOpenSensorPin, then with one change, I know I've made all the necessary changes, not missed any. (I will do similar things with other pin assignments.)

Now connect a simple pushbutton to pin 8 and an LED (with resistor) to pin 4. And write the following, so that when the button is pressed, the LED goes on, and when released, it goes off....

void setup()
{
//Input pins
  pinMode(bIsDoorOpenSensorPin,INPUT);
  digitalWrite(bIsDoorOpenSensorPin,HIGH);// "Connect"
     //internal pull up.

//Output pins
  pinMode(bHallwayLightPin,OUTPUT);
}//end of setup()

void loop()
{
 if (digitalRead(bIsDoorOpenSensorPin)==HIGH)
   {
    digitalWrite(bHallwayLightPin,HIGH);
   }
  else
   {
    digitalWrite(bHallwayLightPin,LOW);
   };
}//end of loop()

That should at least almost work. Press the button, and the LED goes on. Release it, and the LED goes off. Or vice versa. At this point, I don't care. (You'll see why, in a moment, I hope.)

A little newbie gotcha lurks even in such a simple program: Do not put a semicolon after the } which comes before the "else". Some of the others aren't necessary, but it is a good idea to use them, even the "extra" ones, where I've used them. I.e. before the }s. (It is too easy to add something inside the {}s, as the last line inside them, and forget to insert the ; after what was the last line inside the {}s.)

And, if that's ALL you want to do, that program is probably okay. But we're going to make things "complicated", along the road to being able to make big things which would be very hard to make quickly and easily, if you didn't use the trick I am about to introduce.

Wouldn't it be nice, if instead of...

digitalWrite(bHallwayLightPin,HIGH);

...we could use...

HallwayLightOn()

And if instead of...

digitalWrite(bHallwayLightPin,LOW);

...we could use...

HallwayLightOff()

In fact, while we are at it, wouldn't it be nice if there were an...

HallwayLightOnOff(0)
... and a...
HallwayLightOnOff(1)

to, respectively, turn the LED off and on.

Well, there isn't a "HallwayLightOnOff" function built into the Arduino.... but we can make one. Once we've done that, and made a boIsDoorOpen() function, loop() becomes....

void loop()
{
 if (boIsDoorOpen()==true)
   {
    HallwayLightOnOff(1)
   }
  else
   {
    HallwayLightOnOff(0);
   };
}//end of loop()

Don't you think that the code just before this paragraph is easier to read than the earlier version? Yes, you have to learn how to create functions... but it is worth it!!

As I intimated earlier... this is probably overkill, if you just want to write the simple expensive flashlight we have so far... but keep reading. That is NOT all we are going to do, and when we've got everything "going", making it easier to read will become more important!

(Yes, you can simplify...

if (boIsDoorOpen()==true)

... down to

if (boIsDoorOpen())

... and ordinarily, I would. But I wanted to mention the following...

If you write...

if (boIsDoorOpen()=0)

...instead of...

if (boIsDoorOpen()==0)

... the program won't compile. Use "==" when asking the program to see if two things are equal. (The equals sign on its own assigns what is on the right of it to the variable on the left of it.)

Here's the code you need to make the "new word" "boIsDoorOpen()"...

boolean boIsDoorOpen()//Returns true when door is open
{
 if (digitalRead(bIsDoorOpenSensorPin)==HIGH)
  {
     return true;
  }//no ; here
 else
  {
     return false;
  };//end else
}//end boIsDoorOpen

Moving on.... here's the code for "HallwayLightOnOff()"...

void HallwayLightOnOff(byte bOnOff)//Turn hallway light
   //on if 1 passed, off if zero passed
   {
   if (bOnOff==1)
   {
   digitalWrite(bHallwayLightPin,HIGH);
   }
   else
   {
   digitalWrite(bHallwayLightPin,LOW);
   }
   }//end HallwayLightOnOff

Newbie gotcha, class A, alert. Besides being careful to double the equals sign, as explained above...

If you write...

if (boIsDoorOpen==0)

...instead of...

if (boIsDoorOpen()==0)

... the program will compile and upload without complaint... it just won't work as you want it to. Be sure to include the "()" after the boIsDoorOpen.

Whew! Lots of tedious "details"... but master them, and you can forget about OTHER details, and concentrate on the big picture while building a big project!

A word about the "argument", bOnOff, of the "subroutine" HallwayLightOnOff()...

I haven't found a way to make such variable local. In other words, there can only be one bOnOff in my program. I must be missing something, because in many languages, if you create a variable like this, it is "not known" elsewhere in the program, which is a Good Thing for a variety of reasons.

Another thing: It "shouldn't" matter, but I find, for whatever reason, that sometimes it seems to: Put your code for loop() at the end of the program, and your code for setup() just before it. In general, if a subroutine uses something, define that "something" earlier in the program.

So... our "simple flashlight" is now just...

void loop()
{
 if (boIsDoorOpen()) //Returns "true", if door open
   {
    HallwayLightOnOff(1) //Turn light on.
   }
  else
   {
    HallwayLightOnOff(0);
   };
}//end of loop()

That's the heart of our program. It will also need the "bits" that make that work, of course.

Remember a long time ago, I said that the flashlight might be working "backwards"? Maybe the LED is on when button is not pressed?

Exactly how the flashlight behaves with the code I've given will depend on how you wired up the LED, how you wired up the button.

I don't care how you wired them! And don't change it! And don't change what's in loop(). But if your "flashlight" is working backwards, fix it. (And if it isn't, break it!)... Simply by making changes inside bIsDoorOpen() and HallwayLightOnOff().

In this simple case, I doubt your flashlight was working backwards... but with more complex input or output devices, you'll often find them "working backwards". No problem. Get rid of the "problems" in the little subroutines servicing the devices, so that while you are programming, you just say It(1) to turn "It" on, and It(0) to turn "It" off.

Now we're "cooking"

Right! I hope you will feel that things are beginning to move along, now that we have some foundations laid?

Note that I haven't connected my "real" hallway light yet. Nor the "real" is- the- door- open sensor. As long as I am confident that my "stand ins" can be replaced simply, it is better to work with what I have, while developing the final product. I don't, for instance, want to cross the room, open and close the door each time I want to test some new iteration of the program, do I? Often in working on projects, using "stand-ins" makes sense.

We have a stand-in hallway light and a stand-in is- door- open sensor. At this point, we can attach our "final" piezo sounder... or an LED, if we don't want to listen to the sounder. We also want to attach something to the "is it day?" input. At this stage, I would suggest a toggle switch. Or, if you keep it close to the desk where you are working, you might want to connect your photo-sensor, if you aren't using a digital output from another Arduino, as is unlikely, although it is what I will eventually use.

If the Arduino you are using has an LED (and resistor) on the board, on pin 13, as most do, you might want to add a feature to the program which we have not previously discussed: When the system "thinks" it is day, the on-board LED should go on. (This gives you a quick check about what it "thinks" about whether it is day or night, if your system is mis-behaving.)

REGARDLESS of the actual inputs and outputs you wire to your system just now... and, in fact, that is actually the point, in some ways, you can now write the following subroutines. The routines will require, up at the start of the code, three more constants. (The bThinksDayPin isn't necessary if you don't want to turn the on-board LED on to signal "thinks day".)

//Input pin
#define bDaySensorPin 9 //No ; here

//Output pins
#define bBeepPin 5 //No ; here
#define bThinksDayPin 13 //No ; here

Also, in setup, you need the usual pinMode lines, and, where needed, digitalWrite... lines to connect the internal pull up resistors on inputs.

And, with those in place, you can add two more "words" to your Arduino's "vocabulary" with the following. They are really very similar to the ones we did a little while back...

//SUBROUTINE for boIsItDay...

void SayWhetherNightOrDay(byte bDayIfOne)
  //This is NOT the SENSE day/night function... it
  //  is merely a routine to REPORT what has been
  //  sensed.
  //Pass 1 to this if you want Arduino to say it is day.
  //Give indication from Arduino whether it thinks
  //  it is presently night or day (based on light.
  {
   if (bDayIfOne==1)
   {
   digitalWrite(bThinksDayPin,HIGH);
   }
   else
   {
   digitalWrite(bThinksDayPin,LOW);
   }
   }//end SayWhetherNightOrDay

//*************************************************
boolean boIsItDay() /*Returns true if daytime, false if night
   (Based on light levels)
   This can be written two ways (at least), depending
   on what resources are available. In my case, I had
   a second Arduino monitoring light levels already.
   It was a simple matter to get it to drive an output
   (on it) to feed an input on the Arduino HallwayLight
   is running on. Alternatively, the function could use
   one of the Arduino's analog inputs to monitor a light
   sensor.
   */
/*For alternate "is it day" function...
const int MakeLightOnDOutTrue=2;//If greater than this.*/

{
  if (digitalRead(bDaySensorPin)==LOW)
    {SayWhetherNightOrDay(1);
     return true;
   }//no ; here
   else
    {SayWhetherNightOrDay(0);
     return false;
    }//end of else

/*Scrap from another program, showing the basics of using
analog input to determine day/night. Names will need changes
  int iAn0;
            if (iAn0>MakeLightOnDOutTrue)
    {SayWhetherNightOrDay((1);
     return true;
   }//no ; here
   else
    {SayWhetherNightOrDay(0);
     return false;
    }//end of else
*/
}//end boIsItDay()


//*********************************
void BeepOnOff(byte bBeepOnOff)//Turn piezo sounder on/off
   //on if 1 passed, off if zero passed
   {
   if (bBeepOnOff==1)
   {
   digitalWrite(bBeepPin,HIGH);
   }
   else
   {
   digitalWrite(bBeepPin,LOW);
   }
   }//end BeepOnOff

Before we delve into the details of the above, a simple point. When I established the bDaySensorPin constant, I would have added a comment, thus...

#define bDaySensorPin 9// No ; here. See bIsItDay function

Okay... the first thing you see in the new code is

//SUBROUTINE for boIsItDay...

void SayWhetherNightOrDay(byte bDayIfOne)

The comment tells us a bit about how SayWetherNightOrDay is going to be used. In many languages, if a subroutine is only "of interest" to another subroutine, you can declare the subordinate subroutine within the subroutine that uses it. I don't think the Arduino environment allows for this. (I couldn't figure out how to do it, in any case!)

All SayWhether... does it to turn on an LED, if passed a 1, turn it off if passed a zero. The LED will probably be the one that is in the Arduino's PCB, connected to pin 13... but that can be changed simply by changing the earlier line that says...

const byte bThinksDayPin=13;

Then we have....

boolean boIsItDay()

That is very like boIsDoorOpen() which we looked at earlier. It returns "true" if it is day (by light levels, either directly, or indirectly), and "false" if it is night.

As presented, it will work fine with a toggle switch standing in. And if you want to connect a light dependent resistor in due course, the code you need is there, in the commented out section. To use that, note that you will create another constant....

#define MakeLightOnDOutTrue 300//No ; here

On the one hand, having it within the subroutine has a certain logic. But on the other hand, making it a global, and putting it near the head of the code makes it easier to find, if you need to tweak the value.

Which only leaves....

BeepOnOff()

... which is basically just LedOnOff() again. (You could, in fact, probably combine the two into a single subroutine with an additional parameter or two passed... but it is hardly worth the trouble. Having the two routines, with the names shown, makes knowing what the subroutine is going to do much more obvious.)

With our new hardware and subroutines...

With the hardware and subroutines we have added, we can create a pretty good attempt at what we said we wanted. The following would be pretty usable, even if it isn't "the final version" by quite a long way...

void loop()
{
 if (boIsDoorOpen()=false)
   {//Door is NOT open...
     BeepOnOff(0);
     HallwayLightOnOff(0);
   }//end of dealing with "Door is NOT open"
 else
   {//Door IS open...
     BeepOnOff(1);//turn beep on, day or night. Also...
     if (boIsItDay()==false)//... if ALSO it is night-time...
          {HallwayLightOnOff(1);}
          }//End of dealing with case when door IS open.
}//end of loop()

That code turns the buzzer on whenever the door is open, off when closed. And the LED also comes on while the door is open IF it is night. And I hope the code is quite easy to read, understand.

It is easier to understand than it would be, if, for instance, instead of "boIsItDay()" we had, here, all the code which is "hidden away" inside the definition of what computer does when it is instructed to execute the bIsItDay() subroutine!

The biggest problem with the above "solution" is that the light goes off again when we close the door. We were given a glimpse of what was in the hallway (night-time)... but left to rely on our memory of the same to get from door to switches!

But, with our subroutines, we can write something readable which leaves the LED on for a bit...

Hallway Monitor with delayed "LED Off"

To make the LED stay on for a bit after the door is closed, first we create another variable, iTimeOnLeft. And we also set up a constant, iTimeToStayOn, at the top of the program, which will "set" how long the LED will stay on for. At this stage, both use arbitrary units. Setting iTimeToStayOn to 5 won't mean the light stays on for 5 seconds. At this stage, the unit will be very small. Set the constant to 300, for now.

We need to put...

int iTimeOnLeft;

...into the code somewhere. As want the value in the variable to persist between iterations of loop(), we define it outside of loop(); it is a global variable, and might as well be declared just after the line where we set up the constant iTimeToStayOn.

Here is how we use those. Note the delay(5); which has been added right at the bottom of loop()...

void loop()
{
 if (boIsDoorOpen()==false)
   {//Door is NOT open...
     BeepOnOff(0);
     iTimeOnLeft=iTimeOnLeft-1;
     if (iTimeOnLeft==0)
           {
             HallwayLightOnOff(0);
             iTimeOnLeft=1;
           };
   }//end of dealing with "Door is NOT open"
 else
   {//Door IS open...
     iTimeOnLeft=iTimeToStayOn;
     BeepOnOff(1);//turn beep on, day or night. Also...
     if (boIsItDay()==false)//... if ALSO it is night-time...
          {HallwayLightOnOff(1);}
          }//End of dealing with case when door IS open.
 delay(5);
 }//end of loop()

Note the..

iTimeOnLeft=1;

... deep in that code. It is there so that iTimeOnLeft will never equal zero at a time when you are trying to subtract 1 from it.

As required by Alice: Better and better...

The buzzer being on continuously while the door is open is tedious. So let's fix that.

This is just the sort of place that "things" often unravel. Notice we are getting into the realms of the unplanned.

We've already put a delay(5) into loop(), to stop it repeating at "computer time" rates. Although we might pursue other avenues to nirvana, we're going to take a Design Decision here, and try to stick to it: We want loop to complete many, many times per second. If, say, we put delay(1000) into loop(), we could make it repeat only about once per second. When you've slowed things down that far, lagginess becomes an issue. For instance, you open the door, expecting the light to come on (if the hallway is dark). It does... but it takes up to a very perceptible second to do so, if we have put delay(1000) into loop(), which may SEEM like a good thing to do. It does make having certain things happen easier... but it is a Bad Idea.

So what do we do instead?

Introduce two new variables.

Once upon a time, when computers were steam driven, and Real Men wrote machine code, another variable was fought tooth and nail. Today, the cost is primarily that it complicates your code, so do it carefully.

Our new variables will be called bLoopExecutions and iTenthsSinceOpen. The first will count executions of the loop() routine, and be set back to zero repeatedly. The second will (roughly) count tenths of seconds since the door was last opened, based on how many times the loop() subroutine has executed... so we need to keep the time to execute loop(), whatever path is taken due to various "if" statements fairly constant. Somewhat like iTimeOnLeft, we will do something to prevent it from becoming too big. (With iTimeOnLeft we did something to keep it from becoming too small... but we were counting DOWN with iTimeOnLeft, whereas with iTenthsSinceOpen we will be counting up.

We'll also introduce a new constant... bLoopsPerTenthSec... which will hold the number of times loop() executes in one tenth of a second.

We'll put it into the program first. For the moment, iTenthsSinceOpen won't count tenths of seconds since the last opening of the door... it will merely count tenths of seconds since program was started. Then we will use it for "stuff"....

Added at top...

unsigned int iTenthsSinceOpen;
byte bLoopExecutions;
const byte bLoopsPerTenthSec=25;

Added to setup()...

iTenthsSinceOpen=0;
bLoopExecutions=0;

And all of the new loop()...

void loop()
{
 bLoopExecutions=bLoopExecutions+1;//(Yes, I know, you can
   //just say "++bLoopExecutions;" But! Is that newbie friendly?
     if (bLoopExecutions==bLoopsPerTenthSec)
       {
        bLoopExecutions=0;
        iTenthsSinceOpen=iTenthsSinceOpen+1;
        if (iTenthsSinceOpen==65534)
                {iTenthsSinceOpen=65533;};
       };
 if (boIsDoorOpen()==false)
   {//Door is NOT open...
     BeepOnOff(0);
     iTimeOnLeft=iTimeOnLeft-1;
     if (iTimeOnLeft==0)
           {
             HallwayLightOnOff(0);
             iTimeOnLeft=1;
           };
   }//end of dealing with "Door is NOT open"
 else
   {//Door IS open...
     iTimeOnLeft=iTimeToStayOn;
     BeepOnOff(1);//turn beep on, day or night. Also...
     if (boIsItDay()==false)//... if ALSO it is night-time...
          {HallwayLightOnOff(1);}
          }//End of dealing with case when door IS open.
 delay(5);
 }//end of loop()

Bigger and better....

Have you met "mod"? Wonderful arithmetical function. Any number "mod" 4 returns 0 to 3. It is essentially "the remainder", as some children once did division before mastering the complexities of decimal fraction answers.

For x mod 4, for various x's, the answers are....

     x: 0  1  2  3  4  5  6  7  8  9 10 11 12...
answer: 0  1  2  3  0  1  2  3  0  1  2  3  0...

Get it? And here's an example of it being good for something. (To say "tell me x mod 4" in Arduino-speak we say "Tell me x % 4")

To the loop() we had a moment ago, add...

if ((iTenthsSinceOpen % 4)>1)
     {BeepOnOff(0);}// no ; here
   else {BeepOnOff(1);};

... just before the...

if (bIsDoorOpen()==0)

.. which has been part of the code for a long time now.

That, in conjunction with the other new stuff added recently creates, depending on your piezo sounder, a rather annoying on/off/on/off beeping whenever the door- is- open sensor is NOT saying the door is open. NOT what we wanted, but a step along the road.

(I say "depending on your sounder", because our method is crude here... we are turning it on/on/off/off, at quite a high frequency, and some sounders may produce a garbled result. With mine, it "worked", but the sounder wasn't as loud as usual.)

Fear not... what we have will evolve. What we have at the moment is something to count iterations of loop(), (bLoopExecutions), and every time a certain number (bLoopsPerTenthSec) have taken place, we increment the value in iTenthsSinceOpen.

EVERY time a certain number of loop() executions has occurred. So at the moment, iTenthsSinceOpen is really "iTenthsSinceProgramWasStarted"! We're going to fix that. Be sure you're clear on the rest. Look at the code. Think.

Okay. Clear? Onward...

"All" we need is a "iTenthsSinceOpen=0"... at the right place.

We can't just put it in the "else" clause of..

if (boIsDoorOpen()==false)

... because that would keep putting it back to zero the whole time the door was open... and I want to USE the value for iTenthsSinceOpen while the door is still open.

Oh dear. Another variable. This is an example of a "flag" variable. And I'm going to use a variable of the data-type "boolean" here. (We could have used boolean-type variables earlier in this program, but I put it off for a variety of reasons.

The variables we've been using can hold numbers. Only numbers of certain types and ranges, of course. For instance byte-type variables can hold whole numbers from (inclusive) 0 t 255.

A boolean variable can hold "true" or "false".

Our new variable is going to be called boWasClosedBefore. And it will tell us the state of the door the last time we passed through loop().

To add this to the program, we need to declare it up with the other globals...

boolean boDoorWasClosedBefore;

... and we need to initialize it. We do this near the end of setup()....

  if (bIsDoorOpen()==0)
    {boDoorWasClosedBefore=true;}//no ; here
    else
    {boDoorWasClosedBefore=false;};

Once that's done, we need to keep the value in the variable up to date. We do that by putting boDoorWasClosedBefore=true; and boDoorWasClosedBefore=false; into the "then" and "else" clauses of if (bIsDoorOpen()==0), respectively,... right at the end of each clause. (If you are getting a bit lost, fear not, a new full listing of loop() is coming!)

It goes at the END of the clauses, so we can use the value in boDoorWasClosedBefore within the clause. The one use that I already know is necessary is that, in the "the door is now open" clause, we put an...

(pseudocode....
"If the door was closed before, put the
   iTenthsSinceOpen variable back to zero"

In Arduino-speak, that would just be...

 if (boDoorWasClosedBefore==true)
       {iTenthsSinceOpen=0;};

... which can be the penultimate line in the "the door is open" clause. (The "boDoorWasClosedBefore=false;" is the "ultimate" (last) line of the clause, remember?)

(We can make that a little more elegant, because boDoorWasClosedBefore is a boolean variable. The following is just as good... better, once you know how to read it... as the clumsy thing we had before...)

 if (boDoorWasClosedBefore)
       {iTenthsSinceOpen=0;};

Okay. Now iTenthsSinceOpen actually holds a count related to how long it has been since the last time the door was opened. (It may not be the number of tenths of seconds, yet, but it will probably be roughly that. To "fine tune it", when we've finished other things, you just tweak the value in the constant bLoopsPerTenthSec.)

Let's use it for something.

In loop()...

That will make loop()....

void loop()
{
 bLoopExecutions=bLoopExecutions+1;
     if (bLoopExecutions==bLoopsPerTenthSec)
       {
        bLoopExecutions=0;
        iTenthsSinceOpen=iTenthsSinceOpen+1;
        if (iTenthsSinceOpen==65534)
                {iTenthsSinceOpen=65533;};
       };

 if (boIsDoorOpen()==false)
   {//Door is NOT open...
     BeepOnOff(0);
     iTimeOnLeft=iTimeOnLeft-1;
     if (iTimeOnLeft==0)
           {
             HallwayLightOnOff(0);
             iTimeOnLeft=1;
           };
     boDoorWasClosedBefore=true;
   }//end of dealing with "Door is NOT open"
 else
   {//Door IS open...
     iTimeOnLeft=iTimeToStayOn;

     if ((iTenthsSinceOpen % 6)>1) //**
          {BeepOnOff(0);}// no ; here //**
     else {BeepOnOff(1);};         //**


     if (boIsItDay()==false)//... if ALSO it is night-time...
          {HallwayLightOnOff(1);}
     if (boDoorWasClosedBefore==true)
          {iTenthsSinceOpen=0;};
     boDoorWasClosedBefore=false;
   }//End of dealing with case when door IS open.
 delay(5);
 }//end of loop()

Now when you run the program, you get a on and off "beep" whenever "the door is open".

Review what is in loop(). Be sure you know what each thing is there for, what it does, how it does it.

With just a slight change, we're going to make the beeper go off once when the door opens, wait for a bit (duration, in "tenths of seconds", at least by program's "clock", in constant bWaitTenthsToBeep, and then beep as before while door is open until it is closed.

We need to set up the new constant...

#define bWaitTenthsToBeep 20//No ; here

... and then, because we are such brilliant programmers, it only needs a new "if" clause wrapped around some existing code in loop(). (I've quoted a few unchanged lines for context)...

else
   {//Door IS open...
     iTimeOnLeft=iTimeToStayOn;

     if (iTenthsSinceOpen>bWaitTenthsToBeep)
     {//Then clause, level 0
       if ((iTenthsSinceOpen % 6)>1)
          {BeepOnOff(0);}// no ; here
     else {BeepOnOff(1);};
     };//end of "Then clause, level 0"

     if (boIsItDay()==false)//... if ALSO it is night-time...

Simples!

Now the intermittent beeping doesn't start immediately the door is opened. (And also, we have something that we can use to tweak bLoopsPerTenthSec!). The intermittent beeping starts after the door has been open for bWaitTenthstoBeep tenth seconds. Much better!

A little nuisance: At this stage, there was a bug. If you released the "door is open" button, and then pressed it again rapidly, and held it down... instead of silence during the "bWaitTenthsToBeep" interval, you got a continuing beep. But not every time. It had to do with exactly when you released/ re-pressed. Putting a boDoorWasClosedBefore=true; into the boIsDoorOpen subroutine fixed this. You might think it didn't need fixing, but some switches "bounce", and there was a risk of this unwanted behavior arising in use. It isn't brilliant programming to "infect" the boIsDoorOpen routine with the "unrelated" "turn beeper off, if it happens to be on" code... but I'm taking a shortcut here. I will probably pay for it in due course. So the new boIsDoorOpen routine is...

boolean boIsDoorOpen()//Returns true when door is open
{
if (digitalRead(bIsDoorOpenSensorPin)==LOW)
  {
     boDoorWasClosedBefore=true;
     return false;
  }//no ; here
 else
  {
     return true;
  };//end else
}//end boIsDoorOpen

If you've noticed that I've "turned" the logic of the bIsDoorOpen sub-routine "upside down"...

The net effect is the same. (I hope!) and it was easier to put the boDoorWasClosedBefore=true; in where I wanted it that way. The alternative involved an unnecessary else.

Actually... it took me two tries to eliminate the "sometimes beeps when should be silent" bug... a sure sign that I didn't look sufficiently closely at what was going on. My comment about sloppiness coming back to bite was prophetic... and I may be bitten again. Learn from my mistakes! (My first fix put a BeepOnOff(0); where now I have the boDoorWasClosedBefore=true;

Hmm.. that doesn't fix it either. I'll come back to this one! (Another bad practice!)

Before we completely lose track of what we were doing, I should just mention that the LED still comes on (if it is night) as soon as the door is opened. Oh. And the one beep you were supposed to get as the door opened... not yet in the program. Sigh.

Here I must admit that the FINAL version (at the bottom) has got some subtle changes from the exact detail of the program, as the evolution of it has been (and will be described). Sorry! But the final version DOES work, and the path to the final version was not all rubbish... just slightly flawed in places. Test for the student?

Happily, unless I am again missing something, we are back in the Blessed Land of the Good Program, and this feature is added by modifying our existing "don't beep until"... if as follows. (The "||" means "or")...

     if ((iTenthsSinceOpen>bWaitTenthsToBeep) ||
         (iTenthsSinceOpen<3))
     {//Then clause, level 0....

Note something which will become important before long: The count of tenths since the door was opened does not stop, nor does it go back to zero, just because the door has been closed. It goes back to zero when the door is opened again.

That's the core of our project done!... Until you, if you are a Right Thinking Person, start thinking, "Yes, well, that's all well and good, but it would be so much better if it...."

Triggering the taking of pictures

There is one thing we have not gone into.

Remember, way back at the start, I said that I have some security cameras which can be "told" to take a picture with a 12v signal? Now we're going to get the Hallway Monitor to provide that signal.

Before I start on that, I will remind you: Not all cameras will respond graciously to having voltages pushed into them. Some "take picture" inputs only want you to connect the two terminals to one another. Take care! And even if you camera wants a voltage, it may be 3.3 volts ("3v3"), or 5 volts. There is no law to say that it will want (or tolerate) 12 volts. AND you need to "push" it through "the right way around".

Start by making your camera take pictures with some very simple set up. Only when you are clear on the wants of the camera's input move on to having the Arduino supply those wants.

For our development work, surprise, surprise, we will be using an LED as a "stand in" for the "Take Picture" input of the camera.

That makes us nearly ready to start coding... but there's one other thing you should know.

My camera... and many others, I suspect... is "edge sensitive". It doesn't take a picture because the "take picture" input is high... or low. It takes a picture when the input goes from low to high. If the input stays high, no further pictures are taken. First the input must go low again. Still no further picture. It is only when the input goes high a second time, only when another "edge" is seen, that the second picture is taken. (My camera actually lets me tell it whether to take the picture on the positive edge or on the negative edge, but in fact our code is going to produce a brief on- and- then- off- again pulse, so we probably won't even notice if the camera is set up for activation by positive or negative edge. It will take one photo for each pulse.

Whew! Well, if it were simple, would success be so sweet?

Of course, we're going to have another subroutine. Might as well call it "TakePhoto()".

void TakePhoto()
{
  digitalWrite(bIPCamTriggerPin, HIGH);
  delay(bLengthOfTakePhotoPulse);
  digitalWrite(bIPCamTriggerPin, LOW);
}//end of TakePhoto()

Note that it will "waste" a little time, and make any instance of loop() that calls TakePhoto() take a little longer than other instances of loop(). As we will rarely call TakePhoto() it really wouldn't matter, but just to be thorough, I will write the code so that the delay doesn't matter.

Note that a new constant, bLengthOfTakePhotoPulse, was set up, in order to make the TakePhoto() subroutine work. It will eventually be set to 10, but for now, so that mere humans can SEE that the pulse is being generated, it will be set to 100. This will temporarily mess up no end of things, because the time to pass through loop() once will be drastically altered.

Note also that a...

digitalWrite(bIPCamTriggerPin, LOW);

.. has been added to setup(). Long overdue!

So... we have the "pieces". How do we deploy them?

For testing, start by programming the HallwayMonitor to take one photo, when the door is first opened. We can add this... and a "balancing" delay to arise when we are not going into TakePhoto() and waiting for the pulse to finish... with...

     if (iTenthsSinceOpen==1)
         {TakePhoto();}//no ; here
       else
         {delay(bLengthOfTakePhotoPulse);};

... inserted in loop(), just before....

     if ((iTenthsSinceOpen>bWaitTenthsToBeep) ||
         (iTenthsSinceOpen<3))
     {//Then clause, level 0...

So...

We have a pretty good program. Here it is in full, with what we have so far...

void loop()
{
 boIsItDay();//This so that the SayWhetherNightOrDay
 //indicator is frequently updated.
 bLoopExecutions=bLoopExecutions+1;//(Yes, I know, you can
   //just say "++bLoopExecutions;" Is that newbie friendly?
     if (bLoopExecutions==bLoopsPerTenthSec)
       {
        bLoopExecutions=0;
        iTenthsSinceOpen=iTenthsSinceOpen+1;
        if (iTenthsSinceOpen==65534)
                {iTenthsSinceOpen=65533;};
       };

 if (boIsDoorOpen()==false)
   {//Door is NOT open...
     BeepOnOff(0);
     iTimeOnLeft=iTimeOnLeft-1;
     if (iTimeOnLeft==0)
           {
             HallwayLightOnOff(0);
             iTimeOnLeft=1;
           };
     boDoorWasClosedBefore=true;
   }//end of dealing with "Door is NOT open"
 else
   {//Door IS open...
     iTimeOnLeft=iTimeToStayOn;

     if (iTenthsSinceOpen==1)
         {TakePhoto();}//no ; here
       else
         {delay(bLengthOfTakePhotoPulse);};

     if ((iTenthsSinceOpen>bWaitTenthsToBeep) ||
         (iTenthsSinceOpen<3))
     {//Then clause, level 0
       if ((iTenthsSinceOpen % 6)>1)
          {BeepOnOff(0);}// no ; here
     else {BeepOnOff(1);};
     };//end of "Then clause, level 0"

     if (boIsItDay()==false)//... if ALSO it is night-time...
          {HallwayLightOnOff(1);}
     if (boDoorWasClosedBefore==true)
          {iTenthsSinceOpen=0;};
     boDoorWasClosedBefore=false;
   }//End of dealing with case when door IS open.
 delay(5);
 }//end of loop()

That program if pretty good. It turns the hall light on for a bit, when needed. It takes a picture when the door is opened. It beeps if the door is left open.

However... it takes the picture AS SOON AS the door is opened. The camera probably can't yet see the face of the person opening the door. And it would be nice to take one or two photos a moment after the first, don't you think? And the beeping can be made more "clever".

And all of those things only use stuff we've already got in the program... in particular "iTenthsSinceOpen".

I'm changing the "beep" behavior slightly... the first beeps will be to say "taking picture". Only after the door has been open for a bit will the "beep, beep, beep... close the door" beeping start.

It was quite a challenge to "tweak" the program so that three pictures were taken over, say, 15 seconds when the door was opened AND CLOSED in just, say, 4 seconds.`Before some re-working of the logic, closing the door cut short the picture taking... not what was wanted. I'd failed to fully think though my objectives before starting. But because the program had a clear, uncomplicated structure, getting to where I wanted to be proved not too difficult. Whew.

I won't drag you through every detail of the program development, but here's the final edition. As ever... getting to it from the "nearly done" version took hours longer than expected!

/*HallMonitor
Inspired by Computer Shopper article, c. "Dec14" issue

*/
#define vers 'first..29 Dec 14'//No ; here
//Started 29 Dec 14, in ICH05w, my first Arduino Pro Mini.
//For 277RR.

#define iTimeToStayOn 1800 //No ; here
int iTimeOnLeft;
unsigned int iTenthsSinceOpen;
byte bLoopExecutions;
boolean boDoorWasClosedBefore;//
boolean boFinishingPictures;//This variable introduced
   //late in the day. It was needed to stop the closing
   //of the door cutting short the brief spell of taking
   //a few pictures, one after the other.
#define bTakeFirstPhoto 10//no ; here.
#define bTakeSecondPhoto 25//no ; here.
#define bTakeThirdPhoto 45//no ; here.
#define bWaitTenthsToBeep 55//no ; here.

//Input pins
#define bDaySensorPin 9//no ; here. See boIsItDay function
#define bIsDoorOpenSensorPin 8//no ; here.

/*The next two BETWEEN THEM "set" the timebase of the program.
  For debugging, you might want to use, say, 3 and 30 for
      bLoopsPerTenthSec and bLengthOfTakePhotoPulse respectively.
  bLengthOfTakePhotoPulse will, ultimately, have to be long enough
      that your camera "notices" the pulse. (If it is too brief,
      various factors will prevent it "reaching" your camera.)
  Once the final "bLengthOfTakePhotoPulse@ has been chosen, tweaking
      bLoopsPerTenthSec will make the program's nominal "Tenths"
      variables and constants operate on a tenths- of- second
      timebase.
*/

#define bLoopsPerTenthSec 3//no ; here.
#define bLengthOfTakePhotoPulse 60//no ; here.

//Output pins

//SWAP BACK: 6 and 13... 6 should be bIPCamTrigger, 13 ThinksDay

#define bHallwayLightPin 4//no ; here.
#define bBeepPin 5//no ; here. Set high to make beeper sound
#define bIPCamTriggerPin 6//no ; here. Set high to signal to IP Cam
  //to take photo. Remember: Some cams edge sensitive.
#define bThinksDayPin 13//no ; here.

//byte bTmp;//Global "tmp" variable.

void HallwayLightOnOff(byte bOnOff)//Turn hallway light
   //on if 1 passed, off if zero passed
   {
   if (bOnOff==1)
   {
   digitalWrite(bHallwayLightPin,HIGH);
   }
   else
   {
   digitalWrite(bHallwayLightPin,LOW);
   }
   }//end HallwayLightOnOff

void BeepOnOff(byte bBeepOnOff)//Turn piezo sounder on/off
   //on if 1 passed, off if zero passed
   {
   if (bBeepOnOff==1)
   {
   digitalWrite(bBeepPin,HIGH);
   }
   else
   {
   digitalWrite(bBeepPin,LOW);
   }
   }//end BeepOnOff

boolean boIsDoorOpen()//Returns true when door is open
//This code assumes that when door is closed, the SensorPin
//  is pulled low by a circuit. Opening the door opens
//  the circuit, and SensorPin will "look" high, due to
//  the internal pullup, which was enabled with the
//  digitalWrite(bIsDoorOpenSensorPin,HIGH) in setup()

{
 if (digitalRead(bIsDoorOpenSensorPin)==LOW)
  {
     return false;
  }//no ; here
 else
  {
     return true;
  };//end else
}//end boIsDoorOpen

//SUBROUTINE for boIsItDay... but Arduino does not allow
//  nesting of subroutines.

void SayWhetherNightOrDay(byte bDayIfOne)
  //This does NOT find OUT if it is day... it merely
  //   tells you whether the Arduino THINKS, based on
  //   other code, whether it is day.
  //Pass 1 to this if you want Arduino to say it is day.
  //Give indication from Arduino whether it thinks
  //  it is presently night or day (based on light.
  //This is NOT the SENSE day/night function... it
  //  is merely a routine to REPORT what has been
  //  sensed.
  {
   if (bDayIfOne==1)
   {
   digitalWrite(bThinksDayPin,HIGH);
   }
   else
   {
   digitalWrite(bThinksDayPin,LOW);
   }
   }//end SayWhetherNightOrDay

boolean boIsItDay() /*Returns true if daytime, false if night
   (Based on light levels)
   This can be written two ways (at least), depending
   on what resources are available. In my case, I had
   a second Arduino monitoring light levels already.
   It was a simple matter to get it to drive an output
   (on it) to feed an input on the Arduino HallwayLight
   is running on. Alternatively, the function could use
   one of the Arduino's analog inputs to monitor a light
   sensor.
   */
/*For alternate "is it day" function...
const int MakeLightOnDOutTrue=2;//If greater than this.*/

{
  if (digitalRead(bDaySensorPin)==LOW)
    {SayWhetherNightOrDay(1);
     return true;
   }//no ; here
   else
    {SayWhetherNightOrDay(0);
     return false;
    }//end of else

/*Scrap from another program, showing the basics of using
analog input to determine day/night. Names will need changes
  int iAn0;
            if (iAn0>MakeLightOnDOutTrue)
    {SayWhetherNightOrDay((1);
     return true;
   }//no ; here
   else
    {SayWhetherNightOrDay(0);
     return false;
    }//end of else
*/
}//end boIsItDay()

void TakePhoto()
{
  digitalWrite(bIPCamTriggerPin, HIGH);
  delay(bLengthOfTakePhotoPulse);
  digitalWrite(bIPCamTriggerPin, LOW);
}//end of TakePhoto()

void setup()
{
  pinMode(bDaySensorPin,INPUT);
  digitalWrite(bDaySensorPin,HIGH);// "Connect"
     //internal pull up.

  pinMode(bIsDoorOpenSensorPin,INPUT);
  digitalWrite(bIsDoorOpenSensorPin,HIGH);// "Connect"
     //internal pull up.

//Output pins
  pinMode(bHallwayLightPin,OUTPUT);
  pinMode(bBeepPin,OUTPUT);
  pinMode(bIPCamTriggerPin,OUTPUT);
  pinMode(bThinksDayPin,OUTPUT);

  iTenthsSinceOpen=0;
  bLoopExecutions=0;

  if (boIsDoorOpen()==true)
    {boDoorWasClosedBefore=true;}//no ; here
    else
    {boDoorWasClosedBefore=false;};

  digitalWrite(bIPCamTriggerPin, LOW);

  boFinishingPictures=false;//(We have not yet started
     //taking a set of pictures.)

}//end of setup()

void loop()
{
 boIsItDay();//This so that the SayWhetherNightOrDay
 //indicator is frequently updated.

 bLoopExecutions=bLoopExecutions+1;//(Yes, I know, you can
   //just say "++bLoopExecutions;" Is that newbie friendly?
     if (bLoopExecutions==bLoopsPerTenthSec)
       {
        bLoopExecutions=0;
        iTenthsSinceOpen=iTenthsSinceOpen+1;
        if (iTenthsSinceOpen==65534)
                {iTenthsSinceOpen=65533;};
       };

 if ((boIsDoorOpen()==false) &&
    (boFinishingPictures==false))
   {//Door is NOT open... and we not finishing a set of photos...
    BeepOnOff(0);
    iTimeOnLeft=iTimeOnLeft-1;//TimeLeftOn keeps hall light lit.
    if (iTimeOnLeft==0)
           {
             HallwayLightOnOff(0);
             iTimeOnLeft=1;//so that the next -1 doesn't cause problem.
           };
    boDoorWasClosedBefore=true;
   }//end of dealing with "Door is NOT open" AND we are not finishing
        //a set of photos.
else
   {//Door IS open OR we are finishing taking a set of photos

    if (boDoorWasClosedBefore==true)//Do once, when door opens...
         {iTenthsSinceOpen=0;
          boFinishingPictures=true;//Set flag to ensure all photos taken
          boDoorWasClosedBefore=false;
         };//Want ; here. No else for this if

     if (iTenthsSinceOpen==2)
         {BeepOnOff(1);//beep as door opens.. will beep several times,
             //all the while within iTenthsSinceOpen==2
          delay(bLengthOfTakePhotoPulse);//Re-purposed... to let beep last
          BeepOnOff(0);
          };//Want ; here. No else for this if..

     if (iTenthsSinceOpen>bTakeThirdPhoto)
         {boFinishingPictures=false;};//Want ; here: no "else" for this "then"

     iTimeOnLeft=iTimeToStayOn;//Repeatedly reset, until door closed.
        //this variable about how long hall light stays lit.

     if (
          (iTenthsSinceOpen==bTakeFirstPhoto)  ||
          (iTenthsSinceOpen==bTakeSecondPhoto) ||
          (iTenthsSinceOpen==bTakeThirdPhoto) //See note below...
        )
         {BeepOnOff(1);
          TakePhoto();
          BeepOnOff(0);}//no ; here
       else
         {delay(bLengthOfTakePhotoPulse);};

     if (iTenthsSinceOpen>bWaitTenthsToBeep)
               //Make the constant bWaitTenthsToBeep
               //bigger than bTakeThirdPhoto,
               //or the "taking photos" beeps will be
               //hard to distinguish from the "door open"
               //beeps

     {//start of "then" clause "1"
       if ((iTenthsSinceOpen % 8)<1)
             {BeepOnOff(1);}// no ; here
       else  {BeepOnOff(0);};
     };//end of "then" clause "1"

     if (boIsItDay()==false)//... if ALSO it is night-time...
          {HallwayLightOnOff(1);}

   };//End of dealing with case when door IS open.
   delay(5);
 }//end of loop()

I'd be interested to hear what bits of the above were most useful to you, what bits most annoying.

One last "issue", again related to the various circuits used in IP cameras. You may need to connect the ground of the power to the camera to the ground of your Arduino. I would hope that those cameras which require a voltage to trigger a "take picture" are using opto-isolators, in which case you don't need to connect the grounds. I'd be inclined to ADD an opto-isolator, just in case... even though that may leave you with an opto-isolator driving an opto-isolator! Better safe than sorry? I only play with relatively cheap IP cameras, so get a little reckless. Not good, though. Sigh.




To search THIS site.... (Go to my other sites, below, and use their search buttons if you want to search them.)
Click this to search this site without using forms.

powered by FreeFind
Site search Web search
The search engine merely looks for the words you type, so....
*    Spell them properly.
*    Don't bother with "How do I get rich?" That will merely return pages with "how", "do", "I"....

Please also note that I have two other sites, and that this search will not include them. They have their own search buttons.
My site at Arunet.
My Sheepdog Software pages, another of this page's editor's sites.
Ad from page's editor: Yes.. I do enjoy compiling these things for you... hope they are helpful. However.. this doesn't pay my bills!!! If you find this stuff useful, (and you run an MS-DOS or Windows PC) please visit my freeware and shareware page, download something, and circulate it for me? Links on your page to this page would also be appreciated!
Click here to visit editor's freeware, shareware page.




Here is how you can contact this page's editor. This page, and the software it references, ©TK Boyd, 1/2010.

Valid HTML 4.01 Transitional Page tested for compliance with INDUSTRY (not MS-only) standards, using the free, publicly accessible validator at validator.w3.org