PWM freq/duty cycle revisited

Hi

I have continued the quest to have a PWM with both frequency and duty cycle variable but independent of one another.

Using a posted tutorial , i tried to merge two sketches to achieve the above.

After many hours of looking over the merged sketches and changing this , that , and the other.

I got "done uploading".

I nearly s--t myself.

This is the reaction a newbie has , when he feels he has cracked it.

The sketch ran , but alas only the duty cycle varied and the frequency remained fixed.

Doh

My only guess as to why it did not work , is because i used the same pin (9) as a common output.

Over to the experts , a little help please.

Thanks for listening.

Sketch one

/*
  Fade

  This example shows how to fade an LED on pin 9 using the analogWrite()
  function.

  The analogWrite() function uses PWM, so if you want to change the pin you're
  using, be sure to use another PWM capable pin. On most Arduino, the PWM pins
  are identified with a "~" sign, like ~3, ~5, ~6, ~9, ~10 and ~11.

  This example code is in the public domain.

  http://www.arduino.cc/en/Tutorial/Fade
*/

int led = 9;           // the PWM pin the LED is attached to
int brightness = 0;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by

// the setup routine runs once when you press reset:
void setup() {
  // declare pin 9 to be an output:
  pinMode(led, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  // set the brightness of pin 9:
  analogWrite(led, brightness);

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness <= 0 || brightness >= 255) {
    fadeAmount = -fadeAmount;
  }
  // wait for 30 milliseconds to see the dimming effect
  delay(30);
}

Sketch two

//Frequency generator Variables//
int outpin = 9;
int Frequency = 0;
int Output = 0;
const int analogInPin = A0;
//-------------------------------
void setup()
{
  Serial.begin(19200);
}

void loop()
{
 
  //Frequency Output//
  //----------------------------------------
  Frequency = analogRead(analogInPin);
 
    /*This loop makes sure the receiver will always see a minimun output and the Freq.
    Generator is above the minimun limit for the tone function
    */
   
    if (Frequency <= 2)
      {Output = 2;}
    else
      {Output = analogRead(analogInPin);}
   
          //Serial.println (analogInPin);
           Serial.println (Frequency);
           Serial.println (Output);
 
    /* Tone (x, y, w, z)
     x= output Pin;
     y=Output frequency;
     w=multiplier factor <-> Freq*w <-> Output;
     z=Calibration for the receiver */

tone ( 9, Output*20*1.004 );      //Last digit is calibration for the receiver to match the frequency. 
  //----------------------------------------
}

Sketch three (merged sketch)

/*
  Fade

  This example shows how to fade an LED on pin 9 using the analogWrite()
  function.

  The analogWrite() function uses PWM, so if you want to change the pin you're
  using, be sure to use another PWM capable pin. On most Arduino, the PWM pins
  are identified with a "~" sign, like ~3, ~5, ~6, ~9, ~10 and ~11.

  This example code is in the public domain.

  http://www.arduino.cc/en/Tutorial/Fade
//Frequency generator Variables//
int outpin = 9;
*/

int led = 9;           // the PWM pin the LED is attached to
int brightness = 0;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by

int Frequency = 0;
int Output = 0;
const int analogInPin = A0;
//-------------------------------
// the setup routine runs once when you press reset:
void setup() {
  // declare pin 9 to be an output:
  pinMode(led, OUTPUT);


  Serial.begin(19200);
}
// the loop routine runs over and over again forever:
void loop() {
  // set the brightness of pin 9:
  analogWrite(led, brightness);

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness <= 0 || brightness >= 255) 
    fadeAmount = -fadeAmount;
  
  // wait for 30 milliseconds to see the dimming effect
  delay(30);



  //Frequency Output//
  //----------------------------------------
  Frequency = analogRead(analogInPin);

  /*This loop makes sure the receiver will always see a minimun output and the Freq.
    Generator is above the minimun limit for the tone function
  */

  if (Frequency <= 2)
  
    Output = 2;
  
  else
  
    Output = analogRead(analogInPin);
  

  //Serial.println (analogInPin);
  Serial.println (Frequency);
  Serial.println (Output);

  /* Tone (x, y, w, z)
    x= output Pin;
    y=Output frequency;
    w=multiplier factor <-> Freq*w <-> Output;
    z=Calibration for the receiver */

  tone ( 9, Output * 20 * 1.004 );  //Last digit is calibration for the receiver to match the frequency.
  //----------------------------------------
  }

Hi

Had a further look and got rid of delay in the Fade sketch.

It's moving around like a fart in a fan factory.

As i adjust the pot connected to A0 from ground to 5v it appears to be changing frequency from 490hz to 4900hz .

Frequency counter is having a heart attack.

Please still chime in , i'm still new to this stuff

Thanks

I have continued the quest to have a PWM with both frequency and duty cycle variable but independent of one another.

i don't understand what you're trying to do and what the problem is

in the first part of loop() i see you adjusting the brightness of an LED by controlling it's average voltage using PWM. i can't see any problem with this. looks like it should go from minimum to maximum brightness every 1.5 sec

in the 2nd half of loop() you read an analog input and use it's value to generate a tone. but it looks like the only values you use are <= 2. doesn't analogRead() return a 10-bit value, 0-1023?

spuddo:
My only guess as to why it did not work , is because i used the same pin (9) as a common output.

That sounds like a very good guess.

The analogWrite() lets you change the duty-cycle of a fixed frequency pulse train. The tone() lets you change the frequency of a square wave (50% duty-cycle pulse train). Whichever you call last has control of the pin.

To get both variable frequency and variable duty-cycle you will have to abandon the built-in functions and take over control yourself.

If your sketch has nothing else to do you could use the Blink Without Delay example for the basis of an entirely software waveform generator:

  • Turn on the output pin.
  • Wait until the proper time has passed.
  • Turn off the output pin.
  • Wait until the proper time has passd.
  • Repeat.

The two 'proper times' depend on the frequency and the duty cycle. Cycle time is 1/Frequency (for example to get 1500 Hz your cycle is 1/1500th of a second: 666 microseconds). The 'on' time is Cycle time * duty-cycle. The 'off' time is Cycle time * (1.0 - duty-cycle).

If your sketch has other things to do and you want the signal generated in hardware, you will need to learn how the PWM features of the hardware timers work.

Hi.

Thanks for your replies.

My interest is this is audio. Think of synthesizers.

It all started with a simple circuit that gave me both frequency change and duty cycle change , without either effecting the other.

Then someone on the forum (all about circuits) said it would be easier done in code.

So here i am.

I have a lot to learn , but will keep at it----it's fun.

Johnwasser , i will try your suggestion and i am sure i will ask more questions.

Best regards

For audio frequencies I would recommend Timer1 (16-bit) rather than Timer2 (8-bit). With a 16-bit timer you can get 15 Hz to 15 kHz with just one prescale setting (prescale = 8) and retaining 64 levels of duty-cycle. With the 8-bit timer you would have to change between six different prescale settings to get the same range.