PWM at Low Frequencies (.12 Hz-10 Hz)

Hello everyone!

I have been trying to use the Arduino Uno to create square pulses at the following frequencies, 10Hz, 5Hz, 1Hz, .5Hz, and .12Hz using PWM. I’ve been using Timer1 in CTC mode with a 1024 (1562Hz) prescaler.

The problem is that as I lower the frequency, the waveforms I see on the oscilloscope looks less and less like a square wave. 10Hz, 5Hz, and even 1Hz produces a square wave that produce square waves where the bottom and top of the waveform has a slope and is not flat. The .5Hz and .12Hz waveforms are unrecognizable and almost seem sporadic. I’ve tried different combinations of OCR values and prescalers in Timer1 but no I have seen no real improvement.

Are there any suggestions on how to produce a clean square waveform at these lower frequencies? This is being used as apart of a scientific instrument so it is important that the signal is clean and reliable.

The code is below:

Thanks so much for your help!!

int ledPin = 10; // sets pin 10 to output the same value at the ledPin output
int blinkPin = 9; // set pin 9 to output the same value as the output timer which is the blinkPin

void TimerOne_setPeriod(long OCRValue) 

{
  TCCR1B = _BV(WGM12)|_BV(CS12)|_BV(CS10);   // CTC mode - 1024 prescale
                                             //  TCCR1B = _BV(WGM12)|_BV(CS12)|_BV(CS11)|_BV(CS10); is the entire command but since CS11=0 its left out
                                             //  manipulates prescale (one of the parameters we can manipulate**we want to use prescales that yeields high ORC values for more reliable signals 
  TCCR1A = _BV(COM1A0);                      //  or use TCCR1A = 0x40;            // Toggle mode 0C1A  
                                             //  This is used to toggle on pin 11 ** pin 11 = 0 x 1 so COM(COM1A1) = 0 and is not in code
                                             //  **Determines pin behavor
  OCR1A = OCRValue;                          //  set the counter
}

void setup()
{
  pinMode(ledPin, OUTPUT);                   //  Makes ledPin is the output
  pinMode(blinkPin, OUTPUT);                  // turn on the timer ouput pin and it also the input;
  TimerOne_setPeriod(15625);                 // set up and start Timer1 to blink at the same rate as the blink sketch
                                            /* Insert the follwing values into the TimerOne_setPeriod() here for the following frequencies:
                                             .12 Hz: 65104.16667
                                             .5 Hz: 15625
                                             1 Hz: 7812.5
                                             5 Hz: 1562.5
                                             10 Hz: 781.25
                                             */
                                             
                                         
 }
                                          
                                            

void loop()
{
  digitalWrite(ledPin, LOW);                 // set the LED on
  delay(1000);                               // wait for a second
  digitalWrite(ledPin, HIGH);                // set the LED off
  delay(1000);                               // wait for a second
}

Moderator edit:
</mark> <mark>[code]</mark> <mark>

</mark> <mark>[/code]</mark> <mark>
tags added.

// This is used to toggle on pin 11 ** pin 11 = 0 x 1 so COM(COM1A1) = 0 and is not in code

Timer1 PWM pins 9 and 10. Is there a reason not to use Tone library?
http://code.google.com/p/rogue-code/wiki/ToneLibraryDocumentation
Looks like it has same 1/8 Hz lower minimum freq. on 16-bit timer.

Are there any suggestions on how to produce a clean square waveform at these lower frequencies?

I have a sneaky suspicion that the problem has nothing to do with your code or the Uno.

As I suspect all along, it is the work of the illuminati !

Lefty

I have been trying to use the Arduino Uno to create square pulses at the following frequencies, 10Hz, 5Hz, 1Hz, .5Hz, and .12Hz using PWM.

As these frequencies are quite low, why not with using "blink without delay"

unsigned long duration = 100;  // in millis  -- 100, 200, 1000, 2000, 4000 == 10Hz, 5Hz, 1Hz, .5Hz, and .125Hz 
unsigned long lastFlip=0;
int state = LOW;

void setup()
{
  pinMode(7, OUTPUT);
  digitalWrite(7, state);
  Serial.begin(115200);
}

void loop()
{
  unsigned long now = millis();
  if (now - lastFlip >= duration)
  {
    lastFlip = now;
    state = !state;
    digitalWrite(7, state);
  }
}

Or try my PulsePattern library - http://arduino.cc/forum/index.php/topic,139407.0.html - which is timer driven

I wonder what would have the capacity to change a waveform... What in the world could perhaps induce resistance to voltage change....

You might try my code Flexible Sweep | Blinkenlight here. It is completely tested down to 0.0001 Hz. If your issue persists with my code then your issue is caused by your circuit and not by the code.

Assuming you want a 50%/50% square wave output I would just load up the MStimer2 library and have it's ISR just flip the output pin each time it's called. So I would just set the timer to interrupt at the millisecond value that corresponds to one half the period time of the desired frequency you wish to use. To change the frequency just
stop the timer interrupt, issue a new set timer interrupt with the new time value then do another start timer interrupts. Simple and low overhead I would think?

http://www.pjrc.com/teensy/td_libs_MsTimer2.html

Lefty

cyclegadget:
I wonder what would have the...

XD

I cannot see why a lower frequency would alter the logic level on the output - try looking at the probe on the scope, it sounds like it's set to AC coupling!!

// Per.