1

I'm using the arduino uno hooked up to two LEDs. One is in pin 3 and the other one in pin 5. I know that pin 3 is controlled by timer3 and pin 5 by timer 1. I've tried a lot of things to have two independent frequencies. I really don't care about the PWM, I have it to 50% (constant).

There are resources to set the frequency (http://playground.arduino.cc/Main/TimerPWMCheatsheet), but these are predefined frequencies. I need to have one PWM at 650Hz and the other at 850Hz.

Any recommendations on how to approach this problem?

2

4 Answers 4

4

The ATMega PWM hardware underlying the Arduino primarily supports changing the duty cycle; the frequencies can only be selected from a few fixed choices. Typically the timers run from 0 to 255 or 65535 and loop back to 0, and you can select where within that full cycle the output changes on and off.

Since what you want is a simple 50% duty cycle with fine control of frequency, the PWM functions are not very useful. What you want is tone or frequency control. The ATMega timers support this too, but it's a different function than PWM. For frequency control, the timer will cycle from 0 to your choice of upper limit. So for example, you might count up to 200 instead of 255; or to 201 - so you get much finer control of frequency.

Unlike PWM, on the ATMega328p used in the Uno, you can only get one frequency per timer (you can get two PWM outputs per timer - both at the same frequency). And if you want millis() and microseconds() and delay() to continue to work, you don't want to mess with timer 0 for frequency control (you can get PWM from timer 0 if you accept the default frequencies).

So that leaves you with two frequency controllable timers - timer 1 (16 bit resolution) and timer 2 (8 bit resolution).

See the tone() function in the Arduino library for examples of a single tone at a time.

For multiple simultaneous frequencies (on different pins) see this library: https://code.google.com/p/rogue-code/wiki/ToneLibraryDocumentation. You can have two tones at a time, or three if you don't need millis() etc.

0

There is a great library with functions to change PWM frequency on Arduino microcontrollers, called arduino-pwm-frequency-library. I hope this helps you.

0
0

IF you need to dim leds use:

/*PWM signal on most pins is approximately 490 Hz
On the Uno and similar boards, pins 5 and 6 
have a frequency of approximately 980 Hz
brightness1, brightness2 = from 0(0v) to 255(5v)
So make eqution to calculate needed frequency*/

//LED are connected to:
const int ledPin1 = 5; 
const int ledPin2 = 6; 
byte brightness1 = 100; // ~2v
byte brightness2 = 200; // ~4v
void setup()
{
  // initialize the ledPin as an output:
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
}

void loop() {
    // set the brightness of the LED:
    analogWrite(ledPin1, brightness1);
    analogWrite(ledPin2, brightness2);

}
0

I recommend you to use two PWM signal with different duty cycles with the same frequency using timer1 and output pins 9 and 10. The next sketch was tested and it works very well.

 /*
 * Este programa genera 2 PWM signals a partir del timer 1. Las dos señales tienen la misma frecuencia (250Hz)
 * lo que varia es el duty cycle independiente para cada señal. Una sale por el pin 9 y la otra por el pin 10.
 */
#include <avr/io.h>
#include <avr/interrupt.h>

void setup() {
  Serial.begin(115200);
  // put your setup code here, to run once:
  //******** PWM Variable Definitions 
**********************************************************
  // Register initilisation, see datasheet for more detail.
  TCCR1A = 0b10100010; 
  //Timer/Counter1 Control Register A COM1A1 COM1A0 COM1B1 COM1B0 - - WGM11 WGM10
  // COM1A1 COM1A0 COM1B1 COM1B0
  //   1      0      1      0       Clear OC1A/OC1B on Compare Match, set OC1A/OC1B at BOTTOM (non-inverting mode)
  TCCR1B = 0b00011001; 
  //Timer/Counter1 Control Register B ICNC1 ICES1 - WGM13 WGM12 CS12 CS11 CS10
  // ICR1 Register is not double buffered. Using the ICR1 Register for defining TOP works well when using fixed TOP values.
  // By using ICR1, the OCR1A Register is free to be used for generating a PWM output on OC1A. That's why, I am using WGM 14.
  // WGM13 WGM12 WGM11 WGM10
  //   1     1    1     0           Fast PWM ICR1 - fixed TOP, update of OCR1x at BOTTOM. WGM 14 (Table 13-4).  
  // ICNC1 is 0                     the Input Capture Noise Canceler is disable
  // ICES1 is 0                     falling (negative) edge is used as trigger
  // CS12 CS11 CS10
  //  0    0    1                   No prescaling  
  TIMSK1 = 0b00000001; // Timer/Counter1 Interrupt Mask Register. The Timer/Counter1 Overflow interrupt is enabled.
  // TOP value is put in ICR1 and is equal to 64000, it means that 16000000 / 64000 = 250Hz (since no prescaling), the frequency of PWM signals
  ICR1   = 64000;  
  DDRB = 0b00000110; // Set PB1(DB9) and PB2(DB10) as outputs.
  interrupts ();
}
 void loop() {
  // put your main code here, to run repeatedly:
}

 ISR(TIMER1_OVF_vect) {
  // change duty-cycle every period.
  OCR1A = 16000;// in OCR1A is put the value corresponding to duty cycle, OCR1A output pin is 9. Duty cycle 25%. 16000 / 64000 = 0.25
  OCR1B = 48000;// the output pin of OCR1B is 10, duty cycle 75%. 48000 / 64000 = 0.75
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.