Go Down

Topic: 50% duty cycle square wave from 1hz to 1Mhz, easiest way? (Read 52722 times) previous topic - next topic

winner10920

Here's my code to set up timer 1
Code: [Select]
//dynamic frequency generator
//for timer2
#include <avr/io.h>
#include <avr/interrupt.h>
unsigned long frequency = 1000000 ;
void setup(){
  pinMode(9,1);
  pinMode(10,1);
  DFG(frequency);
  Serial.begin(57600);
 
}


void loop(){

}

void DFG(unsigned long tempfreq){
  cli();//disable interupts
  TCCR1A = 0;//registers for timer 1
  TCCR1B = 0;
  TCNT1=0;
  TCCR1A |= _BV(COM1A0) + _BV(COM1B0);
  TCCR1B |=_BV(WGM12);
  TCCR1C = _BV(FOC1A);
   if(tempfreq > 122 && tempfreq < 1000001){
  OCR1A = (8000000/tempfreq)-1;//#TIMER COUNTS
  TCCR1B |= _BV(CS10);
  }
  else if(tempfreq <= 122 && tempfreq > 15){
    OCR1A = (1000000/tempfreq)-1;
    TCCR1B |= _BV(CS11);
  }
  else if(tempfreq <= 15 && tempfreq > 4){
    OCR1A = (125000/tempfreq)-1;
    TCCR1B |= _BV(CS10) + _BV(CS11);
  }
 
  //TIMSK1 = _BV(OCIE1A);//TIMER1 COMPARE INTERUPT
  sei();//enable interupts
}


Docedison

Winner, There's an old trick to make a 50% exact duty cycle Square wave and that is to divide it by two with a flipflop.
A 555 might be tricked into doing that for you. Back in the day when I did discrete designs, before $0.50 Pic chips.
we used a CD4013 as a binary divider and ran the clock twice as fast as the required square wave but it seems a shame to tie up a processor just to make a signal  generator
How much power do you require and how is the device frequency agile?. At those frequencies a DDS chip might well be a good alternative.
there is an AD9850 for ~ $7.50  It's a numerically controlled oscillator that will go from 1 HZ to 30 Mhz) and sketches are available for controlling the device and the I/O necessary as well as an LCD display for setting frequency.
The part and all the rest of the components are on a small PCB you supply power, control and a buffer amplifier and AD9850 outputs both a sine and square wave.
This device requires either 5 8 bit parallel loaded bytes or 40 bits serial and can actually control fractional cycles or phase information as well although the sketch I have doesn't and I have no use for that fine a control.
You can find the board at Electrogragon http://www.electrodragon.com/?product=ad9850-dds-signal-generator-module and I have some more documentation for the board... I own a couple of them.
I will be providing Electrodragon with my files soon as well... Not so very much money for a very versatile signal/clock generator...

Doc
--> WA7EMS <--
"The solution of every problem is another problem." -Johann Wolfgang von Goethe
I do answer technical questions PM'd to me with whatever is in my clipboard

winner10920

Sounds nice, all I need is square wave and for this project the rest of the hardware is maxed out at 1Mhz, tho for a future project that sounds like a great ic
I've aactually got a ton of pins for this project so im using a quad encoder with a decoder ic(hctl2000) and using a spare port to get the data, and with using the hardware for the square wave,its not tieing up the atmega328 much, most probably will be the 16x2 lcd but that's a slow device anyway
and its driving a mosfet driver(high impedance so not much current, just a signal) which needed an inverted input and I can have the 328 have the output do that for me and save an logic inverter,
how fast in your experience was that ic? I imagine 40bits serial would take a decent amount of time, and for 40 parallel id have to get a mega2561
The only problem with a 555 is id then have to count it to display to the lcd, as well as hve multiple switches for caps, whereas with the prescalers I can flow even from 3hz to 1Mhz with just the knob

AdamHI

Winner (or anybody) - Thanks for the code. I'm reasonable with electronics in general, but relatively new to microcontroller stuff, especially low-level programming. 

Bottom line question: How do I incorporate the timer programming into more basic Arduino tasks. Can you give a generic example like "Place main loop here" and "Place time stuff here".

Specifically, I'll be writing a sketch to monitor an analog input (from a filtered audio source), and if the amplitude gets above a certain level, trigger an output - essentially looping through an analogRead the majority of the time. AnalogReads 5-10 times a second is sufficient, and exact consistency is not needed.

I need the adjustable square wave (at around 70 kHz, but will need to be adjustable from about 40 kHz to about 200-300 kHz with about 1 kHz resolution) to be the CLK for the switched-capacitor filter chip that is the filter for the audio input being read. So the timer has to be doing it's fast thing in the background, while the slow main program loops.  The timer would only rarely have to be adjusted, which could be accomplished at compilation time, though it might be nice to be able to be readjusted in response to button presses during the main loop.

Can somebody please help me understand a generic outline of where the different parts go in the final Arduino sketch?

Thanks in advance.

--adam, wh6m

dc42

Here is some code I use to generate a square wave of a given frequency from timer 1.

Code: [Select]

// Set the frequency that we will get on pin OCR1A
void setFrequency(uint16_t freq)
{
  uint32_t requiredDivisor = (F_CPU/2)/(uint32_t)freq;

#if defined(__AVR_ATtiny85__)
  // Code for attiny85
  uint16_t prescalerVal = 1;
  uint8_t prescalerBits = 1;
  uint32_t maxVal = 256;
  while (requiredDivisor > maxVal)
  {
    ++prescalerBits;
    maxVal <<= 1;
  }
 
  uint8_t top = ((requiredDivisor + (prescalerVal/2))/prescalerVal) - 1;
  TCCR1 = (1 << CTC1) | prescalerBits;
  GTCCR = 0;
  OCR1A = top;
#else
  // Code for atmega328p
  uint16_t prescalerVal;
  uint8_t prescalerBits;
  if (requiredDivisor < 65536UL)
  {
    prescalerVal = 1;
    prescalerBits = 1;
  }
  else if (requiredDivisor < 8 * 65536UL)
  {
    prescalerVal = 8;
    prescalerBits = 2;
  }
  else if (requiredDivisor < 64 * 65536UL)
  {
    prescalerVal = 64;
    prescalerBits = 3;
  }
  else if (requiredDivisor < 256 * 65536UL)
  {
    prescalerVal = 256;
    prescalerBits = 4;
  }
  else
  {
    prescalerVal = 1024;
    prescalerBits = 5;
  }

  uint16_t top = ((requiredDivisor + (prescalerVal/2))/prescalerVal) - 1;
  TCCR1A = 0;
  TCCR1B = (1 << WGM12) | prescalerBits;
  TCCR1C = 0;
  OCR1A = (top & 0xFF);
#endif
}

// Turn the frequency on
void on()
{
#if defined(__AVR_ATtiny85__)
  TCNT1 = 0;
  TCCR1 |= (1 << COM1A0);
#else
  TCNT1H = 0;
  TCNT1L = 0; 
  TCCR1A |= (1 << COM1A0);
#endif
}

// Turn the frequency off and turn of the IR LED
void off()
{
#if defined(__AVR_ATtiny85__)
  TCCR1 &= ~(1 << COM1A0);
#else
  TCCR1A &= ~(1 << COM1A0);
#endif
}
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

MarkT


Hi,
   If you see the thread I started a day or two back, the 555 is a horrible source of noise.



That's why I always recommend the 7555 over the 555 (its the CMOS version without
the 0.5A shoot-through problem).
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

cjdelphi

Between pins 6 & 7 place a diode to get a 50÷ duty cycle...

View my attached image, replacing the resistor(s) for potentiometers will give you what you need, a low pass filter on the output should stop noise...

Seems easy enough... view attached image

Magician

To AdamHI: have a look: http://www.maximintegrated.com/app-notes/index.mvp/id/4504

You can't get 1kHz resolution in 200-300 kHz range using arduino Timers only.
16000000/80 = 200.000
16000000/79 = 202.531

Here is one way to build an arduino based PLL :
http://coolarduino.wordpress.com/2013/07/30/diy-am-radio-2/

polymorph

Regarding using a 555 timer:

Quote
Between pins 6 & 7 place a diode to get a 50÷ duty cycle...


You'll have to fiddle with R1 and R2 to get 50%, and it is affected by Vcc and temperature. You can get a lot closer by simply using a very small R1 and a very large R2. However, either way, how will you control the frequency?

If the 50% duty cycle is very important, as suggested generate 1Hz go 2MHz and use a divide by two flip flop.
Steve Greenfield AE7HD
Drawing Schematics: tinyurl.com/23mo9pf - tinyurl.com/o97ysyx - https://tinyurl.com/Technote8
Multitasking: forum.arduino.cc/index.php?topic=223286.0
gammon.com.au/blink - gammon.com.au/serial - gammon.com.au/interrupts

Docedison

@ DuaneB.. The 555 can produce a lot of noise if it's power supply isn't clean. When I was building CTCSS tone generators many years ago I found this out the hard way. My fix was to carefully filter it, 10 uF cap input 10 ohm series resistor to 100 uF cap and the 555 Vcc. Set it to run @ 2X Fo. and use a CD4013 SR F.F. to divide the signal by two. I sure sold a lot of them too.

Doc
--> WA7EMS <--
"The solution of every problem is another problem." -Johann Wolfgang von Goethe
I do answer technical questions PM'd to me with whatever is in my clipboard

Magician


polymorph

You mean Philips states their NE555 up to 500kHz. Different types of 555 timers are rated for different maximum frequencies.
Steve Greenfield AE7HD
Drawing Schematics: tinyurl.com/23mo9pf - tinyurl.com/o97ysyx - https://tinyurl.com/Technote8
Multitasking: forum.arduino.cc/index.php?topic=223286.0
gammon.com.au/blink - gammon.com.au/serial - gammon.com.au/interrupts

Bradley_DA

Here's my code to set up timer 1
Code: [Select]
//dynamic frequency generator
//for timer2
#include <avr/io.h>
#include <avr/interrupt.h>
unsigned long frequency = 1000000 ;
void setup(){
  pinMode(9,1);
  pinMode(10,1);
  DFG(frequency);
  Serial.begin(57600);
 
}


void loop(){

}

void DFG(unsigned long tempfreq){
  cli();//disable interupts
  TCCR1A = 0;//registers for timer 1
  TCCR1B = 0;
  TCNT1=0;
  TCCR1A |= _BV(COM1A0) + _BV(COM1B0);
  TCCR1B |=_BV(WGM12);
  TCCR1C = _BV(FOC1A);
   if(tempfreq > 122 && tempfreq < 1000001){
  OCR1A = (8000000/tempfreq)-1;//#TIMER COUNTS
  TCCR1B |= _BV(CS10);
  }
  else if(tempfreq <= 122 && tempfreq > 15){
    OCR1A = (1000000/tempfreq)-1;
    TCCR1B |= _BV(CS11);
  }
  else if(tempfreq <= 15 && tempfreq > 4){
    OCR1A = (125000/tempfreq)-1;
    TCCR1B |= _BV(CS10) + _BV(CS11);
  }
 
  //TIMSK1 = _BV(OCIE1A);//TIMER1 COMPARE INTERUPT
  sei();//enable interupts
}
 


I've been looking for something that can drive a half bridge Solid State Tesla Coil at frequencies up too 500khz and you've made that possible with the Arduino :) so I Thank you!! I've ran the frequency down to about 5Hz.. Can it achieve frequencies up to a Mega Hert? Also I don't have a scope! How reliable is the Square wave at 500Khz?

Bradley_DA

I'm using PWM channel 9 & 10 to control the gate of 2 2N222A NPN-Transistors. Would this be the proper way to control these gates in opposite phase Via the same internal timer..? Or should I be using to separate internal timers for such a circuit?

Thank you! :)

Go Up