Hi and thanks for looking at this thread. I've been hacking around with this for the past few evenings so it is probably a bit of a mess but I cannot get the code below to work as expected and I cannot see what is wrong with it.
The intent is that the Arduino receives an interrupt on interrupt 0 (pin 2) and then sends a short burst of 40kHz on pin 3. The interrupt is a little complex because it comes in over a radio receiver as a pulse train but that bit is working, in fact it all works except for sending the 40kHz burst. The timer code for this is correct, and it always sends one burst at start up but then does not send anymore, however the "transmitPing" method gets called because I see output on the serial console.
I assume something is disabling the timer or the pin but cannot see what.
const int TOL = 10; //frequency tolerence in uS
const int freqBounds[] = {200-TOL, 200+TOL};
const int LED = 13;
const byte DRIVE = 3; // Timer 2 "B" output: OC2B pin 9 on the mega
const long frequency = 40000L; // Hz
volatile unsigned long prevTime;
volatile unsigned long curTime;
volatile boolean sendPing;
volatile int pulseCount;
volatile boolean trigPending;
//debug
volatile unsigned long irpStart;
volatile unsigned long irpEnd;
volatile unsigned long timings[12];
volatile int tct = 0;
void setup() {
attachInterrupt(0, trigger, RISING); //interupt 0 - pin 2 on the nano
Serial.begin(9600); // open the serial port at 9600 bps:
trigPending = false;
setupUltrasonic();
}
void setupUltrasonic()
{
pinMode (DRIVE, OUTPUT);
digitalWrite(DRIVE, LOW);
TCCR2A = _BV (WGM20) | _BV (WGM21) | _BV (COM2B1); // fast PWM, clear OC2B on compare
OCR2A = ((F_CPU / 8) / frequency) - 1; // zero relative
OCR2B = ((OCR2A + 1) / 2) - 1; // 50% duty cycle
} // setupUltrasonic
void loop() {
if(sendPing) {
transmitPing();
pulseCount = 0;
sendPing = false;
digitalWrite(LED, HIGH);
delay(100);
digitalWrite(LED, LOW);
//dumpTimes();
}
else {
digitalWrite(LED, LOW);
//debug
if(pulseCount > 9) Serial.println(">>>>> Counter overflow <<<<<");
}
//debugging, only dump if not in the middle of a pluse train
//if(pulseCount == 0) dumpTimes();
if(pulseCount == 0) {
//tct = 0;
//dumpTimes();
}
}
void dumpTimes() {
String msg = String();
//int irpDur = irpEnd - irpStart;
//msg = "Interrupt duration: " + String(irpDur) +
// ", " + String(irpStart) + ", " + String(irpEnd);
int d = curTime - prevTime;
msg = "d, prev, cur " + String(d) + ", " + String(prevTime) + ", " + String(curTime);
Serial.println(msg);
Serial.print("Timings:\t");
for(int i=0; i<12; i++) {
msg = String(timings[i]) + "\t";
timings[i] = 0;
Serial.print(msg);
}
Serial.println();
}
void trigger() {
//Rising edge interrupt
prevTime = curTime;
curTime = micros();
irpStart = curTime;
//allow a variation around 100us
int d = curTime-prevTime;
int d2 = d/2;
int d15 = d/1.5; //the period from short rising edge to long rising edge
//is d/1.5 not d/2
if (d > freqBounds[0] && d < freqBounds[1]) {
//in-tolerance signal
trigPending = true;
}
else if(trigPending &&
(d2 > freqBounds[0] && d2 < freqBounds[1])
|| (d15 > freqBounds[0] && d15 < freqBounds[1])){
pulseCount++;
sendPing = pulseCount == 2;
}
else {
//not a valid pulse width so restart
pulseCount = 0;
trigPending = false;
timings[0] = d;
}
//debug
if(tct > 11) tct = 0;
timings[tct++] = d;
irpEnd = micros();
}
void transmitPing() {
//setupUltrasonic();
//start the ping
TCCR2B = _BV (WGM22) | _BV (CS21); // fast PWM, prescaler of 8
delay(100);
TCCR2B = _BV (WGM22) ; // fast PWM, timer off
digitalWrite(DRIVE, LOW);
Serial.println(">>>>> PING SENT <<<<<");
}