Go Down

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

dcconnor

Jan 05, 2013, 05:15 pm Last 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 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: [code] [/code] tags added.

Magician

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?
http://code.google.com/p/rogue-code/wiki/ToneLibraryDocumentation
Looks like it has same 1/8 Hz lower minimum freq. on 16-bit timer.

Coding Badly

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


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

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)

cyclegadget


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....
Good links: Eagle tutorial= http://www.youtube.com/playlist?list=PLDE1858BD83D19C70
General Arduion tutorials = http://tronixstuff.wordpress.com
http://www.gammon.com.au/forum/bbshowpost.php?bbtopic_id=123

Udo Klein

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

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


Zapro

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