Go Down

Topic: PWM frequency library (Read 433667 times) previous topic - next topic

Affirmative

Hi RunnerUp,

Great Library!   Works like a charm on the Nano.   Even verified the accuracy of both the frequency and the DutyCycle.

Now the big question (could go out to everyone as well).   My script is getting bigger by the day and I still need to add a rotary pot&button User Interface.    The infamous 10lbs of stuff in a 5lb bag!!  Not enough space.   I believe all the code is transferable to the Every except the PWM.h libary.

I've done the search for PWM & Every and there are attempts  - some good, some wild.   But, none are as elegant and simple to use as yours.

Would it be possible to update (or new version) to run on the 4809 Every?   Could call it PWM-Every.h.

Thanks,
Dave

bergstar

#226
Aug 30, 2020, 11:08 pm Last Edit: Aug 30, 2020, 11:09 pm by bergstar
I can't compile this on any Arduino SAMD:

Code: [Select]
*: undefined reference to `InitTimersSafe()'
*: undefined reference to `SetPinFrequencySafe(signed char, unsigned long)'
collect2.exe: error: ld returned 1 exit status
Using library pwm at version 5.0 in folder: *\Documents\Arduino\libraries\pwm

This is the same on all SAMD boards.

Same sketch for AVR compiles without issues. 

Any suggestions?

J-M-L

#227
Aug 30, 2020, 11:12 pm Last Edit: Aug 30, 2020, 11:14 pm by J-M-L
Any suggestions?
it's meant for AVR only

may be you can read this thread for ideas (or here too)
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

ocrdu

Any suggestions?
The timer hardware on the SAMD21 is different; you need a library written/suitable for the SAMD21. I have made one, but it is not as easy to use as the one described in this thread: https://github.com/ocrdu/Arduino_SAMD21_turbo_PWM

It should be available in the Library Manager; set filter your search to "turbo".

There may be others out there.

Muplex

#229
Sep 07, 2020, 07:56 pm Last Edit: Sep 07, 2020, 08:58 pm by Muplex
Hello, I'm trying a sketch to generate waveforms on my arduino UNO r3
When I use timer 1 associated with pin 9 everything goes OK.

Same identical sketch,with pin 11 does not work at all.

const int signal_pin = 9; is OK
const int signal_pin = 11; do not work!!!

Many other users said the same issue, anyone discover the solution or the reason of these behaviuor ?


Code: [Select]
#include <PWM.h> //PWM librarey for controlling freq. of PWM signal
#include <ShiftLCD.h> //LCD with Shift-Register IC circuit

//#define LOCALDEBUG 1

ShiftLCD lcd(10, 13, 12);

const int Encoder_OuputA  = 7;
const int Encoder_OuputB  = 4;
const int Encoder_Switch = 8;

const int Interrupt_pin = 2;
const int signal_pin = 9;
const int Sine_pin = 5;

int Previous_Output;
int multiplier = 1;

volatile double angle = 0;
volatile double increment = 0.2;

int32_t frequency; //frequency to be set
int32_t lower_level_freq = 1; //Lowest possible freq value is 1Hz
int32_t upper_level_freq = 100000; //Maximum possible freq is 100KHz

void setup()
{
  //pin Mode declaration
  pinMode (Encoder_OuputA, INPUT);
  pinMode (Encoder_OuputB, INPUT);
  pinMode(Encoder_Switch, INPUT_PULLUP);

  lcd.begin(16, 2); //Initialise 16*2 LCD

  lcd.print("Signal Generator"); //Intro Message line 1
  lcd.setCursor(0, 1);
  lcd.print("- Muplex "); //Intro Message line 2
  delay(2000);
  lcd.clear();
  lcd.print("Freq:0    Hz");
  lcd.setCursor(0, 1);
  lcd.print("Inc. by: 1 ");

#ifdef LOCALDEBUG
  Serial.begin(9600);
#endif

  Timer1_Initialize();
  Timer2_Initialize();

  Previous_Output = digitalRead(Encoder_OuputA); //Read the inital value of Output A

  attachInterrupt(digitalPinToInterrupt(Interrupt_pin), generate_sine, CHANGE);
}

void loop()
{
  if (digitalRead(Encoder_OuputA) != Previous_Output)
  {
    if (digitalRead(Encoder_OuputB) != Previous_Output)
    {
      frequency = frequency - multiplier;
      // Serial.println(frequency);
      pwmWriteHR(signal_pin, 32768); //Set duty cycle to 50% by default -> for 16-bit 65536/2 = 32768
      SetPinFrequencySafe(signal_pin, frequency);
      lcd.setCursor(0, 0);
      lcd.print("Freq:     Hz");
      lcd.setCursor(5, 0);
      lcd.print(frequency);
    }
    else
    {
      frequency = frequency + multiplier;
      // Serial.println(frequency);
      pwmWriteHR(signal_pin, 32768); //Set duty cycle to 50% by default -> for 16-bit 65536/2 = 32768
      SetPinFrequencySafe(signal_pin, frequency);
      lcd.setCursor(0, 0);
      lcd.print("Freq:     Hz");
      lcd.setCursor(5, 0);
      lcd.print(frequency);
    }
    delay(10);
  }

  if (digitalRead(Encoder_Switch) == 0)
  {
    multiplier = multiplier * 10;

    if (multiplier > 1000)
      multiplier = 1;

    // Serial.println(multiplier);
    lcd.setCursor(0, 1);
    lcd.print("Cng. by:     ");
    lcd.setCursor(8, 1);
    lcd.print(multiplier);

    delay(200);
    while (digitalRead(Encoder_Switch) == 0);
  }

  Previous_Output = digitalRead(Encoder_OuputA);

}

void generate_sine()
{
  double sineValue = sin(angle);
  sineValue *= 255;
  int plot = map(sineValue, -255, +255, 0, 255);
#ifdef LOCALDEBUG
  Serial.println(plot);
#endif
  analogWrite(Sine_pin, plot);
  angle += increment;

  if (angle > 2 * PI)
    angle = 0;
}

J-M-L

Hello, I'm trying a sketch to generate waveforms on my arduino UNO r3
When I use timer 1 associated with pin 9 everything goes OK.

Same identical sketch,with pin 11 does not work at all.

const int signal_pin = 9; is OK
const int signal_pin = 11; do not work!!!

Many other users said the same issue, anyone discover the solution or the reason of these behaviuor ?

May be read this
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

Muplex

#231
Sep 07, 2020, 10:23 pm Last Edit: Sep 07, 2020, 10:28 pm by Muplex
May be read this
Ok, for the next generations... =)
If I well understand is because Timer1 is the only internal clock 16 bit vs Timer0 and Timer1 who have 8 bits.

OCRxA is the OutputCompareRegister right ?

Can you explain me a little deeper the link between them ?


My goal is to have two sinusoid waves on two arduino uno pins.
SPWM due to the previous limitation don't seems the correct way. (i was working to implement  this project )
R2R DAC requires a lot of pins for a 8bit wave + 1 LCD and 1 rotary encoder = Not enought Pins....

@J-M-L do you see a way to achieve my goal without IC components or I have to study some OpAmps + Mosfet configuration ?
Maybe ArduinoMega is suitable due to the increased numer of pins and timers?


Thank you a lot, you help me to achieve these point!

jparekh68

Hi!!

I want to use this PWM library. Downloaded it. But unable to add it on my IDE. Can somebody help? I am new to Arduino.

sitas

hi, is it possible to adapt this library for servo ?

BetaCarotin

Is there a way to invert the PWM on a second pin? I am running in 16-bit mode on Pin 9 and would like to have the inverted signal on Pin 10 (thats the second pin of counter 1 isn't it?) I am running it on a nano.
There is some example about changing registers to get an inverted write- but I am not sure how/if it affects the 16bit mode and other library functions.

Orngrimm

Hi!!

I want to use this PWM library. Downloaded it. But unable to add it on my IDE. Can somebody help? I am new to Arduino.
Just copy the complete folder "PWM" in the ZIP to your Arduino-IDE-path /Libraries
Like C:\work\Arduino\libraries

Orngrimm

I DLed and installed the 0.5-Lib and wrote a short Testprogram to test a buzzer i have with 950 HZ and 30% duty.
Running on a Mega1280 and a Mega2560
The f is spot on with like 950.01Hz
But the Duty is off by a factor of 2.54ish and too low
I added a correction-factor to the duty, which is suuuper janky...

Is this a problem with the lib, I made a mistake or something else entirely?
My code:
Code: [Select]

/*
 PWM-Libnrary from Runnerup @ https://forum.arduino.cc/index.php?topic=117425.0 / https://code.google.com/archive/p/arduino-pwm-frequency-library/downloads
 The library
 allows for a frequency range from 1Hz - 2MHz on 16 bit timers and 31Hz - 2 MHz on 8 bit timers. When
 SetPinFrequency()/SetPinFrequencySafe() is called, a bool is returned which can be tested to verify the
 frequency was actually changed.
 This example runs on mega and uno.
 */

#include <PWM.h>

//use pin 11 on the Mega instead, otherwise there is a frequency cap at 31 Hz
int8_t i_pin_output = 11;                // the pin that the Buzzer is attached to
int32_t i_f = 1000;
int i_ms = 0;
int i_duty = 0;
int i_duty2 = 0;
bool b_success = false;
bool b_verbose = true;
int i_parts_in_sequence = 0;

int i_serial_speed = 9600;  // Be aware of the limit of int!

// The buzzer-sequence. Always 3 INT per step for: Frequency(Hz), duration(ms), Duty(%)
int i_Freq_Time_Duty[] = {
  950, 100, 30,
  950, 100, 0,
  950, 100, 30,
  950, 100, 0,
  950, 100, 30,
  950, 300, 0,
 
  950, 100, 30,
  950, 100, 0,
  950, 100, 30,
  950, 500, 0,

  950, 100, 30,
  950, 100, 0,
  950, 100, 30,
  950, 100, 0,
  950, 100, 30,
  950, 300, 0,
 
  950, 100, 30,
  950, 100, 0,
  950, 100, 30,
  950, 5000, 0
  };

void setup()
{
  Serial.begin(i_serial_speed); // Öffnet die serielle Schnittstelle bei 57.600 Bit/s:
  //initialize all timers except for 0, to save time keeping functions
  InitTimersSafe();

  //sets the frequency for the specified pin
  b_success = SetPinFrequencySafe(i_pin_output, i_f);
 
  //if the pin frequency was set successfully, notify me
  if(b_success) {
    // Some messages to Serial maybe?
    Serial.println("All ok @ setup");
  }
  i_parts_in_sequence = sizeof(i_Freq_Time_Duty)/sizeof(int)/3; // determine the # of sets in the array

  // print_table(i_Freq_Time_Duty[],3);
  Serial.println("----- Table-printout -------");
  for (int i = 0; i <= i_parts_in_sequence-1; i++) {
    Serial.print("Part "); Serial.print(i); Serial.print(": \t");
    Serial.print(i_Freq_Time_Duty[i * 3 + 0]); Serial.print("Hz,  \t");
    Serial.print(i_Freq_Time_Duty[i * 3 + 1]); Serial.print("ms,  \t");
    Serial.print(i_Freq_Time_Duty[i * 3 + 2]); Serial.println("%");
  }
  Serial.println("----- End of Table-printout -------");
  Serial.println("");
    if(b_verbose==false){Serial.println("As verbose = false, no further output will be generated");}
}

void loop()
{
  for (int i = 0; i <= i_parts_in_sequence-1; i++) {
    if(i_Freq_Time_Duty[i * 3 + 0] != i_f) { // Only update frequncy of PWM if necessary
      i_f = i_Freq_Time_Duty[i * 3 + 0];
      b_success = SetPinFrequencySafe(i_pin_output, i_f);
      if(b_verbose){
        if(b_success){
          Serial.print("Set f: Success  \t");
        } else {
          Serial.print("Set f: FAIL     \t");
        }
      }
    } else {
      if(b_verbose){Serial.print("Set f: n/a (same)\t");}
    }
    i_ms = i_Freq_Time_Duty[i * 3 + 1]; // Get how long the next part will be
    i_duty = i_Freq_Time_Duty[i * 3 + 2]; // get the next duty-dycle of next part
   
    //use this functions instead of analogWrite on 'initialized' pins
    i_duty2 = int(i_duty * 2.56); // <----- I HAVE TO ADD A CORRECTION-FACTOR! WHY!?!?!??!
//    Serial.println(i_duty);
    pwmWrite(i_pin_output, i_duty2);
    wait_part(i_ms, b_verbose); // Delaytime(ms), UART-Rapporting?
  }
  if(b_verbose){
    Serial.println("------- REPEATING -------");
  }
}

void wait_part(int i_ms, boolean uart)
{
int32_t i_timing = millis() + i_ms;
  if(uart == true) {
    Serial.print("f = ");
    Serial.print(i_f);
    Serial.print("\t ms = ");
    Serial.print(i_ms);
    Serial.print("\t duty% = ");
    Serial.println(i_duty); 
  }
  //Wait till the part is over
  do {
    delay(0);
  } while (millis() < i_timing);
}

 



Orngrimm

Also, if i raise the UART-Speed to 38400 and above the whole thing breaks...

savke989

Hi. I am trying to make frequency adjustable with external potenciometer conected to analog input. It goes from 5Hz up to 50Hz in periods of 5Hz. Everything seams to work good, but sometimes i get a "hole" (output goes completly off) for about  1sec just in moment of changing frequency. Tried on Nano and Mega same problem.

Code: [Select]
#include <PWM.h>

//use pin 11 on the Mega instead, otherwise there is a frequency cap at 31 Hz
int a;
int led = 9;   
int lastFrequency;// the pin that the LED is attached to
int brightness = 100;         // how bright the LED is
int fadeAmount = 5;         // how many points to fade the LED by
int32_t frequency = 25; //frequency (in Hz)

void setup()
{
    Serial.begin(9600);
  //initialize all timers except for 0, to save time keeping functions
  InitTimersSafe();

  //sets the frequency for the specified pin

    SetPinFrequencySafe(led, frequency);


}

void loop()
{
 
   a = analogRead(A1);
   if(a >= 0 && a < 100){frequency = 5;}
   if(a > 100 && a < 200){frequency = 10;}
   if(a > 200 && a < 300){frequency = 15;}
   if(a > 300 && a < 400){frequency = 20;}
   if(a > 400 && a < 500){frequency = 25;}
   if(a > 500 && a < 600){frequency = 30;}
   if(a > 600 && a < 700){frequency = 35;}
   if(a > 700 && a < 800){frequency = 40;}
   if(a > 800 && a < 900){frequency = 45;}
   if(a > 900 && a <= 1024){frequency = 50;}

if(frequency != lastFrequency) {
     Serial.println("freqChange");
     Serial.println(frequency);

  SetPinFrequency(led, frequency);
  }



  //use this functions instead of analogWrite on 'initialized' pins
  pwmWrite(led, brightness);



  lastFrequency = frequency;
 
  delay(50);     
}



Go Up