Sensor count questions

Hey all!
I've been trying to make a programme for an IR tachometer with an IR sensor, and I've been having no luck. The main problem I run into is that the results from my programme is very random and I don't have a clue why. here's what I'm trying to do

Check if the sensor is on
    if yes, add 1 to counter
    if not, do nothing

and repeat it per second, print the counter at the end of the loop

It shouldn't be too hard, but this is my first programme so I have no clue what I'm doing. Also I'm intergating a ESC controller into the programme, so that will also be displayed.

/*
 ESC to D9
 Sensor to D8
 Potentiometer to A0
 Screen to SDA/SCL respectively
 GND/VCC to breadboard
 */
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include <Servo.h>

//Display&sensor
#define Backlight_Pin 13
//#define sensor 8
int initial=0;
//int REV=0;
//int prevtime=0;
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

//ESC
Servo ESC;     // create servo object to control the ESC
int potValue;  // value from the analog pin

//Calculation
int sensorVal;
int start;
int val = 0;
unsigned int count = 0;



void setup() {
  pinMode(8,INPUT);
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.clear();
  ESC.attach(9, 1000, 2000);
  pinMode(8,INPUT);
}
void loop() {
  //Calculation
 start = millis();
 while (millis()-start <= 1000){
 sensorVal = digitalRead(8);
  if (sensorVal == 0){
    count ++;
    val = count;
  }
 }
 if (millis()-start > 1000){
  start = millis();
 }

Serial.println(val);
  
//ESC
  potValue = analogRead(A0);   // reads the value of the potentiometer (value between 0 and 1023)
  potValue = map(potValue, 0, 1023, 0, 180);   // scale it to use it with the servo library (value between 0 and 180)
  ESC.write(potValue);    // Send the signal to the ESC
}

and these are the results that I get from serial print

0
-18721
22502
27485
-945
-27102
9386
14099
-8628
-5658
-32368
6290
-11366
27172
-7108
30951
2265
-27729
18529
-10478
-9145
23157
-7499
-6513

Any help will be appreciated. Thanks!

Are you deliberately not resetting count to zero in the program ?

Checking if millis() - start > 1000 seems pointless as it will never reach this line until it is true anyway.

What happens to count if there is no motion and the sensor is blocked (sensorVal = = 0)?

Check out the state-change example in the IDE

SeaScorpion:
Any help will be appreciated. Thanks!

You don't say how fast the thing is rotating - how many pulses per second need to be counted.

It may help to define the variables count and val as unsigned long rather than int

Also, variables associated with millis() should always be unsigned long.

This link has code derived from a program I have used to control the speed of a small DC motor.

...R

UKHeliBob:
Are you deliberately not resetting count to zero in the program ?

I would like to do that, except I have no clue how to...

Isn't the point of a tachometer to count the number of changes in a given time?

SeaScorpion:
I would like to do that, except I have no clue how to...

count = 0;

Is that literelly it...

SeaScorpion:
Is that literelly it...

Yes, that is all you need to set the count variable back to zero. You sound surprised

 start = millis();
 while (millis()-start <= 1000){
 sensorVal = digitalRead(8);
  if (sensorVal == 0){
    count ++;
    val = count;
  }
 }

  start = millis();
  count=0;
 

Serial.println(val);

so something like this? still gives the same result though.

start = millis();
 while (millis()-start <= 1000){
 sensorVal = digitalRead(8);
  if (sensorVal == 0){
    count ++;
    val = count;
  }
 }

With this code, you are counting multiple times when the sensor is LOW.

You were given previous advice which you did not follow.

Check out the state-change example in the IDE

You want to count a pulse on a state change transition where HIGH>LOW or LOW>HIGH
You will need a new variable to hold the last sensor reading to compare to the current sensor reading.

Here's the method

lastSensorVal = sensorVal;
 sensorVal = digitalRead(8);
  if (sensorVal == 0 && lastSensorVal == 1)//falling state change
  {
    count ++;
  }
 
 if (millis()-start > 1000)//reporting interval
 {
  start = millis();
  Serial.println(count);
  count = 0;
 }

Do you have a pullup or pulldown resistor on the sensor output?

Could you elaborate please? The sensor was a pre build, so all I did was connect the VCC, GND and OUT pins.

Why have you not posted a link to your sensor product page or data sheet?

Please read and follow the instructions in the How to use this forum post.

Sorry didn't read that... Here's the Data sheet

http://irsensor.wizecode.com/

The sensor is an IR-08H, and the above sheet is the closest one I could find. Bought the sensor off a friend of mine, and he didn't have the original packaging and forgot where he got it.

SeaScorpion:
Sorry didn't read that... Here's the Data sheet

http://irsensor.wizecode.com/

Note filename of attachment.

make links clickable.png

make links clickable.png

The sensor is an IR-08H, and the above sheet is the closest one I could find.

Output signal: TTL level
LOW level if obstacle detected
HIGH if no obstacle detected

This says that there is active output from the sensor, and you will be OK without other pullups.

If you are still having trouble with detecting the transition from HIGH to LOW please explain more about what you are detecting and how fast it is rotating.

cattledog:
This says that there is active output from the sensor, and you will be OK without other pullups.

If you are still having trouble with detecting the transition from HIGH to LOW please explain more about what you are detecting and how fast it is rotating.

Currently the detection from high to low is working at slow paces, and I haven't had the ability to test it properly yet. The test object is a spinning propeller on a brushless motor, spinning at a max 8000-13000 RPM depending on the rotor. This speed can be decreased, though, as I only need to take about 5-10 different data sets.

The background is: I'm investigating the relationship between lift force and the RPM of a rotor, ignoring all other components of force. I haven't yet tested if the IR sensor can take 13000 RPM yet, though. Still figuring out the code for controlling the rotor.

ps. Sorry if I'm nerding out over physics a bit, but I figured it'll be alright here.

The test object is a spinning propeller on a brushless motor, spinning at a max 8000-13000 RPM depending on the rotor.

At those speeds you are likely to require an interrupt based routine.

There are different ways to do it. Robin2 has linked to one method in reply #4 which looks at the time between pulses. This method can be extended to look at the time taken for a number of pulses. Alternatively you can look at the number of pulses in a fixed interval of time.

Pulses can be captured on an io pin with an external interrupt. Alternatively a timer using input capture or a time gated external clock source can be used.

I would suggest that you take a look at two libraries frequently used for this purpose

FreqCount Library and FreqMeasure Library

cattledog:
Alternatively you can look at the number of pulses in a fixed interval of time.

IMHO that will always be slightly less accurate by the amount of time between successive pulses. In any time period you could just barely catch, or just barely miss the final pulse.

...R