Two groups of 40KHz square wave but 180 phase shift

558 views
Skip to first unread message

ERobot

unread,
Jan 10, 2017, 12:06:10 AM1/10/17
to HomeBrew Robotics Club
Hello,
   I used the code below, and use Arduino UNO pin #3, to generate a group of 20 bursts square at 40KHz every 550ms.  I did not use those "HIGH" or "LOW" because they are not working well (do not exactly know why).  Now I need to generate another similar group at the same time at another pin, but 180 phase difference, meaning when one is high, the other one is low.  Can someone advise me?  I have Arduino UNO and Mega.  thank you very much. 
  ERobot

const long frequency = 40000L; 
const byte Pinn = 3; 
void setup()
  {
  Serial.begin(115200);
  pinMode (Pinn, OUTPUT); 
  delay(1000);
  }
void loop()
  {   
  startTransducer();
  delayMicroseconds(500); // 500 us means 20 bursts
  stopTransducer();
  delay (550);  // every 550 ms
  }
void startTransducer()
{
  TCCR2A = _BV (WGM20) | _BV (WGM21) | _BV (COM2B1); 
  TCCR2B = _BV (WGM22) | _BV (CS21);         
  OCR2A =  ((F_CPU / 8) / frequency) - 1;    
  OCR2B = ((OCR2A + 1) / 2) - 1;             
}  
void stopTransducer()
{
  TCCR2A = 0;
  TCCR2B = 0;
}


Val Kirshin

unread,
Jan 10, 2017, 2:04:36 AM1/10/17
to hbrob...@googlegroups.com
Add TCCR2A | = _BV(COM2A1) | _BV(COM2A0) and look at Uno pin 11?

--
You received this message because you are subscribed to the Google Groups "HomeBrew Robotics Club" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hbrobotics+unsubscribe@googlegroups.com.
To post to this group, send email to hbrob...@googlegroups.com.
Visit this group at https://groups.google.com/group/hbrobotics.
For more options, visit https://groups.google.com/d/optout.

Tom Bertalan

unread,
Jan 10, 2017, 8:52:24 AM1/10/17
to HomeBrew Robotics Club
Where can one find documentation for these magic functions and registers?

Marco Walther

unread,
Jan 10, 2017, 10:57:59 AM1/10/17
to hbrob...@googlegroups.com
On 01/10/2017 05:37 AM, Tom Bertalan wrote:
> Where can one find documentation for these magic functions and registers?
>
In the data sheet or users guide ;-)

http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf

and the related #defines probably in the `hardware' headers coming with
the Arduino IDE;-)

-- Marco

Chris Albertson

unread,
Jan 10, 2017, 1:14:04 PM1/10/17
to hbrob...@googlegroups.com
You have a slight problem already with timing.    The loop runs slower than every 550 ms.   The correct way to write it would be

loop
   start time <-- current time
   DoStuff()
   wait for current time == start state + 550
end of loop

The above will run every 550 ms no mater how log DoStuff() takes to run

The other, harder way is to set up a timer to expire every 550 ms and have to trigger an interrupt.

Now about the second signal that needs to be 180 degree out of phase  I see Val Kirshin's suggestion but I don't know enough to know why it would be 180 degrees out of phase.

On Mon, Jan 9, 2017 at 9:06 PM, ERobot <eric.c...@gmail.com> wrote:

--
You received this message because you are subscribed to the Google Groups "HomeBrew Robotics Club" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hbrobotics+unsubscribe@googlegroups.com.
To post to this group, send email to hbrob...@googlegroups.com.
Visit this group at https://groups.google.com/group/hbrobotics.
For more options, visit https://groups.google.com/d/optout.



--

Chris Albertson
Redondo Beach, California

Chris Albertson

unread,
Jan 10, 2017, 1:50:44 PM1/10/17
to hbrob...@googlegroups.com
Sorry, a typo.   The second to the last line SHOUUD read
wait for current time >= start state + 550 ms

Now if DoStuff() takes to long to run the loop will still function and also this handles cases of the clock not being sampled at even ms intervals.   "greater than or equal" is the correct way.
Saving the start time is pretty much universal.  I did not think of it 

loop
   start time <-- current time
   DoStuff()
   wait for current time == start state + 550
end of loop

Alex Sy

unread,
Jan 10, 2017, 1:54:15 PM1/10/17
to hbrob...@googlegroups.com
Hi Eric,
To make a 180 degree out of phase on the pulses, you can configure as follows:   I am not familiar with the Arduino way of doing it.
This assumes 16Mhz clock, no divider (ie CPU runs at 16Mhz), PB1 (OC1A) and PB2 (OC1B) is 180 degrees or opposite polarity.
TCCR1A = (2 << COM1A0) | (3 << COM1B0) | (2 << WGM10);    // OC1A = high then low, OC1B = low then high
TCCR1B = (3 << WGM12) | (1 << CS10);                        // The timer mode uses ICR1 to control the frequency, in this case 40khz
OCR1A = 199;            // 50% duty cycle
OCR1B = 199;            // 50% duty cycle
ICR1 = 399;                // (16Mhz / 1 / 40000) - 1
 
As for generating the 20 pulses every 550msec, I would recommend to use another timer, ie timer 0 or timer 2 (with it's prescaler), then let it interrupt you both at COMPA and OVF, one to turn on the TCCR1A as above, and the other to turn off by setting it to 0.
 
This would make the timings very accurate.
If you are using this for distance measurement, I would recommend to actually use timer 0 for the ultrasonic pulses, time 2 for the pulse timing and then use the timer 1 capture mode (PB0 ICP1 pin) to actually time the reflected ultrasonic pulse.  This minimizes any CPU load.
 
Take some time to understand the TIMER0, 1, and 2 section of the Atmel datasheet as it gives you a lot of options.  It also helps to have a logic analyzer or a scope to verify signals and timing.
Alex
 
To unsubscribe from this group and stop receiving emails from it, send an email to hbrobotics+...@googlegroups.com.

Val Kirshin

unread,
Jan 10, 2017, 4:53:13 PM1/10/17
to hbrob...@googlegroups.com
Now about the second signal that needs to be 180 degree out of phase  I see Val Kirshin's suggestion but I don't know enough to know why it would be 180 degrees out of phase.

Yeah, you're right, he would probably need to adjust the timings. What I was trying to say was that each timer is connected to two pins. For timer 2 which the OP is using they are Uno pins 3 and 11. He's using pin 3 but he can also use pin 11 and set up the control register so that pin 11 will be set low at the same time as pin 3 is set high and vise versa. Same thing as what Alex Sy suggests.

There's no way to change pin assignments, so to use different pins just use the timer interrupt. Set it to fire at the needed interval and toggle pins in any way as needed. I think it actually will be simpler than Fast PWM mode he is using now. And it would be possible to get rid of the main loop entirely and just keep a counter in the interrupt handler to get 550ms delay.
Reply all
Reply to author
Forward
0 new messages