Trying to count the amount of passing objects

Hello, so i’ve been working on a project with arduino where i’m trying to make a parking lot using servo’s, sensors and an LCD to display the time and free parking spaces, but i can’t get the information on the LCD to work.

Here’s the code i currently have:

#include <Servo.h> 
#include <LiquidCrystal_I2C.h>
#include <Wire.h>


int servoPin1=3;
int servoPin2=4;
int intCounter = 20;
String strFreeSpots = " free spots";

Servo Servo1;
Servo Servo2;
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

void setup(){
Servo1.attach(servoPin1);
Servo2.attach(servoPin2);
lcd.begin(16, 2);
pinMode(22, INPUT);
pinMode(24, INPUT);
pinMode(26, INPUT);
pinMode(28, INPUT);

}
void loop(){
if(digitalRead(22) == LOW)
{
  Servo1.write(90);
}
if(digitalRead(24) == LOW)
{
  Servo1.write(0);
  counter--;
}
if(digitalRead(26) == LOW)
{
  Servo2.write(90);
}
if(digitalRead(28) == LOW)
{
  Servo2.write(0);
  counter++;
}

String strDisplay = intCounter + strFreeSpots;

if(intCounter > 0 && intCounter < 21)
{
lcd.setCursor(0,0);
lcd.print(strDisplay);
lcd.setCursor(0,1);
lcd.print(time);
}
else
{
lcd.setCursor(0,0);
lcd.print("No free spots");
lcd.setCursor(0,1);
lcd.print(time);
}
}

I have no idea how to do the time part but the counter keeps counting and i don’t know how to make it count only once so if anyone could help me I would be very grateful.

Have a look at the state change example in the IDE :slight_smile:

Also some tips:

  • watch the indentation! It’s one of the best tools we have to read through code easily. Press ctrl+T in the IDE to make it help you.
  • Use descriptive variable names for pins etc.
  • use “cont byte” for those pin definitions
  • Same for the objects. We know Servo1 is a servo-object, but what do you want it to do in you’re application? Is it controlling a barrier? Than call it barrierServo etc.
  • Get rid of Strings, use (c-style) strings :slight_smile:

So i tried using the state change detection but i don’t seem to get it working.
This is what i have right now.

#include <Servo.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>


int servoPin1 = 3;
int servoPin2 = 4;
int intCounter = 20;
String strFree = " free spots";

Servo ServoEntrance;
Servo ServoExit;

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

int sensorState1 = 0;
int lastSensorState1 = 0;
int sensorState2 = 0;
int lastSensorState2 = 0;

void setup() {
  ServoEntrance.attach(servoPin1);
  ServoExit.attach(servoPin2);

  lcd.begin(16, 2);

  pinMode(22, INPUT);
  pinMode(24, INPUT);
  pinMode(26, INPUT);
  pinMode(28, INPUT);
}
void loop() {

  sensorState1 = digitalRead(24);
  sensorState2 = digitalRead(28);

  if (digitalRead(22) == LOW)
  {
    ServoEntrance.write(90);
  }
  if (digitalRead(24) == LOW)
  {
    ServoEntrance.write(0);
    if (sensorState1 != lastSensorState1) {
      if (sensorState1 == HIGH) {
        intCounter++;
      }
    }
  }
  if (digitalRead(26) == LOW)
  {
    ServoExit.write(90);
  }
  if (digitalRead(28) == LOW)
  {
    ServoExit.write(0);
    if (sensorState2 != lastSensorState2) {
      if (sensorState2 == HIGH) {
        intCounter--;
      }
    }
  }

  String strDisplay = intCounter + strFree;

  if (intCounter > 0 && intCounter < 21)
  {
    lcd.setCursor(0, 0);
    lcd.print(strDisplay);
    lcd.setCursor(0, 1);
    lcd.print(time);
  }
  else
  {
    lcd.setCursor(0, 0);
    lcd.print("No free spots");
    lcd.setCursor(0, 1);
    lcd.print(time);
  }
}

Now it just doesn’t count at all.

Is 'sensorState1' ever going to be HIGH if that part is only run with pin 24 LOW?

PS Please don't just ignore my comments ;) At least mention it in your reply. Or better, follow them. Because 1) it makes debugging a lot easier because you can make sense of what you wrote 2) It makes understanding the code easier. Also for you when you didn't look at the code for a week/month/year. 3) For us to read it! After all, we offer free help and advice. But of counter effort from your side is very much appreciated :)

Sorry about not using the tips, I tried using some of them like the indentation and the descriptive variable names but I don’t really know what you meant with the tip about the const byte pin definitions and the c-style strings.

I also tried changing my state change detection to LOW and it still doesnt work.

I also realised i forgot the lastSensorState1 = sensorState1;.

Here is my current code:

#include <Servo.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>


int servoPin1 = 3;
int servoPin2 = 4;
int intCounter = 20;
String strFree = " free spots";

Servo ServoEntrance;
Servo ServoExit;

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

int sensorState1 = 0;
int lastSensorState1 = 0;
int sensorState2 = 0;
int lastSensorState2 = 0;

void setup() {
  ServoEntrance.attach(servoPin1);
  ServoExit.attach(servoPin2);

  lcd.begin(16, 2);

  pinMode(22, INPUT);
  pinMode(24, INPUT);
  pinMode(26, INPUT);
  pinMode(28, INPUT);
}
void loop() {

  sensorState1 = digitalRead(24);
  sensorState2 = digitalRead(28);

  if (digitalRead(22) == LOW)
  {
    ServoEntrance.write(90);
  }
  if (digitalRead(24) == LOW)
  {
    ServoEntrance.write(0);
    if (sensorState1 != lastSensorState1) {
      if (sensorState1 == LOW) {
        intCounter++;
       }
      lastSensorState1 = sensorState1;
    }
  }
  if (digitalRead(26) == LOW)
  {
    ServoExit.write(90);
  }
  if (digitalRead(28) == LOW)
  {
    ServoExit.write(0);
    if (sensorState2 != lastSensorState2) {
      if (sensorState2 == LOW) {
        intCounter--;
      }
    lastSensorState2 = sensorState2;
    }
  }

  String strDisplay = intCounter + strFree;

  if (intCounter > 0 && intCounter < 21)
  {
    lcd.setCursor(0, 0);
    lcd.print(strDisplay);
    lcd.setCursor(0, 1);
    lcd.print(time);
  }
  else
  {
    lcd.setCursor(0, 0);
    lcd.print("No free spots");
    lcd.setCursor(0, 1);
    lcd.print(time);
  }
}

Erkens15:
I tried using some of them like the indentation

Saw that, good!

Erkens15:
and the descriptive variable names

Mm, in that you still failed quite. Don’t try to think in code, try to think in your application! Keeping track of all variables is easy for the compiler and microcontroller. So you don’t need the names for them.

Some examples:

//you already did these, good! But also try to use the same style, lowerCamelCase is common in Arduino
Servo servoEntrance;
Servo servoExit;

//But go on and use:
const byte ServoEntrancePin = 3;
const byte ServoExitPin = 4;
//here you also see the use of const byte. And I used UpperCamelCase to indicate I can't change those variables at run time.

//but also for:
const byte CarEnteringPin = 24;
const byte CarLeavingPin = 28;
//etc

//And for the counting:
int carCounter = 20; //it's counting cars, not ints ;)

Erkens15:
the c-style strings.

Use:

char strFree[] = " free spots";
//instead of
//String strFree = " free spots";
//or even better:
char strFree[] PROGMEM= " free spots";

For the last you need to add

#include <avr/pgmspace.h>

Google “progmem” for what it does :wink:

Erkens15:
I also tried changing my state change detection to LOW and it still doesnt work.

First a question, how are the switches/buttons/whatever wired? And what are they?

If they are switches, do you use an external pull up/down resistor?

Next, can you spot your error now?

 sensorState1 = digitalRead(24);
  if (digitalRead(24) == LOW)
  {
    ServoEntrance.write(0);
    if (sensorState1 != lastSensorState1) {
      if (sensorState1 == LOW) {
        intCounter++;
       }
      lastSensorState1 = sensorState1;
    }
  }

I only removed a little bit.

My sensors are wired directly to a breadboard. With a wiring going to the +5v, one to the GND and one to my pins i.e. pin 24, so i’m currently not using resistors.

For the #include <avr/pgmspace.h>, i suppose this is not a standard library and thus requiring me to download it first?

For the mistake in the state change detection, it seems i need to put the “lastSensorState1 = sensorState1;” one } further, like so:

 sensorState1 = digitalRead(24);
  if (digitalRead(24) == LOW)
  {
    ServoEntrance.write(0);
    if (sensorState1 != lastSensorState1) {
      if (sensorState1 == LOW) {
        intCounter++;
       }
    }
    lastSensorState1 = sensorState1;
  }

Erkens15:
My sensors are wired directly to a breadboard.

Okay, sensors, but which? Some only pull down when activated for example :slight_smile:

Erkens15:
For the #include <avr/pgmspace.h>, i suppose this is not a standard library and thus requiring me to download it first?

Nope, it’s standard.

Erkens15:
For the mistake in the state change detection, it seems i need to put the “lastSensorState1 = sensorState1;” one } further, like so:

That doesn’t really matter. Trouble is, you only go looking for a change WHEN the pin is low. Drop that! Now the code is never executed when ‘sensorState1’ read HIGH. Just check if there was a change. And if there was a change, look if that change was falling / going low.

I’m using inductive proximity sensors, model number is LJ12A3-4-Z/BX.

I tried using the #include <avr/pgmspace.h> and char strFree PROGMEM= " free spots"; but it doesn’t seem to work for me, seeing as i get an error when compiling.

EDIT: Counter works now, going to rewire everything since i disconnected servos to program LCD and see if it still completely works.

Here is my current code:

#include <Servo.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>


int servoPin1 = 3;
int servoPin2 = 4;
int intCounter = 20;
String strFree = " free spots";

Servo ServoEntrance;
Servo ServoExit;

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

int sensorState1 = 0;
int lastSensorState1 = 0;
int sensorState2 = 0;
int lastSensorState2 = 0;

void setup() {
  ServoEntrance.attach(servoPin1);
  ServoExit.attach(servoPin2);

  lcd.begin(16, 2);

  pinMode(22, INPUT);
  pinMode(24, INPUT);
  pinMode(26, INPUT);
  pinMode(28, INPUT);
}
void loop() {

  sensorState1 = digitalRead(24);
  sensorState2 = digitalRead(28);

  if (digitalRead(22) == LOW)
  {
    ServoEntrance.write(90);
  }
    if (sensorState1 != lastSensorState1) {
      if (sensorState1 == LOW) {
        ServoEntrance.write(0);
        intCounter++;
       }
      lastSensorState1 = sensorState1;
    }

  if (digitalRead(26) == LOW)
  {
    ServoExit.write(90);
  }

    if (sensorState2 != lastSensorState2) {
      if (sensorState2 == LOW) {
        ServoExit.write(0);
        intCounter--;
      }
    lastSensorState2 = sensorState2;
    }

  String strDisplay = intCounter + strFree;

  if (intCounter > 0 && intCounter < 21)
  {
    lcd.setCursor(0, 0);
    lcd.print(strDisplay);
    lcd.setCursor(0, 1);
    lcd.print(time);
  }
  else
  {
    lcd.setCursor(0, 0);
    lcd.print("No free spots");
    lcd.setCursor(0, 1);
    lcd.print(time);
  }
}

Erkens15:
I’m using inductive proximity sensors, model number is LJ12A3-4-Z/BX.
[…]
EDIT: Counter works now, going to rewire everything since i disconnected servos to program LCD and see if it still completely works.

I’m quite surprised actually. Because that sensor is a Normally Open (NO) NPN type. Which would need an pull up resistor to work reliable. ::slight_smile:

Erkens15:
I tried using the #include <avr/pgmspace.h> and char strFree PROGMEM= " free spots"; but it doesn’t seem to work for me, seeing as i get an error when compiling.

Might be, you do some stuff you can do with a String but not with a string. But the errors will try to tell you what the problem is.

Now I’m here to teach others how to program, not really how to get a single project done. So if you also want to learn you have quite some tips still to incorporate :wink: And no, you wouldn’t be the first newbie to find them annoying. But trust me, when you start making bigger programs you’re glad you’re following them :wink: