I think I got it. Here is the setup: I have arduino #1 that puts out six pulses by writing high and low to a digital pin and waiting a couple microseconds. I have it perform the series of pulses every 10 mS 3x. If I need another set of samples I press the reset button. BlinkSlave4.ino is arduino#1 code.
void setup() {
// initialize digital pin 13 as an output.
pinMode(13, OUTPUT);
pinMode(2, OUTPUT);
// Demonstrate successful reboot with 3 blinks
digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(13, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(13, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(13, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
event();
delay(10);
event();
delay(10);
event();
delay(10);
}
void event(){
uint8_t delayTime = 5;
PORTD |= B00000100;
PORTD &= B11111011;
delayMicroseconds(delayTime);
PORTD |= B00000100;
PORTD &= B11111011;
delayMicroseconds(delayTime);
PORTD |= B00000100;
PORTD &= B11111011;
delayMicroseconds(delayTime);
PORTD |= B00000100;
PORTD &= B11111011;
delayMicroseconds(delayTime);
PORTD |= B00000100;
PORTD &= B11111011;
delayMicroseconds(delayTime);
PORTD |= B00000100;
PORTD &= B11111011;
delayMicroseconds(delayTime);
}
void loop() {
}
It is connected to arduino #2 D8 with a pull down resistor of 100 ohms to cancel out noise. #2 is running FrequencyCounter.ino:
// Frequency timer using input capture unit
// Author: Nick Gammon
// Date: 31 August 2013
// Input: Pin D8
volatile boolean first;
volatile boolean second;
volatile boolean third;
volatile boolean fourth;
volatile boolean fifth;
//volatile boolean sixth;
volatile boolean triggered;
volatile unsigned long Time1;
volatile unsigned long Time2;
volatile unsigned long Time3;
volatile unsigned long Time4;
volatile unsigned long Time5;
volatile unsigned long Time6;
ISR (TIMER1_CAPT_vect)
{
// grab counter value before it changes any more
uint16_t timer1CounterValue;
timer1CounterValue = ICR1; // see datasheet, page 117 (accessing 16-bit registers) is this reading 16 or 8 bits?
// wait until we noticed last one
if (triggered)
return;
if (first)
{
Time1 = timer1CounterValue;
first = false;
second = true;
return;
}
if (second)
{
Time2 = timer1CounterValue;
second = false;
third = true;
return;
}
if (third)
{
Time3 = timer1CounterValue;
third = false;
fourth = true;
return;
}
if (fourth)
{
Time4 = timer1CounterValue;
fourth = false;
fifth = true;
return;
}
if (fifth)
{
Time5 = timer1CounterValue;
fifth = false;
return;
}
Time6 = timer1CounterValue;
triggered = true;
TIMSK1 = 0; // no more interrupts for now. consider revising if using multiple sensors.
} // end of TIMER1_CAPT_vect
void prepareForInterrupts ()
{
noInterrupts (); // protected code
first = true;
second = false;
third = false;
fourth = false;
fifth = false;
// sixth = false;
triggered = false; // re-arm for next time
// reset Timer 1
TCCR1A = 0;
TCCR1B = 0;
TIFR1 = bit (ICF1) | bit (TOV1); // clear flags so we don't get a bogus interrupt
TCNT1 = 0; // Counter to zero
// overflowCount = 0; // Therefore no overflows yet
// Timer 1 - counts clock pulses
// TIMSK1 = bit (TOIE1) | bit (ICIE1); // interrupt on Timer 1 overflow and input capture, Consider disabling timer overflow interrupt and maintain input capture interrupt.
TIMSK1 = bit (ICIE1); // interrup on timer1 only on input capture
// start Timer 1, no prescaler
TCCR1B = bit (CS10) | bit (ICES1); // plus Input Capture Edge Select rising on D8 and no prescaler
interrupts ();
} // end of prepareForInterrupts
void setup ()
{
Serial.begin(250000);
Serial.println("Frequency Counter");
// set up for interrupts
prepareForInterrupts ();
} // end of setup
void loop ()
{
// wait till we have a reading
if (!triggered)
return;
// period is elapsed time
unsigned long deltaTime1 = Time2 - Time1;
unsigned long deltaTime2 = Time3 - Time2;
unsigned long deltaTime3 = Time4 - Time3;
unsigned long deltaTime4 = Time5 - Time4;
unsigned long deltaTime5 = Time6 - Time5;
Serial.print ("T1,T2,T3,T4,T5,T6: ");
Serial.print (Time1);
Serial.print (", ");
Serial.print (Time2);
Serial.print (", ");
Serial.print (Time3);
Serial.print (", ");
Serial.print (Time4);
Serial.print (", ");
Serial.print (Time5);
Serial.print (", ");
Serial.print (Time6);
Serial.println (" timestamp. ");
Serial.print ("Took: ");
Serial.print (deltaTime1);
Serial.print (", ");
Serial.print (deltaTime2);
Serial.print (", ");
Serial.print (deltaTime3);
Serial.print (", ");
Serial.print (deltaTime4);
Serial.print (", ");
Serial.print (deltaTime5);
Serial.println (" cycles. ");
// period is elapsed time
unsigned long elapsedTime = ( deltaTime1 + deltaTime2 + deltaTime3 + deltaTime4 + deltaTime5 ) / 5;
// frequency is inverse of period, adjusted for clock period
float freq = F_CPU / float (elapsedTime); // each tick is 62.5 ns at 16 MHz
Serial.print ("Took: ");
Serial.print (elapsedTime);
Serial.print (" counts. ");
Serial.print ("Frequency: ");
Serial.print (freq);
Serial.println (" Hz. ");
// so we can read it
delay (500);
prepareForInterrupts ();
} // end of loop
I was able to collapse the pulses of arduino #1 such that arduino #2 would consistently read down to 62 cycles. That is pretty good! I was also able to repeat this every to 10ms. From here I see that I have two problems:
-
If the timer overflows, I need to be able to account for this with an if else statement. This isn't too difficult. I just need to know when the timer overflows. Does a timer count from 0 to 2^16-1 or 1 to 2^16? What is the last discreet number that exists and what does it start on upon overflow?
-
It would be nice to connect this to a square wave signal generator and observe the resolution by adjusting the frequency and observe changes on the serial monitor. Anybody have any suggestions that gets me to prove the accuracy and precision of this setup? Anybody able to do me a solid and run it on their equipment? I feel like using a different arduino is a self licking ice cream cone at this point.
FrequencyCounter.ino (3.98 KB)
BlinkSlave4.ino (1.96 KB)