Dana Mah
Created April 1, 2016

Real Time Target

Hardware to capture where a projectile hits a target.

AdvancedWork in progress3 hours830
Real Time Target

Things used in this project

Hardware components

General Purpose Quad Op-Amp
Texas Instruments General Purpose Quad Op-Amp
×1
555 or 556 Timer (generic)
555 or 556 Timer (generic)
×2
piezo element
×4
bc846
×4
5.1v zener diode
×8
Multi-Turn Precision Potentiometer- 10k ohms (25 Turn)
Multi-Turn Precision Potentiometer- 10k ohms (25 Turn)
×4
Resistor 1k ohm
Resistor 1k ohm
×4
Resistor 2.21k ohm
Resistor 2.21k ohm
×4
Resistor 1M ohm
Resistor 1M ohm
×5
Arduino Mega 2560
Arduino Mega 2560
I used a mega 2560, but any arduino with 4 hardware interrupts will work. If you dont have one, you could use pretty much any arduino with a code change to use the pin change interrupt instead of the hardware interrupts, you could accomplish the same thing.
×1

Story

Read more

Schematics

Schematic for target interface

It should be noted that the piezos should be attached to each corner of the target.

This circuit gave me the best results, but was still unstable. I was getting inconsistent results during testing. It seem to have crosstalk between the op-amps.
I'm not sure if it was because of the tolerances of the part or because I was using a breadboard to test the circuit it may have even been the piezos that I was using.

Basically the circuit will sense vibration from the target back board using the piezo. That signal is then amplified using the op-amp. The output triggers a 555 timer configured as a latch. The output of the latch is the input to one of the hardware interrupts of the arduino. Where the arduino will either start a counter if it hasn't been started or store a counter value for the piezo sensor activated.

Initially I was going to just use the arduinos analogue inputs to read the values of the 4 piezos, but after a bit of research, I found out the AD converter converts each input sequentially and at ~110uS per conversion my resolution would be ~37 mm minimum which compounded for each sensor read. I quickly found out that pretty much non of the current arduinos would be fast enough to give me 1 -2 mm resolution. In order to get that kind of resolution I would have to read all 4 sensors in about 4uS. I did more research, and found out I can read a full port in an arduino at once, I just had to be able to trigger the digital inputs with an analogue sensor. hence the circuit, its basically a 1 bit AD converter.

To get even better resolution, I decided to connect this circuit to the hardware interrupts of the arduino. This allowed me to code interrupt routines. The first interrupt routine activated would start a 16 bit counter and when the other 3 interrupt routines are activated, they would store the value of the counter at that time. The reason to use the 16 bit counter is because it would give a time frame of about 4 ms way more then need. That is calculated by taking the clock frequency 16MHz and getting the time for each pulse 1/16000000 = 62.5 nano seconds. Take the 62.5 nS * 65536 and that gives you ~4mS

Code

Arduino Code

Arduino
The way to find the x and y coordinates is to do the following

X1 = TimeA / (TimeA + TimeB)
X2 = TimeC / (TimeC + TimeD)
Y1 = TimeA / (TimeA + TimeC)
Y2 = TimeB / (TimeB + TimeD)
X = (X1 + X2) / 2
Y = (Y1 + Y2) / 2
#define sensorReset 17

unsigned long lastTriggerTime;
boolean transmitted = false;
volatile unsigned long triggerTimeA;
volatile unsigned long triggerTimeB;
volatile unsigned long triggerTimeC;
volatile unsigned long triggerTimeD;
volatile boolean triggeredA;
volatile boolean triggeredB;
volatile boolean triggeredC;
volatile boolean triggeredD;

void isrA ()
{
  if (TCNT1 == 0){
    TCCR1B |= (1 << CS10);
  }
  triggerTimeA = TCNT1;
  triggeredA = true;
  detachInterrupt(5);
}  // end of isr

void isrB ()
{
  if (TCNT1 == 0){
    TCCR1B |= (1 << CS10);
  }
  triggerTimeB = TCNT1;
  triggeredB = true;
  detachInterrupt(4);
}  // end of isr

void isrC ()
{
  if (TCNT1 == 0){
    TCCR1B |= (1 << CS10);
  }
  triggerTimeC = TCNT1;
  triggeredC = true;
  detachInterrupt(3);
}  // end of isr

void isrD ()
{
  if (TCNT1 == 0){
    TCCR1B |= (1 << CS10);
  }
  triggerTimeD= TCNT1;
  triggeredD = true;
  detachInterrupt(2);
}  // end of isr

ISR(TIMER1_OVF_vect)        
{
  TCNT1 = 0;            // preload timer
  attachInterrupt(5, isrA, RISING);
  attachInterrupt(4, isrB, RISING);
  attachInterrupt(3, isrC, RISING);
  attachInterrupt(2, isrD, RISING);
  digitalWrite(sensorReset, LOW);
  //digitalWrite(sensorReset, HIGH);
}

void setup()
{
  pinMode(sensorReset, OUTPUT);
  digitalWrite(sensorReset, HIGH);
  
  noInterrupts();
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  TIMSK1 |= (1 << TOIE1);
  interrupts();

  
  digitalWrite (2, HIGH);  // pull-up
  attachInterrupt(5, isrA, RISING);
  attachInterrupt(4, isrB, RISING);
  attachInterrupt(3, isrC, RISING);
  attachInterrupt(2, isrD, RISING);
  Serial.begin (115200);
  Serial.println ("Started timing ...");
}  // end of setup

void loop()
{
  if (!triggeredA || !triggeredB || !triggeredC || !triggeredD){
    return;
  }

  long elapsed = triggerTimeA - triggerTimeB;
  Serial.println ("A: ");
  Serial.print (triggerTimeA);
  Serial.println ("B: ");
  Serial.print (triggerTimeB);
  Serial.println ("C: ");
  Serial.print (triggerTimeC);
  Serial.println ("D: ");
  Serial.print (triggerTimeD);
  Serial.println ("  ");
  transmitted = true;

  if (transmitted)
  {
    triggeredA = false;
    triggeredB = false;
    triggeredC = false;
    triggeredD = false;
    triggerTimeA = 0;
    triggerTimeB = 0;
    triggerTimeC = 0;
    triggerTimeD = 0;
    elapsed = 0;
    transmitted = false;
  }
}  // end of loop

Credits

Dana Mah

Dana Mah

12 projects • 27 followers
I'm a hobbyist interested in microcontroller solutions to simple problems.

Comments