HardwareTimer inside a Class
HardwareTimer inside a Class
Hi
did somebody knows why this compiles but freezes the blackpill MCU? (PC13 LED flashes always and does not run anything more)
class Motor {
public:
uint8_t pinPulse;
uint8_t pinDirec;
uint8_t pinEnable;
uint8_t TimerNum;
Motor(uint8_t pinPulse, uint8_t pinDirec, uint8_t pinEnable, uint8_t TimerNum) {
this->pinPulse = pinPulse;
this->pinDirec = pinDirec;
this->pinEnable = pinEnable;
this->TimerNum = TimerNum;
pinMode(pinPulse, PWM );
pinMode(pinEnable, OUTPUT);
pinMode(pinDirec, OUTPUT);
}
HardwareTimer *MyTim = new HardwareTimer(TimerNum);
void Start() {
MyTim->pause();
MyTim->setPrescaleFactor(1);
MyTim->setOverflow(1000);
MyTim->refresh();
MyTim->resume();
}
};
Motor Mot1 = Motor(PA8,PA9,PB1,1);
void setup() {
Mot1.Start();
}
void loop(){}
did somebody knows why this compiles but freezes the blackpill MCU? (PC13 LED flashes always and does not run anything more)
class Motor {
public:
uint8_t pinPulse;
uint8_t pinDirec;
uint8_t pinEnable;
uint8_t TimerNum;
Motor(uint8_t pinPulse, uint8_t pinDirec, uint8_t pinEnable, uint8_t TimerNum) {
this->pinPulse = pinPulse;
this->pinDirec = pinDirec;
this->pinEnable = pinEnable;
this->TimerNum = TimerNum;
pinMode(pinPulse, PWM );
pinMode(pinEnable, OUTPUT);
pinMode(pinDirec, OUTPUT);
}
HardwareTimer *MyTim = new HardwareTimer(TimerNum);
void Start() {
MyTim->pause();
MyTim->setPrescaleFactor(1);
MyTim->setOverflow(1000);
MyTim->refresh();
MyTim->resume();
}
};
Motor Mot1 = Motor(PA8,PA9,PB1,1);
void setup() {
Mot1.Start();
}
void loop(){}
Re: HardwareTimer inside a Class
How do you know that it freezes MCU ??
There's nothing in this code that would allow you to see if it's working.
There's nothing in this code that would allow you to see if it's working.
Re: HardwareTimer inside a Class
because the PC13 is not in normal conditions as when the timer is not inside the class.
Another more complete example of the code, that does not work for some reason...
class Motor {
public:
uint8_t pinPulse;
uint8_t pinDirec;
uint8_t pinEnable;
uint8_t TimerNum;
Motor(uint8_t pinPulse, uint8_t pinDirec, uint8_t pinEnable, uint8_t TimerNum) {
this->pinPulse = pinPulse;
this->pinDirec = pinDirec;
this->pinEnable = pinEnable;
this->TimerNum = TimerNum;
pinMode(pinPulse, PWM );
pinMode(pinEnable, OUTPUT);
pinMode(pinDirec, OUTPUT);
}
HardwareTimer *MyTim = new HardwareTimer(TimerNum);
void Close(){
MyTim->pause();
pwmWrite(pinPulse,0);
MyTim->refresh();
MyTim->resume();
}
void Start() {
int stepPulse = 100;
int tSpace = 100;
uint32 DutyCyc;
uint32 PeriodCyc;
uint16 Prescaler;
uint16 Overflow;
MyTim->pause();
PeriodCyc = (stepPulse + tSpace) * (F_CPU/1000000.0);// ciclos por us del STM32
#define MAX_RELOAD ((1 << 16) - 1)//timer 16 bits resolution
Prescaler = (PeriodCyc / MAX_RELOAD) + 1.0;
MyTim->setPrescaleFactor(Prescaler);
Overflow = (PeriodCyc + (Prescaler / 2.0)) / Prescaler;
MyTim->setOverflow(Overflow);
DutyCyc = Overflow*stepPulse/(stepPulse+tSpace);
pwmWrite(pinPulse,DutyCyc);
MyTim->refresh();
MyTim->resume();
}
};
Motor Mot1 = Motor(PA8,PA9,PB1,1);
void setup() {
Mot1.Close();
}
void loop(){
delay(3000);
Mot1.Start();
}
Another more complete example of the code, that does not work for some reason...
class Motor {
public:
uint8_t pinPulse;
uint8_t pinDirec;
uint8_t pinEnable;
uint8_t TimerNum;
Motor(uint8_t pinPulse, uint8_t pinDirec, uint8_t pinEnable, uint8_t TimerNum) {
this->pinPulse = pinPulse;
this->pinDirec = pinDirec;
this->pinEnable = pinEnable;
this->TimerNum = TimerNum;
pinMode(pinPulse, PWM );
pinMode(pinEnable, OUTPUT);
pinMode(pinDirec, OUTPUT);
}
HardwareTimer *MyTim = new HardwareTimer(TimerNum);
void Close(){
MyTim->pause();
pwmWrite(pinPulse,0);
MyTim->refresh();
MyTim->resume();
}
void Start() {
int stepPulse = 100;
int tSpace = 100;
uint32 DutyCyc;
uint32 PeriodCyc;
uint16 Prescaler;
uint16 Overflow;
MyTim->pause();
PeriodCyc = (stepPulse + tSpace) * (F_CPU/1000000.0);// ciclos por us del STM32
#define MAX_RELOAD ((1 << 16) - 1)//timer 16 bits resolution
Prescaler = (PeriodCyc / MAX_RELOAD) + 1.0;
MyTim->setPrescaleFactor(Prescaler);
Overflow = (PeriodCyc + (Prescaler / 2.0)) / Prescaler;
MyTim->setOverflow(Overflow);
DutyCyc = Overflow*stepPulse/(stepPulse+tSpace);
pwmWrite(pinPulse,DutyCyc);
MyTim->refresh();
MyTim->resume();
}
};
Motor Mot1 = Motor(PA8,PA9,PB1,1);
void setup() {
Mot1.Close();
}
void loop(){
delay(3000);
Mot1.Start();
}
-
- Posts: 633
- Joined: Thu Dec 19, 2019 1:23 am
Re: HardwareTimer inside a Class
Some working examples w/ caveats:
https://forum.arduino.cc/index.php?topi ... msg3453059
They compile error free on Roger's core, I do not guarantee them to work as
I am not in the lab to test on hardware.
https://forum.arduino.cc/index.php?topi ... msg3453059
They compile error free on Roger's core, I do not guarantee them to work as
I am not in the lab to test on hardware.
Re: HardwareTimer inside a Class
Your timer declaration might be wrong.
It should be like this:
All variables in class are created before you run constructor so you timer is created before you assign value to TimerNum.
(At least this is how I was taught).
It should be like this:
Code: Select all
HardwareTimer *MyTim;
Motor(...)
{
....
this->TimerNum = TimerNum;
MyTim = new HardwareTimer(this->TimerNum);
...
}
(At least this is how I was taught).
-
- Posts: 505
- Joined: Fri Dec 27, 2019 4:53 pm
- Location: Munich, Germany
- Contact:
Re: HardwareTimer inside a Class
I really don't see any point of using the "new" constructor.
This will use malloc and then you do not have any overwiev how you memory is increasing / decreasing.
Especially, contructing temporary objetcs in the main loop is the most common cause of memory corruption/overflow problems.
Usually, you should use the timer objects contructed per default in the core (at least in Roger's), or contruct your object (and not the pointer!) in the sketch outside any function.
This way you can access the timer class function with "." instead of "->" and you call "directly" the functions instead of using function pointers.
Another thing is the Motor class declaration. Usually it will be contructed at the first call of any function of the class. Therefore a begin() or init() function should be defined for that and called in setup, which should then setup the class internals with the input parameters used in your case by declaration.
So you better define and use such function of the class:
P.S. Use the code tag when posting code!
This will use malloc and then you do not have any overwiev how you memory is increasing / decreasing.
Especially, contructing temporary objetcs in the main loop is the most common cause of memory corruption/overflow problems.
Usually, you should use the timer objects contructed per default in the core (at least in Roger's), or contruct your object (and not the pointer!) in the sketch outside any function.
This way you can access the timer class function with "." instead of "->" and you call "directly" the functions instead of using function pointers.
Another thing is the Motor class declaration. Usually it will be contructed at the first call of any function of the class. Therefore a begin() or init() function should be defined for that and called in setup, which should then setup the class internals with the input parameters used in your case by declaration.
So you better define and use such function of the class:
Code: Select all
begin(uint8_t pinPulse, uint8_t pinDirec, uint8_t pinEnable, uint8_t TimerNum) {
this->pinPulse = pinPulse;
this->pinDirec = pinDirec;
this->pinEnable = pinEnable;
this->TimerNum = TimerNum;
pinMode(pinPulse, PWM );
pinMode(pinEnable, OUTPUT);
pinMode(pinDirec, OUTPUT);
}
Re: HardwareTimer inside a Class
Yes It is about that Im sure BUT it still freezes the unit... using this compiles AND work...GonzoG wrote: Sun Oct 25, 2020 7:28 am Your timer declaration might be wrong.
It should be like this:All variables in class are created before you run constructor so you timer is created before you assign value to TimerNum.Code: Select all
HardwareTimer *MyTim; Motor(...) { .... this->TimerNum = TimerNum; MyTim = new HardwareTimer(this->TimerNum); ... }
(At least this is how I was taught).
Code: Select all
class Motor {
private:
uint32 DutyCyc;
uint32 PeriodCyc;
uint16 Prescaler;
uint16 Overflow;
HardwareTimer *TIMER;
public:
uint8_t pinPulse;
uint8_t pinDirec;
uint8_t pinEnable;
float Pulse;
float Space;
uint8_t TimNum;
Motor(uint8_t pinPulse, uint8_t pinDirec, uint8_t pinEnable,uint8_t TimNum){
this->pinPulse = pinPulse;
this->pinDirec = pinDirec;
this->pinEnable = pinEnable;
this->TimNum=TimNum;
//HardwareTimer *TIMER = new HardwareTimer(TimNum);//HTline1 <----------
pinMode(pinPulse, PWM );
pinMode(pinEnable, OUTPUT);
pinMode(pinDirec, OUTPUT);
}
void move(float Pulse,float Space){
this->Pulse=Pulse;
this->Space=Space;
HardwareTimer *TIMER = new HardwareTimer(TimNum);//HTline2 <----------
TIMER->pause();
PeriodCyc = (Pulse + Space) * (F_CPU/1000000.0);
#define MAX_RELOAD ((1 << 16) - 1)
Prescaler = (PeriodCyc / MAX_RELOAD) + 1.0;
TIMER->setPrescaleFactor(Prescaler);
Overflow = (PeriodCyc + (Prescaler / 2.0)) / Prescaler;
TIMER->setOverflow(Overflow);
DutyCyc = Overflow*Pulse/(Pulse+Space);
pwmWrite(pinPulse,DutyCyc);
digitalWrite(pinEnable,true);
TIMER->refresh();
TIMER->resume();
}
};
Motor Mot1 = Motor(PA8,PA9,PB1,1);
void setup(){}
void loop(){
Mot1.move(0,10);//0%
delay(1500);
Mot1.move(10,0);//100%
delay(1500);
}
Re: HardwareTimer inside a Class
Both ways are wrong.
HT1: your TIMER in constructor is local variable.
In constructor function use:
TIMER = new HardwareTimer(TimNum);
not
HardwareTimer *TIMER = new HardwareTimer(TimNum);
pointer to TIMER is declared in your class, you don't need to create new one.
HT2: you create TIMER each time you run Move() function. You will run out of memory.
HT1: your TIMER in constructor is local variable.
In constructor function use:
TIMER = new HardwareTimer(TimNum);
not
HardwareTimer *TIMER = new HardwareTimer(TimNum);
pointer to TIMER is declared in your class, you don't need to create new one.
HT2: you create TIMER each time you run Move() function. You will run out of memory.
Re: HardwareTimer inside a Class
Thanks GonzoG! now It works properly...