Go Down

### Topic: PWM at Low Frequencies (.12 Hz-10 Hz) (Read 24817 times)previous topic - next topic

#### dcconnor

##### Jan 05, 2013, 05:15 pmLast Edit: Jan 06, 2013, 10:07 am by Coding Badly Reason: 1
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!!

Code: [Select]
`int ledPin = 10; // sets pin 10 to output the same value at the ledPin outputint blinkPin = 9; // set pin 9 to output the same value as the output timer which is the blinkPinvoid 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: [code] [/code] tags added.

#### Magician

#1
##### Jan 05, 2013, 07:17 pm
Quote
//  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?
Looks like it has same 1/8 Hz lower minimum freq. on 16-bit timer.

#2
##### Jan 06, 2013, 10:16 am
Quote
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.

#### retrolefty

#3
##### Jan 06, 2013, 11:20 am

Quote
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

#### robtillaart

#4
##### Jan 06, 2013, 04:55 pm
Quote
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"

Code: [Select]
`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
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

#5
##### Jan 12, 2013, 06:11 pm

Quote
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.

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

#### udoklein

#6
##### Jan 12, 2013, 06:21 pm
You might try my code http://blog.blinkenlight.net/experiments/measurements/flexible-sweep/ 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.
Check out my experiments http://blog.blinkenlight.net

#### retrolefty

#7
##### Jan 12, 2013, 06:31 pm
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

#8
##### Jan 12, 2013, 07:47 pm
I wonder what would have the...

XD

#### Zapro

#9
##### Jan 12, 2013, 09:48 pm
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.

Go Up