Are these Timer/Counter settings right for PWM generation?

Hi there,
I am trying to generate a 125kHz square wave carrier and read in the middle of that carrier signal, say at approximately 4 us or less. I do not have a source that reproduces the 125kHz at the moment. Can anyone tell me if the code is generating a 125kHz square wave. I do not have any instrumentation at the moment to check it real time… :frowning:
It would really help as I am a beginner in arduino and still learning. The code is NOT printing anything on the serial monitor.

//#define SYNC_BITS 50 //NUMBER OF BIT PERIODS TO MEASURE
//#define MAX_MSG_BITS 1500 //STOP READING HERE
boolean toggle1 = 0;

//int measured_periods[SYNC_BITS];

String data;

void setup() {
  // put your setup code here, to run once:

  pinMode(9, OUTPUT);//oc1a
  pinMode(2,INPUT_PULLUP);
  Serial.begin(9600);

  attachInterrupt(digitalPinToInterrupt(2), measure_middle_ISR, RISING);
  //Serial.print(buffer_in);
  
  cli();

  //Timer 1 interrupt at 125kHz
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  
  //turn on CTC mode
  TCCR1A |= (0<<COM1A1)|(1<<COM1A0); //toggle on compare match
  TCCR1B |= (1<<ICNC1)|(1<<ICES1);
  TCCR1B |= (1<<WGM12);
  //Set prescaler 8 
  //-------> no prescaler - CS10 - 1; 64 prescaler - CS11, CS10 - 1 <-----//
  TCCR1B |= (1<<CS11)|(0<<CS10);

  OCR1A = 15; //[(16000000/(125000*8)] - 1
  OCR1B = 15;
  //enable timer compare interrupt
  TIMSK1 |= (1<<ICIE1)|(1<<OCIE1B)|(1<<OCIE1A)|(1<<TOIE1);

  sei();
  //allow interrupts
  

}
//digitalwrite is very slow??
ISR(TIMER1_COMPA_Vect){//timer1 interrupt 125kHz toggles pin 13
  //generates a wave of frequency 125kHz/2 = 62.5kHz
  if(toggle1){
    digitalWrite(9, HIGH);
    toggle1 = 0;
    }
  else{
    digitalWrite(9, LOW);
    toggle1 = 1;
    
    }

  /*
  delayMicroseconds(4);
  PORTB |= (1<<PB7);
  delayMicroseconds(4);
  PORTB &= ~(1<<PB7);*/

  
  }
/*
void start_sync_ISR(){


  detachInterrupt(0);
  start_sync = true;
}

void measure_middle_ISR(){
  
  detachInterrupt(0);
  start_middle = true;
  
  }
*/

byte val;
short i;
//char buffer_in[800];
uint8_t state = 0;
void loop() {
  // put your main code here, to run repeatedly:



  for(i = 0; i<SYNC_BITS; i++){
    
    measured_periods[i] = pulseIn(2, HIGH);
    
    }
/*while(1){
  if(i<800){
  buffer_in[i] = digitalRead(13);
  val = buffer_in[i];
  }i++;
  }*/
 if(toggle1 == 0){
  state = 1;
  Serial.println(state);
  }
 else{
  state = 0;
  Serial.println(state);
 }


 
/*
 while(1){
  if(i<800){
    delayMicroseconds(4);
    buffer_in[i] = digitalRead(13);
    val = buffer_in[i];
    }i++;
 }*/

  
//Serial.println(val);

Serial.println(measured_periods[i]);
}

Thanks,
AM

Hi there,
I want to read the middle of a 125kHz square wave. I m not sure how to do it. If someone could show me how I would be grateful.

//#define SYNC_BITS 50 //NUMBER OF BIT PERIODS TO MEASURE
//#define MAX_MSG_BITS 1500 //STOP READING HERE
boolean toggle1 = 0;

//int measured_periods[SYNC_BITS];

String data;

void setup() {
  // put your setup code here, to run once:

  pinMode(9, OUTPUT);//oc1a
  pinMode(2,INPUT_PULLUP);
  Serial.begin(9600);

  attachInterrupt(digitalPinToInterrupt(2), measure_middle_ISR, RISING);
  //Serial.print(buffer_in);
  
  cli();

  //Timer 1 interrupt at 125kHz
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  
  //turn on CTC mode
  TCCR1A |= (0<<COM1A1)|(1<<COM1A0); //toggle on compare match
  TCCR1B |= (1<<ICNC1)|(1<<ICES1);
  TCCR1B |= (1<<WGM12);
  //Set prescaler 8 
  //-------> no prescaler - CS10 - 1; 64 prescaler - CS11, CS10 - 1 <-----//
  TCCR1B |= (1<<CS11)|(0<<CS10);

  OCR1A = 15; //[(16000000/(125000*8)] - 1
  OCR1B = 15;
  //enable timer compare interrupt
  TIMSK1 |= (1<<ICIE1)|(1<<OCIE1B)|(1<<OCIE1A)|(1<<TOIE1);

  sei();
  //allow interrupts
  

}
//digitalwrite is very slow??
ISR(TIMER1_COMPA_Vect){//timer1 interrupt 125kHz toggles pin 13
  //generates a wave of frequency 125kHz/2 = 62.5kHz
  if(toggle1){
    digitalWrite(9, HIGH);
    toggle1 = 0;
    }
  else{
    digitalWrite(9, LOW);
    toggle1 = 1;
    
    }

  /*
  delayMicroseconds(4);
  PORTB |= (1<<PB7);
  delayMicroseconds(4);
  PORTB &= ~(1<<PB7);*/

  
  }
/*
void start_sync_ISR(){


  detachInterrupt(0);
  start_sync = true;
}

void measure_middle_ISR(){
  
  detachInterrupt(0);
  start_middle = true;
  
  }
*/

byte val;
short i;
//char buffer_in[800];
uint8_t state = 0;
void loop() {
  // put your main code here, to run repeatedly:



  for(i = 0; i<SYNC_BITS; i++){
    
    measured_periods[i] = pulseIn(2, HIGH);
    
    }
/*while(1){
  if(i<800){
  buffer_in[i] = digitalRead(13);
  val = buffer_in[i];
  }i++;
  }*/
 if(toggle1 == 0){
  state = 1;
  Serial.println(state);
  }
 else{
  state = 0;
  Serial.println(state);
 }


 
/*
 while(1){
  if(i<800){
    delayMicroseconds(4);
    buffer_in[i] = digitalRead(13);
    val = buffer_in[i];
    }i++;
 }*/

  
//Serial.println(val);

Serial.println(measured_periods[i]);
}

Best,
AM

  //enable timer compare interrupt
  TIMSK1 |= (1<<ICIE1)|(1<<OCIE1B)|(1<<OCIE1A)|(1<<TOIE1);

In the above you are turning on several interrupts, without providing interrupt routines for them. This is extremely dangerous. Use instead something like

  TIMSK1 = (1<<OCIE1A);  //enable timer COMPA interrupt

I want to read the middle of a 125kHz square wave

What do you want to “read”? Please explain, as the code is a muddle.

You should avoid using detachInterrupt() if at all possible.

Hi remington,

I want the arduino to generate a 125 kHz square wave first. Once that is outputted at some pin, I want to read that very signal approximately in the middle of the wave but not the edges. This is taking into account of the jitter. In real time, the square wave will contain some data superimposed on it. So reading it in the middle will help obtain that superimposed data(assumption - I m aware for this a separate analog circuitry is required). Does this make sense?

I am unable to even serial.print to the serial monitor. It's printing just the first two characters of the string. :(

Best, AM

Does this make sense?

Not at all, sorry.

... Well, do you think my PWM generation is correct? All, I want to do first is generate that 125kHz square wave. Are there any scientific keywords that I am missing here? How does one measure the duration of the pulse in-between rather than peak to peak?

If you program a timer to produce a square or rectangular wave, it will do so very, very accurately and continuously, without any jitter, and without any further intervention by the CPU. Get that working, using the simplest possible code, before moving on. Plenty of tutorials on that, plus study the timer section of the CPU data sheet.

You don't need to use interrupts to do that.

So far, your description of some sort of modulation of the signal produced by the timer seems to be entirely theoretical. Please explain, and post circuit diagrams and timing diagrams showing your intent.

But why worry about measuring something, until that something actually exists?

Hi remington,
I unfortunately cannot post any circuit diagrams or any as such as I do not have access to any. All I have been assigned as part of a project is to read whatever that physical quantity is whether time or voltage in between the peak-to-peak pulse duration. Since I can’t see whether pin 9 is outputting a 125khz square wave, I had to seek approvals from on here. I have attached an image below.

Best,
A

125 kHz is 8 µs. The signal is high for 4 µs. Reading in the middle of the high level is 2 µs after the rising edge.

With an Arduino Uno, a interrupt takes at least 5 µs: https://gammon.com.au/interrupts. That is 2.9 µs for storing the cpu state to the stack and 2.2 µs for retrieving the cpu state from the stack.

When you use attachInterrupt() at the rising edge, and read a digital pin by reading a register directly, then you read the pin about 2.9 µs later than the rising edge of the signal. That is about in the middle.

However, what will you do with that information. There is not enough time to do something with it. The 125 kHz is too high for an Arduino Uno.

To create a 125 kHz signal can be done with alternative tone() libraries, for example the toneAC library. https://bitbucket.org/teckel12/arduino-toneac/wiki/Home

I will ask the admin to combine the questions, they are slightly different, but on this forum you probably get the same answers.

Thanks Koepel, the struggle is real.

Hi Koepel,

Thanks. The attachInterrupt was a failed implemetation. But, I did not know that ArduinUno interrupts take 5 us. I want to store that in a buffer. And later use it for processing.

Thanks, Azim

Threads merged.

Interrupts are not the way to go, but it is certainly possible to read an input pin at a rate much faster than 125 kHz.

Use direct port access and poll, for example, wait until PORTB, pin 5 goes high, then read PORTD, pin 3:

  while (PINB & (1<<5) == 0); //poll PORTB, pin 5 
  x = PIND&(1<<3); //read PORTD, pin 3

The second read will happen just a couple of 62.5 ns processor cycles after PB5 goes high, but of course there will be some jitter because of the branch.

I did not understand that implementation. :(

In that case, you will need to learn about direct port access using Arduino.

Hint: google "arduino direct port access"

People, I am still stuck at this.

I tried port manipulation, but nothing seems to happening. What mode should I be using to get a near perfect square wave of 125kHz?

I suspect my timer/counter settings are wrong.

 //DDRB &= ~(1<<PB0);//pin 8 input //ICP1
  //DDRB &= ~(1<<PB1);
  //PORTB |= (1<<PORTB1);//PORTB Input Pullup

  //DDRB &= ~(1<<PB
  //pinMode(9, OUTPUT);//oc1a
  //DDRD &= ~(1<<PD2);//portd pin2 input
  //PORTD |= (1<<PD2);
  //pinMode(interrupt_pin,INPUT_PULLUP);

  //pinMode(dataIn,INPUT);

  pinMode(PB1,INPUT_PULLUP);
  Serial.begin(115200);
  //attachInterrupt(8, rising, RISING);
  //delayMicroseconds(1000);
  Serial.println("AVR Initialization");
  delay(50);

  

  //Serial.print(buffer_in);
 
  
  cli();

  //Timer 1 interrupt at 125kHz
  //TCCR1A = 0;
  //TCCR1B = 0;
  //TCNT1 = 0;
  ICR1 = 63;
  //turn on CTC mode
  //TCCR1A |= (0<<COM1A1)|(0<<COM1A0)|(0<<COM1B1)|(0<<COM1B0)|(0<<WGM11)|(0<<WGM10); //normal 00//toggle 01//low level 10//high level 11
 
  //TCCR1B |= (1<<ICNC1);
  TCCR1B |= (1<<ICNC1)|(1<<ICES1)|(1<<WGM13)|(1<<WGM12); //FAST MODE - 8 bit Mode 5
  //Set prescaler 8 
  //-------> no prescaler - CS10 - 1; 64 prescaler - CS11, CS10 - 1 <-----//
  TCCR1B |= (0<<CS12)|(0<<CS11)|(1<<CS10); //256 prescaler

  //OCR1A = 127; //[(16000000/(125000*8)] - 1//top value 8 BIT
  //OCR1B = 63;
  //ICR1 = 63;
  //TCNT1 = 0;
  //enable timer compare interrupt
  //TIMSK1 |= (1<<ICIE1)|(1<<OCIE1A)|(1<<TOIE1);
  TIMSK1 |= (1<<ICIE1)|(1<<TOIE1);
  sei();

Hi, I have been trying to understand how to use timer/counter manipulations in order to generate a pwm of a desired frequency. I have to output a 125kHz square wave from th arduino. Can someone show me how?
What mode to select, what values to set (ICR1 or OCR1A/OCR1B), any calculations involved? I would highly appreciate it.

Also, I need to be able to measure the duration between the consecutive pulses in the middle of the pulses rather edge to edge. I need some inputs people. :confused:

Please have a look at the code snippet.

// put your setup code here, to run once:
  //DDRB &= ~(1<<PB0);//pin 8 input //ICP1
  //DDRB &= ~(1<<PB1);
  //PORTB |= (1<<PORTB1);//PORTB Input Pullup

  //DDRB &= ~(1<<PB
  //pinMode(9, OUTPUT);//oc1a
  //DDRD &= ~(1<<PD2);//portd pin2 input
  //PORTD |= (1<<PD2);
  //pinMode(interrupt_pin,INPUT_PULLUP);

  //pinMode(dataIn,INPUT);

  pinMode(PB1,INPUT_PULLUP);
  Serial.begin(115200);
  //attachInterrupt(8, rising, RISING);
  //delayMicroseconds(1000);
  Serial.println("AVR Initialization");
  delay(50);

  

  //Serial.print(buffer_in);
 
  
  cli();

  //Timer 1 interrupt at 125kHz
  //TCCR1A = 0;
  //TCCR1B = 0;
  //TCNT1 = 0;
  ICR1 = 63;
  //turn on CTC mode
  //TCCR1A |= (0<<COM1A1)|(0<<COM1A0)|(0<<COM1B1)|(0<<COM1B0)|(0<<WGM11)|(0<<WGM10); //normal 00//toggle 01//low level 10//high level 11
 
  //TCCR1B |= (1<<ICNC1);
  TCCR1B |= (1<<ICNC1)|(1<<ICES1)|(1<<WGM13)|(1<<WGM12); //FAST MODE - 8 bit Mode 5
  //Set prescaler 8 
  //-------> no prescaler - CS10 - 1; 64 prescaler - CS11, CS10 - 1 <-----//
  TCCR1B |= (0<<CS12)|(0<<CS11)|(1<<CS10); //256 prescaler

  //OCR1A = 127; //[(16000000/(125000*8)] - 1//top value 8 BIT
  //OCR1B = 63;
  //ICR1 = 63;
  //TCNT1 = 0;
  //enable timer compare interrupt
  //TIMSK1 |= (1<<ICIE1)|(1<<OCIE1A)|(1<<TOIE1);
  TIMSK1 |= (1<<ICIE1)|(1<<TOIE1);
  sei();

lrdazmmlk, you started a new topic with the same question. It might be merged with this one.

Can you tell us: 1 ) Do you want to use a timer for 125 kHz output. That is possible. 2 ) Do you want to create an interrupt of 125 kHz, that will not be reliable. It might work for a short time, but I don't know why that can be helpful for something. 3 ) How will this help with reading a signal of 125 kHz after a few µs of the rising edge ?

People, I am still stuck at this.

Cross-posting. What a selfish act. Don't do it again.