output block wave with different time intervals

Hi all,

I'm looking for a way to output a block wave with different toggle time intervals, more specifically belonging to 39, 40 and 41 kHz . For instance 10 pulse signal consisting out these frequencies 39|40|41|40|41|39|40|41|39|41, or variations with the same idea. After this signal, a waiting period of 10ms or so and repeat.

------------------___-- (signal should look something like this)

I'm not very familiar with intervals on the Arduino, but thought this would be a way forward. Getting a bit more acquainted with CTC timers, I see they are defined in the setup and are fixed in frequency. What would be a good way to produce my required signal?

Can I for instance combine multiple interrupts, finish one and reset the timer for the next one in line and so on?

Kind regards,

What have you tried so far? If the signal example is what you refer to as "different frequencies", you should think of it as being a signal that runs at the highest common frequency (or higher) and varies in high / low time.

For how long time does the signal extend, is it in bursts or is it endless? If it is in bursts, you can look into how the "adafruit neopixel" send the signal to the pixels, that would work for you. If it is endless, you could use Timer2 to oscillate the signal.

My answer assumes that ATmega328 is the brain.

Hi Danois,

Thanks for your reply.

The signal is a burst of about 10.

//timer setup for timer0, timer1, and timer2.
//For arduino uno or any board with ATMEL 328/168.. diecimila, duemilanove, lilypad, nano, mini...

//this code will enable all three arduino timer interrupts.
//timer0 will interrupt at 2kHz
//timer2 will interrupt at 8kHz

//storage variables
boolean toggle0 = 0;
int counter = 0;

void setup(){
  
  //set pins as outputs
  pinMode(9, OUTPUT);


cli();//stop interrupts

//set timer0 interrupt at 2kHz
  TCCR0A = 0;// set entire TCCR2A register to 0
  TCCR0B = 0;// same for TCCR2B
  TCNT0  = 0;//initialize counter value to 0
  // set compare match register for 2khz increments
  OCR0A = 124;// = (16*10^6) / (2000*64) - 1 (must be <256)
  // turn on CTC mode
  TCCR0A |= (1 << WGM01);
  // Set CS01 and CS00 bits for 64 prescaler
  TCCR0B |= (1 << CS01) | (1 << CS00);   
  // enable timer compare interrupt
  TIMSK0 |= (1 << OCIE0A);

//set timer2 interrupt at 8kHz
  TCCR2A = 0;// set entire TCCR2A register to 0
  TCCR2B = 0;// same for TCCR2B
  TCNT2  = 0;//initialize counter value to 0
  // set compare match register for 8khz increments
  OCR2A = 249;// = (16*10^6) / (8000*8) - 1 (must be <256)
  // turn on CTC mode
  TCCR2A |= (1 << WGM21);
  // Set CS21 bit for 8 prescaler
  TCCR2B |= (1 << CS21);   
  // enable timer compare interrupt
  TIMSK2 |= (1 << OCIE2A);


sei();//allow interrupts

}//end setup

ISR(TIMER0_COMPA_vect){//timer0 interrupt 2kHz toggles pin 9
//generates pulse wave of frequency 2kHz/2 = 1kHz (takes two cycles for full wave- toggle high then toggle low)
if (counter == 0){
    if (toggle0){
      digitalWrite(9,HIGH);
      toggle0 = 0;
    }
    else{
      digitalWrite(9,LOW);
      toggle0 = 1;
    }
  }
  counter=0;

//  TCNT0  = 0;//initialize counter value to 0
  TCNT2  = 0;//initialize counter value to 0
}

  
ISR(TIMER2_COMPA_vect){//timer1 interrupt 8kHz toggles pin 9
//generates pulse wave of frequency 8kHz/2 = 4kHz (takes two cycles for full wave- toggle high then toggle low)
if (counter ==1){
    if (toggle0){
      digitalWrite(9,HIGH);
      toggle0 = 0;
    }
    else{
      digitalWrite(9,LOW);
      toggle0 = 1;
    }
  }

  TCNT0  = 0;//initialize counter value to 0
//  TCNT2  = 0;//initialize counter value to 0

  counter=0;
}


void loop(){
  //do other things here
}

I'm currently trying to combine two interrupts, as in the code above, but not working yet.
How would your suggestion of looking at the highest frequency work in code, could you explain a bit more?

Thanks,

Ok, seems I've got the general idea working. Can switch between frequencies by resetting OCR0A after a certain amount of pulses.

#include <avr/interrupt.h>

#ifndef cbi // Definitions for setting and clearing register bits
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif


boolean toggle0 = 0;
int counter = 0;

void setup() {

  pinMode(9, OUTPUT);

  //set timer0 interrupt 
  TCCR0A = 0;// set entire TCCR2A register to 0
  TCCR0B = 0;// same for TCCR2B
  TCNT0  = 0;//initialize counter value to 0
  
  // set compare match register 
  OCR0A = 193;
  // turn on CTC mode
  TCCR0A |= (1 << WGM01);
  // Set prescaler to 1
  TCCR0B |= (0 << CS02) | (0 << CS01) | (1 << CS00);
  // enable timer compare interrupt
  TIMSK0 |= (1 << OCIE0A);


}//end setup

ISR(TIMER0_COMPA_vect) { //timer0 interrupt, toggles pin 9

  if (counter < 20) {
    if (toggle0) {
      digitalWrite(9, LOW);
      toggle0 = 0;
    }
    else {
      digitalWrite(9, HIGH);
      toggle0 = 1;
    }
  }
  counter += 1;

  if (counter == 10) {
    cbi(TCCR0A, COM0A0) ; // disconnect pulse clock
    OCR0A = 193;   // update timer value
    sbi(TCCR0A, COM0A0) ; // connect pulse clock

  }

  if (counter == 20) {
    cbi(TCCR0A, COM0A0) ; // disconnect pulse clock
    OCR0A = 204;   // update timer value
    sbi(TCCR0A, COM0A0) ; // connect pulse clock

  }

  if (counter > 100) {
    counter = 0;
  }
}

void loop() {

}

As it works, it seems to be a reasonable way to do it. Any suggestions for improving?

Thanks,

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.