Detecting a high speed object with a phototransistor.

Hello.

I’m trying to create an airsoft pellet counter with two seven segment displays. For detecting pellets I used a phototransistor (http://www.ges.cz/sheets/b/bpw42.pdf) and a bright red LED which created a gate at the end of muzzle. The sensor’s analog value is around ~30 when the led emits light and 1023 when there’s an object blocking the light. Everything works perfectly but the sensor doesn’t register a pellet traveling 110m/s. It does register a pen though. The diameter of a pellet is 6mm. I used this code:

const int A = 6;
const int B = 7;
const int C = 8;
const int D = 9;
const int E = 10;
const int F = 11;
const int G = 12;
const int mltx_pin = 5;
const int sensor_pin = A0;

boolean mltx_val = true;
boolean tick = true;
int count = 68;
int cycle = 0;
int zero_blink = 0;

void setup()
{
  pinMode(A, OUTPUT);
  pinMode(B, OUTPUT);
  pinMode(C, OUTPUT);
  pinMode(D, OUTPUT);
  pinMode(E, OUTPUT);
  pinMode(F, OUTPUT);
  pinMode(G, OUTPUT); 
  pinMode(mltx_pin, OUTPUT); 
  
  Serial.begin(9600);
}

void mltx_reverse()
{
  if (mltx_val==false)
  {mltx_val=true;}
  else
  {mltx_val=false;} 
}

void no_blank()
{
  digitalWrite(A, HIGH); 
  digitalWrite(B, HIGH); 
  digitalWrite(C, HIGH); 
  digitalWrite(D, HIGH); 
  digitalWrite(E, HIGH); 
  digitalWrite(F, HIGH); 
  digitalWrite(G, HIGH); 
}

void no_0()
{
  digitalWrite(A, LOW); 
  digitalWrite(B, LOW); 
  digitalWrite(C, LOW); 
  digitalWrite(D, LOW); 
  digitalWrite(E, LOW); 
  digitalWrite(F, LOW); 
  digitalWrite(G, HIGH); 
}

void no_1()
{
  digitalWrite(A, HIGH); 
  digitalWrite(B, LOW); 
  digitalWrite(C, LOW); 
  digitalWrite(D, HIGH); 
  digitalWrite(E, HIGH); 
  digitalWrite(F, HIGH); 
  digitalWrite(G, HIGH); 
}

void no_2()
{
  digitalWrite(A, LOW); 
  digitalWrite(B, LOW); 
  digitalWrite(C, HIGH); 
  digitalWrite(D, LOW); 
  digitalWrite(E, LOW); 
  digitalWrite(F, HIGH); 
  digitalWrite(G, LOW); 
}

void no_3()
{
  digitalWrite(A, LOW); 
  digitalWrite(B, LOW); 
  digitalWrite(C, LOW); 
  digitalWrite(D, LOW); 
  digitalWrite(E, HIGH); 
  digitalWrite(F, HIGH); 
  digitalWrite(G, LOW); 
}

void no_4()
{
  digitalWrite(A, HIGH); 
  digitalWrite(B, LOW); 
  digitalWrite(C, LOW); 
  digitalWrite(D, HIGH); 
  digitalWrite(E, HIGH); 
  digitalWrite(F, LOW); 
  digitalWrite(G, LOW); 
}

void no_5()
{
  digitalWrite(A, LOW); 
  digitalWrite(B, HIGH); 
  digitalWrite(C, LOW); 
  digitalWrite(D, LOW); 
  digitalWrite(E, HIGH); 
  digitalWrite(F, LOW); 
  digitalWrite(G, LOW); 
}

void no_6()
{
  digitalWrite(A, HIGH); 
  digitalWrite(B, HIGH); 
  digitalWrite(C, LOW);
  digitalWrite(D, LOW); 
  digitalWrite(E, LOW); 
  digitalWrite(F, LOW); 
  digitalWrite(G, LOW); 
}

void no_7()
{
  digitalWrite(A, LOW); 
  digitalWrite(B, LOW); 
  digitalWrite(C, LOW); 
  digitalWrite(D, HIGH); 
  digitalWrite(E, HIGH); 
  digitalWrite(F, HIGH); 
  digitalWrite(G, HIGH); 
}

void no_8()
{
  digitalWrite(A, LOW); 
  digitalWrite(B, LOW); 
  digitalWrite(C, LOW); 
  digitalWrite(D, LOW); 
  digitalWrite(E, LOW); 
  digitalWrite(F, LOW); 
  digitalWrite(G, LOW); 
}

void no_9()
{
  digitalWrite(A, LOW); 
  digitalWrite(B, LOW); 
  digitalWrite(C, LOW); 
  digitalWrite(D, HIGH); 
  digitalWrite(E, HIGH); 
  digitalWrite(F, LOW); 
  digitalWrite(G, LOW); 
}


void loop()
{
  //CONTROL MULTIPLEX 
  if (mltx_val==true)
  {
    digitalWrite(mltx_pin, LOW);
  }
  else
  {
    digitalWrite(mltx_pin, HIGH); 
  }
  
  //RESET COUNTER
  if (count<0)
  {
    count=68; 
  }
  
  //READ SENSOR
  int sensor_value=analogRead(sensor_pin); 

  if (tick==false)
  {
    if (sensor_value<100)
    {
      tick=true;
      count-=1;
    } 
  }
  else
  {
    if (sensor_value>150)
    {
      tick=false;
    } 
  }
  
  Serial.print("sensor_value = ");                       
  Serial.print(sensor_value);
  Serial.print("\t count = ");      
  Serial.print(count); 
  Serial.print("\t tick = ");      
  Serial.println(tick); 
  
  if (zero_blink<500)
  {
    if (cycle==0)
    {
      //DO STUFF
      if (mltx_val==true)
      {
          //DRAW ONES
          int val=floor(count/10);
            
          if (val==0) {no_0();}
          if (val==1) {no_1();}
          if (val==2) {no_2();}
          if (val==3) {no_3();}
          if (val==4) {no_4();}
          if (val==5) {no_5();}
          if (val==6) {no_6();}
          if (val==7) {no_7();}
          if (val==8) {no_8();}
          if (val==9) {no_9();}    
      }
      else
      {
          //DRAW TENS
          int val=count-(floor(count/10)*10);
        
          if (val==0) {no_0();}
          if (val==1) {no_1();}
          if (val==2) {no_2();}
          if (val==3) {no_3();}
          if (val==4) {no_4();}
          if (val==5) {no_5();}
          if (val==6) {no_6();}
          if (val==7) {no_7();}
          if (val==8) {no_8();}
          if (val==9) {no_9();} 
      }
    }
    else
    {
      no_blank(); 
    }
  }
  else
  {
    no_blank(); 
  }
  
  
  zero_blink+=1;
  
  if (zero_blink>1000 || count>9)
  {
    zero_blink=0; 
  }
  
  cycle+=1;
  
  if (cycle>2)
  {
    cycle=0;
    mltx_reverse();
  }
}

The code does 10000 cycles in about 6 seconds which is 0.6ms per cycle. A pellet travels 110mm/ms which means for each cycle the pellet travels 66mm. I even simplified the code to this:

const int analogInPin = A0;

int counter = 0;
boolean tick = false;

void setup() {
  Serial.begin(9600); 
}

void loop() {
  
  int sensorValue = analogRead(analogInPin);                    

  if (tick==false)
  {
    if (sensorValue<250)
    {
      tick=true;
      counter+=1;
    } 
  }
  else
  {
    if (sensorValue>280)
    {
      tick=false;
    } 
  }

  Serial.print("sensor = ");                       
  Serial.print(sensorValue);
  Serial.print("\t counter = ");      
  Serial.print(counter); 
  Serial.print("\t tick = ");      
  Serial.println(tick);                 
}

Same result. What should I do? I have Arduino Micro.

You could try using one of the two external interrupts to detect rising edges:

unsigned long count = 0;

void counter() {
    count++;
}

void setup() {
    Serial.begin(19200);
    attachInterrupt(0, counter, RISING);  // Call counter() for each rising edge on Pin 2 (INT 0)
}

loop() {
   delay(1000); // wait a second
   Serial.println(count);
}

Hey John, How much snow did you get? We got 16-17", wet heavy stuff. Had my driveway all cleared, big grader with a plow just cleared the street some more, now I have another wall of really packed snow to clear out. Ugh.

If possible, you should see what it looks like on an oscilloscope. At that speed, the ball takes a little under 55uS to travel its diameter. Your loop cycle time is approximately 10 times that long. You have too much other stuff going on to be looking for it like you are, you really need something to use interrupts of some kind. At what rate do the balls come? The datasheet leaves it a mystery when it comes to how fast the transistor is, no information on that. That's why it'd be nice to see how it looks on the scope.

http://www.cameraaxe.com/wiki/index.php?title=Sensors#Projectile_Sensor

Lots of discussion on that projectile sensor if you dig around a bit.

CrossRoads: Hey John, How much snow did you get? We got 16-17", wet heavy stuff. Had my driveway all cleared, big grader with a plow just cleared the street some more, now I have another wall of really packed snow to clear out. Ugh.

I saw a the neighboring town claim 21 inches on a newscast. I think we got about 18 inches. We would have gotten much more accumulation if most of Thursday had not been rain.