50% duty cycle square wave from 1hz to 1Mhz, easiest way?

Like said in the subject what would be the easiest way to make an adjustable square wave(50% duty cycle) that can be adjusted from 1hz(doesn't have to be that low but it'd be nice) to 1Mhz(doesn't have to be that high maybe >750khz but it'd be nice), the precision doesn't have to be crazy but adjustable as much as possible so I can correct it
I used to have a function generator that did it but it broke and I need this as a separate solution anyway, also if it could be easily digitally adjusted that would be really awesome to exchange a potentiometer for an encoder for fine adjustments
I know there's a ton of ways of making oscillators and than just turning it into a good square wave, but what's the easiest best? It doesn't have to drive much of a load, its more for signal purposes
my current attempt is my 555 timer which is a pain to readjust everytime I want to change and it never turns out to be 50% duty cycle or even close enough, also the fastest I think I got was 300khz with a horrible duty cycle

There are many roads to jerusalem!

A timed interrupt would probably be the best way, or use the onboard PWM not that I have ever used that as I always program PWM manually

Digital write takes about 4us so thats not an option for even moderate frequencies direct port addressing is what you need

But the easiest way is a program that does nothing else like this

void setup()
{ 
  DDRB = DDRB | B110000;} // Set digital pins 12 and 13 to outputs
int T = 30;
void loop()
{  
  
    
  PORTB = B100000;         // Digital pin 13 high
   delayMicroseconds(T);  //30 microsecond delay
   PORTB = B000000;        // Digital pin 13 low 
   delayMicroseconds(T);   //30 microsecond delay

}

I am not sure it will produce a 1MHz wave though you will need to modify it so the delay is 0.5us

Put the output of your 555 through a divide by two to get a 1:1 duty cycle. Something like a 74LS74.

You will not get that range with a single capacitor so you will have to switch ranges.

There are many roads to jerusalem!

So how come they all lead to Rome? (except the A57, which ends up in Worksop)

I was thinking about using an arduino timer but do thy have that kind of flexibility?
I know pwm wont work as I believe the max speed is 133khz but I don't need pwm, just 50% constant

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

I would look to the the ATMega built in timers, your application is basically what they are there for.

You can configure the timers to automatically toggle a pin in the background, much faster and more accurate than trying to do it in software - there may be libraries already available that provide a nice interface to this functionality.

Duane B

rcarduino.blogspot.com

I know pwm wont work as I believe the max speed is 133khz

No that is wrong it will go faster than that.

I don't need pwm, just 50% constant

The advantage of PWM is that it works without using any of the software CPU cycles.
If you follow the PWM output with a divide by two you get the square wave you are after.
Some processors have a toggle output pin on counter overflow, but not this one.
Doing it in software you have to arrange for the counter overflow ( or under flow ) to trigger an interrupt. In the ISR you simply toggle the pin.

Hi GM,
I thought the ATMega328 has toggle on output compare ?

Duane B

I guess im gonna have to dive into the datasheet and figure this out
So the general consensus is that the arduino hardware can do this? I don't wanna spend 20 hours and realize it can't do what I want, ill be needing to dynamically change the frequency so I guess that means changing prescalers and counters on the fly?

I thought the ATMega328 has toggle on output compare ?

Yes sorry you are right it does see section 17.5.1 and 14.7 of the data sheet.

Maybe the easyest way would be to use the Timer1 library:

http://www.arduino.cc/playground/Code/Timer1

setPeriod(period)
Sets the period in microseconds. The minimum period or highest frequency this library supports is 1 microsecond or 1 MHz. The maximum period is 8388480 microseconds or about 8.3 seconds. Note that setting the period will change the attached interrupt and both pwm outputs' frequencies and duty cycles simultaneously

I used this sketch to time a Atmega1284p at 1MHz:

Edit - With another Uno.

#include <TimerOne.h>

#define pwmRegister OCR1A
const int  outPin = 9;

long period = 1;     // the period in microseconds
long pulseWidth = 0.5; // width of a pulse in microseconds

int prescale[] = {0,1,8,64,256,1024}; // range of prescale values

void setup()
{
  Serial.begin(9600);
  pinMode(outPin, OUTPUT);
  Timer1.initialize(period);  //initialize timer1, 1000 microsec
  setPulseWidth(pulseWidth);
}

void loop()
{
}

bool setPulseWidth(long microseconds)
{
  bool ret = false;
  
  int prescaleValue = prescale[Timer1.clockSelectBits];
  long precision = (F_CPU / 128000) * prescaleValue  ;
  period = precision * ICR1 / 1000;
  if( microseconds < period)
    {
      int duty = map(microseconds, 0, period, 0, 1024);
      if(duty < 1)
        duty = 1;
      if( microseconds > 0 && duty < RESOLUTION)
      {
        Timer1.pwm(outPin, duty);
        ret = true;
      }
    }
    return ret;
}

Just need the Timer1 library.

Solved XD
dig some digging in the datasheet for the past few hours and I can now set up pin 9 or ten to any frequency I want
thx for the help, using the arduino hardware is real easy once you figure it out

winner10920:
Solved XD
dig some digging in the datasheet for the past few hours and I can now set up pin 9 or ten to any frequency I want
thx for the help, using the arduino hardware is real easy once you figure it out

And you can share your solution with us? I need to generate a wave of 1 MHz to recover a "Fuse brick";

Thanks

you'll be working with TCCR1A, TCCR1B, and OCR1A
first disable interupts,
set the wgm bits to CTC mode with OCR1A as top, calculate and set OCR1A,
set COM1A1,COM1A0 (or B depending if you want uno pin 9 or 10) then start the clock with prescaler /1,
If your in a rush you can probbly read the datasheet about these and figure it out,
ill post my code after work, I made a function that calculates the OCR1A and prescaler down to 4hz, but upwards of700khz the resolution is pretty bad, tho 1Mhz is fine I measured it with my uno @ .997Mhz which I guess is close enough,

Here's my code to set up timer 1

 //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
}

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 AD9850 DDS Signal Generator Module – ElectroDragon 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

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

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

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

// 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
}