void setup()
{
pinMode(freqOutputPin, OUTPUT);
Serial.begin(9600);
// Set Timer 2 CTC mode with no prescaling. OC2A toggles on compare match
//
// WGM22:0 = 010: CTC Mode, toggle OC
// WGM2 bits 1 and 0 are in TCCR2A,
// WGM2 bit 2 is in TCCR2B
// COM2A0 sets OC2A (arduino pin 11 on Uno or Duemilanove) to toggle on compare match
//
TCCR2A = ((1 << WGM21) | (1 << COM2A0));
// Set Timer 2 No prescaling (i.e. prescale division = 1)
//
// CS22:0 = 001: Use CPU clock with no prescaling
// CS2 bits 2:0 are all in TCCR2B
TCCR2B = (1 << CS20);
// Make sure Compare-match register A interrupt for timer2 is disabled
TIMSK2 = 0;
// This value determines the output frequency
OCR2A = ocr2aval;
Serial.print("Period = ");
Serial.print(period);
Serial.println(" microseconds");
Serial.print("Frequency = ");
Serial.print(freq);
Serial.println(" Hz");
}
void loop(){}
I am working on a project where i need an ultrasonic pulse of 8Mhz every one second and emitter is piezo disc. Please help me with the code.
-
If you are using an AVR-based Arduino, read Timers and counters, by Nick Gammon.Edgar Bonet– Edgar Bonet2018年11月12日 21:48:31 +00:00Commented Nov 12, 2018 at 21:48
-
That's an interesting article, but it seems to be about detecting pulses, not making them. Did I miss something?Hack Saw– Hack Saw2018年11月12日 21:53:41 +00:00Commented Nov 12, 2018 at 21:53
-
actually i need both emission and detection but currently i am working on emitting the pulses using arduino and piezo discs but i am not so good with codingDanish– Danish2018年11月12日 21:59:25 +00:00Commented Nov 12, 2018 at 21:59
-
what code have you tried so far?MichaelT– MichaelT2018年11月12日 22:01:28 +00:00Commented Nov 12, 2018 at 22:01
-
ive embedded the code aboveDanish– Danish2018年11月12日 22:16:45 +00:00Commented Nov 12, 2018 at 22:16
1 Answer 1
With 8 Mhz pulse, I assume you mean a pulse of 0.125 μs duration every second. "Frequency" may be misleading here.
Since the ATmega328 in the Arduino Uno is only clocked at 16 Mhz, you only have one extra cycle before having to turn it back off. Debugging and developing at this sort of speed absolutely requires a good oscilloscope.
I would attempt setting your output pin via register, and then turning it off again right after. Use cli()
to prevent interrupts during your desired pulse.
void setup() {
DDRC |= (1 << DDRC0); //Set PC0 as output (Analog Pin 0)
}
void loop() {
cli(); //Disable interrupts
PORTC = 0b00000001; //Set Analog Pin 0 HIGH
PORTC = 0b00000000; //Set Analog Pin 0 LOW
sei(); //Enable interrupts again
delay(1000); //Delay for 1000ms until next pulse
}
Beware that this would also set all other pins on Port C (Analog Pins 1 through 5) LOW.
This
PORTC |= (1 << PORTC0); //Set Analog Pin 0 HIGH
PORTC &= ~(1 << PORTC0); //Set Analog Pin 0 LOW
would be cleaner and only affect Analog Pin 0, but it may take more than one clock cycle to execute.
Unfortunately, I don't have a quick enough oscilloscope to try this out.
If it is too fast (e.g., you get a pulse of duration 0.06125 μs, you may want to insert another PORTC = 0b00000001;
before turning it off again. It is not unlikely that compiler optimization might just remove this when compiling, so you may have to set some other register to waste that one clock cycle.
-
1Your second snippet is the way to go. It is almost guaranteed to generate the proper
sbi
andcbi
instructions at any optimization level (save, maybe, level zero). These instructions execute in two clock cycles each, thus you get a pulse exactly two cycles wide.Edgar Bonet– Edgar Bonet2018年11月13日 14:33:10 +00:00Commented Nov 13, 2018 at 14:33