Carpark entry counter

Hi, I've been working on a count to track cars entering a carpark, and I'm having some monir trouble.

What I need, is for ir beam 1 to be triggered, then IR beam 2 to be triggered, whilst the first is still active, before I get a counter+1 event.
and the opposite for exiting the carpark, IR 2, then IR 1 whilst the first is active, before I get a counter-1 event.
i have 3 LEDs to light one to replicate IR 1, one to replicate IR2 and one to indicate that the counter has changed.

I thought I had it figured out, as the sketch compiled, but I'm not getting any results or not what I am expecting,anyway.
Sorry if its a bit messy, I have been chopping and changing it to try and get it to work. it was a lot neater than this to begin with :frowning:
Eventually I will be relaying the output to a web page, but first I need to get the data acquisition right.

Any help is very much appreciated.
cheers
Jason

const int IRTrigger1 = 1;     // the number of the pin used to read IR beam status
const int IRTrigger2 = 2;
const int CounterChange =  13;      // the number of the LED pin

// variables will change:
int IRState1 = 0;         // variable for reading the pushbutton status
int IRState2 = 0;
int totalcars =0;
int value = 0;
int entering = 0;
int leaving = 0;
void setup() {
 const int IRTrigger1 = 1;     // the number of the pin used to rear IR beam status
const int IRTrigger2 = 2;
const int CounterChange =  13;      // the number of the LED pin

// variables will change:
int IRState1 = 0;         // variable for reading the pushbutton status
int IRState2 = 0;
int totalcars =0;
int value = 0;
int entering = 0;
int leaving = 0;
  // initialize the LED pin as an output:
  pinMode(CounterChange, OUTPUT);      
  // initialize the pushbutton pin as an input:
  pinMode(IRTrigger1, INPUT);     
  pinMode(IRTrigger2, INPUT); 
 Serial.begin(9600);
}

void loop(){
  // read the state of the pushbutton value:
  IRState1 = digitalRead(IRTrigger1);
  IRState2 = digitalRead(IRTrigger2);

    
  
if (IRTrigger1 < 1){
     IRState1=1; digitalWrite(CounterChange, HIGH);
}

if (IRTrigger2 < 1){
     IRState2=1;
}

if(IRState1 > IRState2){
  entering = 1;
} else if (IRState2 > IRState1){
     leaving=1;
}
  
if ((IRState1 + IRState2) ==2){
      if (entering == 1){
     totalcars = totalcars + 1;
     digitalWrite(CounterChange, HIGH);
     delay(200);
     digitalWrite(CounterChange, LOW); 
     }  else if (leaving == 1){
    totalcars = totalcars - 1;
     }
entering=0; // reset everything
leaving=0;
IRState1=0;
IRState2=0;
}
}

There is no point testing IRTrigger1 or IRTrigger2 as they are both defined as constants.

You should be testing IRState1 and IRState2.

You don't seem to have any code to figure out which IR was triggered first.

I think your logic needs to be something like this

wait until both sensors are off ... then
if sensor1 is on and sensor 2 is off there is an incoming car
but don't count it until sensor 2 goes on
if sensor2 is on and sensor 1 is off there is an outgoing car
but don't count it until sensor 1 goes on

...R

Testing a constant....well done jason.

Ok, I have the logic part sorted, I messed with it a bit before posting, so it didnt look right. Thanks Robin2!

Hi again,
I have sorted the Logic part of the code, and cleaned it up a bit, but now that I have inserted the websever side of it, I am getting weird results(web server worked by itself, but as a function, not so much

what i get in the serial monitor is:
"New client
G
client Disconnected"

Now I cannot for the life of me, figure out where this "G" is coming from, nor why I am getting no "Digital Input pin is: x" data on the web page.

I realise it is probably not syntax that is the issue, as it compiles. I have been staring at theis for hours, and just can't see it.

any help is appreciated
Regards
Jason

#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1, 100);
const int IRTrigger1 = 2;     // the number of the pin used to read IR beam status
const int IRTrigger2 = 3;
const int CounterChange =  13;      // the number of the LED pin

// variables will change:
int IRState1 = 0;         // variable for reading the pushbutton status
int IRState2 = 0;
int totalcars =0;
int IRvalue1 = 0;
int IRvalue2 = 0;
int entering = 0;
int leaving = 0;
int webserver();
// Initialize the Ethernet server library
// with the IP address and port you want to use 
// (port 80 is default for HTTP):
EthernetServer server(80);

void setup() {

  // initialize the LED pin as an output:
  pinMode(CounterChange, OUTPUT);      
  // initialize the pushbutton pin as an input:
  pinMode(IRTrigger1, INPUT);     
  pinMode(IRTrigger2, INPUT); 
  Serial.begin(9600);
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}

void loop(){
  
   EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    webserver();}
  // read the state of the pushbutton value:
  IRState1 = digitalRead(IRTrigger1);
  IRState2 = digitalRead(IRTrigger2);

    
  Serial.print("IRvalue1= ");
     Serial.println(IRState1);
if (IRState1 >0){
     IRvalue1=1; digitalWrite(CounterChange, HIGH);
     Serial.print("IRvalue1= ");
     Serial.println(IRState1);}

if (IRTrigger2 >0){
     IRvalue2=1;}

if(IRState1 > IRState2){
  entering = 1;} else if (IRState2 > IRState1){
     leaving=1;}
  
if ((IRState1 + IRState2) ==2){
      if (entering == 1){
     totalcars = totalcars + 1;
     digitalWrite(CounterChange, HIGH);
     delay(1000);
     digitalWrite(CounterChange, LOW); }
     else if (leaving == 1){
    totalcars = totalcars - 1;
     }
entering=0; // reset everything
leaving=0;
IRState1=0;
IRState2=0;
}
}
int webserver(){

   EthernetClient client = server.available();
 boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        client.println("
"); 
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connnection: close");
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
                    // add a meta refresh tag, so the browser pulls again every 5 seconds:
          client.println("<meta http-equiv=\"refresh\" content=\"5\">");
          // output the value of each analog input pin
          for (int digitalChannel = 0; digitalChannel < 3; digitalChannel++) {
            int inputs = digitalRead(digitalChannel);
            client.print("Digital input Pin");
            client.print(digitalChannel);
            client.print(" is ");
            client.print(inputs);
            client.println("
");       
          }
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
          // give the web browser time to receive the data
      delay(5);  
      }
    delay(5000);
    
          
        
  
      }
   //close the connection:
    client.stop();
   Serial.println("client disonnected");  
  }}

Assuming you're using an SPI-based Ethernet shileld...

Arduino communicates with both the W5100 and SD card using the SPI bus (through the ICSP header). This is on digital pins 11, 12, and 13 on the Duemilanove Uno.

const int CounterChange =  13;      // the number of the LED pin

Arrch:
Assuming you're using an SPI-based Ethernet shileld...

http://arduino.cc/en/Main/ArduinoEthernetShield

Arduino communicates with both the W5100 and SD card using the SPI bus (through the ICSP header). This is on digital pins 11, 12, and 13 on the Duemilanove Uno.

const int CounterChange =  13;      // the number of the LED pin

Simple trap to fall into. I did something similar with a little project. I wanted to toggle a light for diagnostics. I happened to have some small 0.1" lead spacing 5V LEDs (integrated resistor for running directly on 5V). Since there is a GND connection right next to D13, I dropped it in and added code to toggle that LED for my diagnostics. Scratched my head for a bit wondering why the LED was constantly on at a low level... (I couldn't easily see the on-board LED because I had the Ethernet shield plugged in...) Felt kinda silly after I discovered the error. What I ended up doing (so I could keep using the same LED plugged directly into the shield pass-through header) was putting it between A0 and A1. Set A0 as digital output LOW, and toggled A1 digitally as my diagnostics. That worked.

But to the OP... By your description, it looks much like you are using the two IR beams just like how a rotary encoder works. (Only you are trying to ignore single IR beam trips because that would be a person, not a car...) Check some of the rotary encoder examples for counting forward and backwards and get your code working counting cars in and out. Then add the code to ignore isolated single beam interruptions.

" LED was constantly on at a low level..."

now that you mention it, so is mine.

ill look at that first then move to the rest of your post, thanks!

I've moved the diag LED to pin 10, or do you suggest moving it to analog pins?

it hasn't made any difference at D10

, still can't see where this "G" is coming from in the serial monitor.

and nothing shows on the web page, just a blank screen
the UNO derivative I'm using is the EtherTen, from freetronics

Regards
Jason

JsGarage:
I've moved the diag LED to pin 10, or do you suggest moving it to analog pins?

On both boards, pin 10 is used to select the W5100 and pin 4 for the SD card.

JsGarage:
I've moved the diag LED to pin 10, or do you suggest moving it to analog pins?

it hasn't made any difference at D10

, still can't see where this "G" is coming from in the serial monitor.

and nothing shows on the web page, just a blank screen
the UNO derivative I'm using is the EtherTen, from freetronics

Regards
Jason

Check the documentation for that board. I know when using my UNO r3 D10 is tied up when doing anything with ISP, so often boards use it as a CS. It might be the same with your board, I don't know but likely. In my "solution" I chose the analog pins just because they were available and I didn't have any wires to that side of my Arduino so the LED wasn't occluded by anything. Mostly an arbitrary choice. You can treat the analog pins like digital pins though. Reference them with A0-A5 when using the digital functions. (You could reference them as 14-19. Best to use the "A" numbers to make it easier to remember what they are called because the board silkscreen likely doesn't have the 14-19 indicators on it.)

thanks people!, I now have this working(as far as code is concerned)
now, I have a hardware issue :frowning:

ok, i have a tactile switch with 2k2, pulldown resistor attached to D2, and another wired the same on D3,
there is a yellow led indicator attached to pin D5, red to pin D7, and green to D9.
now when i press switch 1, pin 5 lights the yellow LED
when i press switch two, pin 7 lights the red LED
when i hold one switch, and press the other, the code deciphers which was the first to trigger, modifies the counter(for total entries/exits) and pin 9 lights the green LED
these result are mirrored to the web server which can be viewed from a browser. until......

THE PROBLEM
when i press both buttons at once, the ethernet portion of the board drops out.
code is as follows:::

#include <SPI.h>
#include <Ethernet.h>
// For MEGA2560 with IEsheild v1.01 only
// #include <enc28j60.h>
// #include <ethershield>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1,100);
const int IRTrigger1 = 2;     // the number of the pin used to read IR beam status
const int IRTrigger2 = 3;
const int CounterChange =  9;      // the number of the LED pin
const int IR1Triggered = 7;   // to show beam one is broken
const int IR2Triggered = 5;  // to show beam two is broken
// variables will change:
int IRState1 = 0;         // variable for reading the pushbutton status
int IRState2 = 0;
int totalcars =0;
int IRvalue1 = 0;
int IRvalue2 = 0;
int entering = 0;
int leaving = 0;
int webserver();
// Initialize the Ethernet server library
// with the IP address and port you want to use 
// (port 80 is default for HTTP):
EthernetServer server(80);

void setup() {

  // initialize the LED pin as an output:
  pinMode(CounterChange, OUTPUT);      
  // initialize the pushbutton pin as an input:
  pinMode(IRTrigger1, INPUT);     
  pinMode(IRTrigger2, INPUT); 
  pinMode(IR1Triggered, OUTPUT);
  pinMode(IR2Triggered, OUTPUT);
  Serial.begin(9600);
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}

void loop(){
  
   EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    webserver();}
  // read the state of the pushbutton value:
  IRState1 = digitalRead(IRTrigger1);
  IRState2 = digitalRead(IRTrigger2);

    
     Serial.print("IRvalue1= ");
     Serial.println(IRState1);
     Serial.print("IRvalue2= ");
     Serial.println(IRState2);
     Serial.println(" ");
     Serial.println(" ");
if (IRState1 >0){
     IRvalue1=1; digitalWrite(IR1Triggered, HIGH);
     Serial.print("IRvalue1= ");
     Serial.println(IRvalue1);}
else digitalWrite(IR1Triggered,LOW);
if (IRState2 >0){
     IRvalue2=1;digitalWrite(IR2Triggered, HIGH);
     Serial.print("IRvalue2= ");
     Serial.println(IRvalue2);}
else digitalWrite(IR2Triggered,LOW);

if(IRState1 > IRState2){
  entering = 1;} else if (IRState2 > IRState1){
     leaving=1;}
  
if ((IRState1 + IRState2) ==2){
      if (entering == 1){
     totalcars = totalcars + 1;
     digitalWrite(CounterChange, HIGH);
     delay(1000);
     digitalWrite(CounterChange, LOW); }
     else if (leaving == 1){
    totalcars = totalcars - 1;
     digitalWrite(CounterChange, HIGH);
     delay(1000);
     digitalWrite(CounterChange, LOW); 
     }
entering=0; // reset everything
leaving=0;
IRState1=0;
IRState2=0;
}
}
int webserver(){

   EthernetClient client = server.available();
 boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) 
      //{
        char c = client.read();
   //   Serial.write(c);
       
        client.println("
"); 
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
   //   if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connnection: close");
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
                    // add a meta refresh tag, so the browser pulls again every 5 seconds:
          client.println("<meta http-equiv=\"refresh\" content=\"5\">");
          // output the value of each Digital input pin
          
             client.println("
");
            client.print("Beam 1 is ");
            client.println(IRState1);
             client.println("
");
            client.print("Beam 2 is ");
            client.print(IRState2);
            client.println("
");
     client.print("Total cars in carpark is ");      
     client.println(totalcars);
    //      }
          client.println("</html>");
          
          break;
        }
    //  if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
   //     } 
   //   else if (c != '\r') {
          // you've gotten a character on the current line
        currentLineIsBlank = false;
          // give the web browser time to receive the data
    delay(5);  
   //   }
    delay(5000);
     //}
   //close the connection:
    client.stop();
   Serial.println("client disonnected");  
  }
//}

sorry to be such a pain, any help is muchos appreciado

How do you know the ethernet portion drops out? Could it be that it just isn't called?

Can you run a version of the program without any ethernet stuff and see what happens when you press 2 buttons at the same time?

...R

All the lights on the ethernet side go out,(including the ones on the eth port) and i cant refresh the page.
while one button is pressed, the page can be refreshed(or does automatically every 15 sec)

without the ethernet portion running, the program does what it should.

I'm wondering if the +5 rail cannot handle the load? and if so, how do remedy this?

Regards
Jason

Am I correct to assume that the tactile switches are a substitute for your IR sensors? If not what are they for?

I haven't used the ethernet shield but I wonder should you be creating a new instance of client in every iteration of the loop? I would be inclined to create the instance once in setup.

Am I correct to think that there is no problem when both switches are pressed provided one is pressed first and the problem only arises if both are pressed at the same time? Have you tried pressing them one after the other but with as short an interval as possible?

If your switches are each drawing 5v / 2200ohms = 2.3 mA then I can't see how they are overloading the 5v supply unless they are the last straw and the root of the problem is elsewhere.

Is it possible that when you press the two switches you move something else that has a poor connection?

It's an interesting problem.

...R

Robin2:
Am I correct to assume that the tactile switches are a substitute for your IR sensors?

Correct

I haven't used the ethernet shield but I wonder should you be creating a new instance of client in every iteration of the loop? I would be inclined to create the instance once in setup.

hahaha, God I'm daft sometimes.

Am I correct to think that there is no problem when both switches are pressed provided one is pressed first and the problem only arises if both are pressed at the same time? Have you tried pressing them one after the other but with as short an interval as possible?

No, as soon as the second one is pressed(regardless of which is pressed first) it dies/freezes/becomes unresponsive/etc.

Is it possible that when you press the two switches you move something else that has a poor connection?

I'm, beginning to think so, as after a PC reboot, an Arduino reload, a board reset, and trying my best not to scream like a madman and rip it all to pieces then set it on fire.....it's stopped doing it.

Now, i just need to add time stamping and SD card save, and i think its about ready!

thanks for your help :slight_smile:

Once again, thanks for all your help so far !

what i have now is a working counter/ a working web server/ and a working(to a point-but thats not a worry just yet) clock.
now what i can't get to play nice, is the SD card writing.
I have it attempting to write to the SD card every 10sec(will eventually be every hour, but 10sec will do for testing)
It keeps failing to init the card.

all the 1000ms delays in my code are just to slow it down; they will eventually be removed--- it was originally scrambling the serial output and the SD card writings, adding these got rid of that, but also stopped the card inits from working

now it says initialise failed, but when i view the card on my pc, it has actually created the "traffic.txt" file.

I have added a line "sd.remove" to clear the card again, just incase it is a "file exists" type of problem.
should i have a line to check for the file instead?

Also, it appears to be looping back into my SETUP () constantly.....i would have thought this would only run once?

I have code to change the SPI pins(4 and 10) to mirror what i am trying to achieve at each point, but that does not appear to have helped.

Something of note is that the LED on board(D13) is flickering constantly, but i have nothing writing to it?

i have spent a couple of days on this problem now, and i just can't figure it out.
I have attached the sketch file below ,

Please, if you could?
Regards
Jason

counter_sd_fail.ino (14.8 KB)

Also, it appears to be looping back into my SETUP () constantly.....i would have thought this would only run once?

Classic out-of-memory action.

Use the F() macro with all of your string literals:
client.println(F("HTTP/1.1 200 OK"));

That seems to have done the trick, thanks PaulS !

I did a few other tweaks as well, and now have all functions running in total harmony :smiley:

Is there a way to pull the time from a network adapter or something? this board will be running standalone once its installed, with just an ethernet link to the outside world. (no internet access)

current code is attached :slight_smile:

Regards
Jason

countertimefault.ino (17.5 KB)

JsGarage:
[... trim ...]
Something of note is that the LED on board(D13) is flickering constantly, but i have nothing writing to it?

Not sure if you have realized what is happening with D13. I went through a similar issue with once before I realized the obvious... D13 is used by writing to the SD because it is also the SPI MISO pin. So every time you write or read from the SD card the LED essentially gets a PWM signal. If the flickering looks random enough, extend it to a LED in a candle-shaped enclosure. If the candle is flickering, you haven't crashed. Kinda a cute indicator for actual deployment. :wink: