Counter of light change

Hi all
I try to use a Phototransistor to count objects passing a tube.

I have already a lot of code but there is still a problem:
If I use this code...

/if (senseSignal < 450)
{

buttonPresses++;

lcd.setCursor(0,1);
lcd.print (buttonPresses);
}

...the counter is counting many times during the object passes the phototransistor.
For Ex.: I put my hand over the transistor and during this time the counter counts from 1 to 21.
But I would like the counter to ad 1 after or while my hand covers the phototransistor.

Is There any possibility to solve my problem without using other Hardware?

Her is the complete code:

[/#include <LiquidCrystal.h>

LiquidCrystal lcd(12,11,10,7,6,5,4); //Pins für Disply werden festgelegt

//Zähler:

int buttonPresses = 0;      // Wie oft ist der Schalter gedrückt   

//Lichtschranke:
int sensePin = 0;
int senseSignal;     //geänderter Wert

 

void setup() 
  { 
  //Zähler:
  Serial.begin(9600);                     // Start der seriellen Kommunikation mit 9600bps 
  lcd.begin(16,4);
  lcd.setCursor(0,0);
  lcd.print("100% i.O.  Dobry");
  
  //Lichtschranke:
  Serial.begin(9600);
  pinMode(13, INPUT);                  //Pullup für Sensor
  digitalWrite(13,HIGH);               //Pullup aktivieren 
  senseState = analogRead(sensePin);   //Anfangszustand lesen
  


}     

void loop()
{   
  //Lichtschranke:
  senseSignal = analogRead(sensePin);
  
  if (senseSignal < 450) 
  {       
 
    buttonPresses++; 
    // Inkrementieren der Variablen buttonPresses 
  
  
  
    Serial.print("Schalter wurde "); 
    Serial.print(buttonPresses); 
    Serial.println(" gedrueckt");
   lcd.setCursor(0,1);
   lcd.print (buttonPresses);
  }}]

What you're looking for is edge detection. Edge detection is accomplished by keeping track of the last value read. The "edge" occurs when your last senseSignal reading was >= 450 and your current reading is < 450. The pseudo code would be something like this.

get currentReading from sensor

if lastReading is less than 450 and currentReading is greater than or equal to 450
increment counter variable

set lastReading to currentReading

Simple enough to achieve.

At the moment, you are saying "While the input value is less than 450, add one to the count".

What you need is something more like:

"If the input value is less than 450 then add one to the count and wait for the input value to rise above 450."

You need to look for the object entering the beam and leaving the beam - not just its presence within the beam.

Thanks a a lot. I think I understand.

How can I get this into code? Im not very advanced?:

if lastReading is less than 450 and currentReading is greater than or equal to 450
increment counter variable

set lastReading to currentReading

That should certainly be a way of doing it, yes.

like this?

[/  if (senseState > 450) 
  {  if senseSignal < 450)
 
    {buttonPresses++; 
    // Inkrementieren der Variablen buttonPresses 
    }}
  
  
    Serial.print("Schalter wurde "); 
    Serial.print(buttonPresses); 
    Serial.println(" gedrueckt");
   lcd.setCursor(0,1);
   lcd.print (buttonPresses);
  }}]
if (senseState > 450) 
  {  if senseSignal < 450)

I have no idea what these variables are in the context of your code, so I can't say, but I can tell you that neither of those take into account if the value is exactly 450.

Ok. The Programm looks now like this... But the serial shows constantly 0 button presses. Can you give me any advice.

[/#include <LiquidCrystal.h>

LiquidCrystal lcd(12,11,10,7,6,5,4); //Pins für Disply werden festgelegt

//Zähler:

int buttonPresses = 0;      // Wie oft ist der Schalter gedrückt   

//Lichtschranke:
int sensePin = 0;
int senseState;      //Anfangszustand
int senseSignal;     //geänderter Wert

 

void setup() 
  { 
  //Zähler:
  Serial.begin(9600);                     // Start der seriellen Kommunikation mit 9600bps 
  lcd.begin(16,4);
  lcd.setCursor(0,0);
  lcd.print("100% i.O.  Dobry");
  
  //Lichtschranke:
  Serial.begin(9600);
  pinMode(13, INPUT);                  //Pullup für Sensor
  digitalWrite(13,HIGH);               //Pullup aktivieren 
 
  


}     

void loop()
{   
  //Lichtschranke:
  senseState = analogRead(sensePin);
  
  
  
  
  if (senseState > 450) 
  {  
    senseSignal= analogRead(sensePin);
    
    if (senseSignal < 450)    
   
   {
     buttonPresses++;  // Inkrementieren der Variablen buttonPresses 
     senseState = senseSignal;
   }  
  
  }
  
  
   
    Serial.print(buttonPresses); 
   
 lcd.setCursor(0,1);
   lcd.println (buttonPresses);
   delay(500);
  }]

You're resetting senseState every time through the loop. You should set the initial value only once in the setup() routine.

Ok. I did this. But there must be an other mistake. Ofter the first contact a 1 appeared. But than nothing happened.

Here is a little sketch I have knocked together which uses the Serial port to display the transition values. Use it for inspiration :wink:

int inState;

void setup()
{
  Serial.begin(9600);
  inState = analogRead(0);
}

void loop()
{
  int state;
  state = analogRead(0);
  if(state <= 512)
  {
    if(inState > 512)
    {
      Serial.print(inState);
      Serial.print(" => ");
      Serial.println(state);
    }
  }
  inState = state;
}

Basically it's:

  1. Is the input value in the "on" region?
  2. Yes: Is the previous value in the "off" region?

  3. Yes: Do something interesting

  4. Store the current value as the previous one.
  if (senseState > 450) 
  ...
     senseState = senseSignal;

Just look at that small part. senseState will ONLY change if it is greater than 450. That means, that after the first transition, it is set to something less than 450, and never changes. Thus, that first if statement will ALWAYS fail thereafter.

You should consider using Serial.print to help debug your code. Seeing the value of senseState stay the same after the first transition would have clued you in to your assignment being in the wrong place.