1
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.

VE7JRO
2,51519 gold badges27 silver badges29 bronze badges
asked Nov 12, 2018 at 21:44
6
  • If you are using an AVR-based Arduino, read Timers and counters, by Nick Gammon. Commented 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? Commented 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 coding Commented Nov 12, 2018 at 21:59
  • what code have you tried so far? Commented Nov 12, 2018 at 22:01
  • ive embedded the code above Commented Nov 12, 2018 at 22:16

1 Answer 1

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.

answered Nov 13, 2018 at 14:22
1
  • 1
    Your second snippet is the way to go. It is almost guaranteed to generate the proper sbi and cbi 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. Commented Nov 13, 2018 at 14:33

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.