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.

  • If you are using an AVR-based Arduino, read Timers and counters, by Nick Gammon. – Edgar Bonet Nov 12 '18 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 Nov 12 '18 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 – Danish Nov 12 '18 at 21:59
  • what code have you tried so far? – MichaelT Nov 12 '18 at 22:01
  • ive embedded the code above – Danish Nov 12 '18 at 22:16
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.

  • 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. – Edgar Bonet Nov 13 '18 at 14:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.