Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is this lbrary exact the same as the TimerOne library, but for TimerTwo? #3

Open
Rimbaldo opened this issue May 17, 2023 · 6 comments

Comments

@Rimbaldo
Copy link

Hi! I'm driving a BLDC motor with 3 pwm pins. So I have to use Timer1 and Timer2 to adjust this pins at the same time. Is your library exactly the same as the TimerOne, library, adapted to the Timer2? I mean, Can I use the same functions for both? I noticed in your's there's a little difference on some names and commands... If I use both at the same time, with the right values, could I have the same output for Timer1 and Timer2 pins at the same frequencies, duties, at the same time?

@theAndreas
Copy link
Owner

Hi, yes my library is very simular to the Timer1. But Timer1 is a 16 Bit timer and Timer2 only 8 Bit. So the resolution is lower. But it should work.

@Rimbaldo
Copy link
Author

Hi, yes my library is very simular to the Timer1. But Timer1 is a 16 Bit timer and Timer2 only 8 Bit. So the resolution is lower. But it should work.

Ok.. I´m testing timerone and your´s timertwo together now.. In the timeone library there´s this function that enables output pwm on a timer 1 pin, for instance, a led on pin 9:

Timer1.pwm(9, dutyCycle, period);

or with just the first two arguments, without period:

Timer1.pwm(9, dutyCycle);

It actuallys outputs a pwm signal on a led attached to pin 9, for instance.

But with yours, if I write the same code, but for timer2, like this:

Timer2.setPwmDuty(TimerTwo::PWM_PIN_11, dutycycle);

or

Timer2.enablePwm(TimerTwo::PWM_PIN_11, dutycycle);`

I get nothing on the led, and with a scope I see no pwm on the pin 11.. why is that? What can I do so it outputs a pwm signal that I can use just like the timer one library? Can you help me out on this? Thanks!

Here´s the complete code for timerone (pin9) that I want to use with timer two on pin 11

#include <TimerOne.h> // https://github.com/PaulStoffregen/TimerOne

// This example creates a PWM signal with a variable duty cycle.
// This scheme enforces a minimum pulse width at low duty cycles
// by varying the frequency and increasing the off times between
// pulses.
//
// this code was adapted from the TimerOne library example
// for a 25kHz fan
// https://github.com/PaulStoffregen/TimerOne/blob/master/examples/FanSpeed/FanSpeed.ino
//
// Minimum pulse width could be important for good torque from motors
// With a tau=L/R, a 5tau pulse width for a R=1.65ohm, L=3.2mH stepper
// would be tau=0.0032/1.65=1.9ms and 5
L/R = 5*.0032/1.65=9.7ms
//

constexpr int fanPin = 9; // Uno Timer1 OC1A pin

// Set the high frequency period and the minimum pulse
// These settings work for the Wokwi chips-scope from
// https://github.com/Dlloydev/Wokwi-Chip-Scope
// scope demo config:
// https://wokwi.com/projects/359331973918199809
// 2000us & 400us looks good with 200us sampling rate >22Hz
// 80 &4 at 1us sampling rate >1Hz
// 20000us and 2000us at 1ms sample rate for 50Hz>3Hz
// 20 & 1 and a real scope for 50K operation
constexpr unsigned long basePeriod = 2000;
constexpr unsigned long minUs = 400;
// calculate the changeover from adjusting pulse width at const freq
// to adjusting the frequency at const pulse width:
constexpr float minDuty = 100.0 * minUs / basePeriod;

float dutyCycle = 0;
int lastA0 = 0;
void setup(void)
{
Timer1.initialize(basePeriod); // us
Serial.begin(9600);
}

void loop(void)
{
updateSettings();
delay(0);
}

void updateSettings(void) {
const int interval = 250;
static unsigned long last = -interval;
if (millis() - last < interval ) return;
last += interval;
int val = analogRead(A0);
if (val != lastA0) {
lastA0 = val;
dutyCycle = 100 * (1 - cos(PI / 2 * val / 1023)); // 0-100% with high res at low end
unsigned long myPeriod = 0;
Serial.print("PWM Fan, Duty Cycle = ");
Serial.println(dutyCycle);
if (dutyCycle > minDuty || dutyCycle == 0.0) {
myPeriod = basePeriod;
Timer1.setPeriod(myPeriod);
Timer1.pwm(fanPin, (dutyCycle * 1023UL / 100));
Serial.print((int)(dutyCycle * myPeriod / 100));
Serial.print("us pulse at Hz:");
Serial.println(1000000UL / myPeriod);

} else { // Set by minimum width:
  myPeriod = minUs * 100UL / dutyCycle;
  if(myPeriod > 1885292UL){ 
    myPeriod  = 1885292UL;
  }
  Timer1.setPeriod(myPeriod);
  Timer1.pwm(fanPin, (uint32_t)(dutyCycle * 1023UL / 100));
  Serial.print(minUs);
  Serial.print("us pulse / ");
  Serial.print(myPeriod);
  Serial.print("us period / Hz:");
  Serial.println(1.0e6 / myPeriod);
  Serial.print("Timer1.OCR1A:"); Serial.print(OCR1A);
  Serial.print(" / ICR1:");Serial.print(ICR1);
  Serial.print(" TCCR1B:0b");Serial.println(TCCR1B,BIN);

}

}

}

@theAndreas
Copy link
Owner

Timer2 must be explicitly started with the API start(). Could you please try this? Seems to me there is a difference between Timer1 and Timer2. Timer1 is automatically started by calling initialize(). This is not really clear from the documentation. After analyzing the Timer1 example: start() is never called. In my example, however, it is.

@Rimbaldo
Copy link
Author

Hi! ok, I did like this, to make that code for both timers, and still the same result... the led on pin 11 never lits...

void setup(void) {
Timer1.initialize(basePeriod); // us

Timer2.init(basePeriod);
Timer2.start();
Timer2.enablePwm(TimerTwo::PWM_PIN_11, 127);

Serial.begin(9600);
}

... inside the code:

Timer1.setPeriod(myPeriod);
Timer1.pwm(ledPin9, (dutyCycle * 1023UL / 100));
Timer2.setPeriod(myPeriod);
Timer2.setPwmDuty(TimerTwo::PWM_PIN_11, (dutyCycle * 1023UL / 100));

Anything else I could try???

@theAndreas
Copy link
Owner

theAndreas commented Jun 25, 2023 via email

@theAndreas
Copy link
Owner

theAndreas commented Jun 25, 2023

Ok Pin 11 is wrong. Pin 3 is correct. Fixed also some other things. This code with the updated Timer.h and Timer.cpp is now working on my board:

#include <Arduino.h>
#include <TimerTwo.h>

void setup() {
  Timer2.init();
  Timer2.start();
  Timer2.enablePwm(TimerTwo::PWM_PIN_3, 10);
}

void loop() {
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants