Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
6 years ago.
EventQueue. Can't make controller work in real time.
Hi, I need several functions to be called every 1 ms precisely at the same time. Take a look at the code. I use eventqueue for this. To monitor real time, I send an integer via uart every 10ms, and then increase it. But it happens slower than a real time goes. After 2 minutes of monitoring, it delays for 2s from real time. How can i make it execute in real time, without delays, what do i do wrong?
code
#include "mbed.h"
#include "rtos.h"
#include "QEI.h"
#define SAMPLE_TIME 0.001f
#define PWM_PERIOD 0.0001f
#define PI 3.14159265359f
class ControlLoop{
private:
float dutyCycleI, dutyCycleK, dutyCycle;
public:
float uz, e, ep, ew, wz, uzp;
QEI enc;
PwmOut in1, in2;
ControlLoop(PinName driverIn1, PinName driverIn2, PinName encoderChA, PinName encoderchB, int ppr):\
enc(encoderChA, encoderchB, NC, ppr, QEI::X4_ENCODING), in1(driverIn1), in2(driverIn2){
in1.period(PWM_PERIOD);
in2.period(PWM_PERIOD);
in1.write(0);
in2.write(0);
}
float zpOutput(float uz, float acc, float wmax){ //zp
float sign, temp;
ep = uz - uzp;
if(ep >= 0) sign = 1.0f;
if(ep < 0) sign = -1.0f;
temp = sign * sqrt((abs(ep) * 2.0f));
if(temp >= wmax) temp = wmax;
if(temp <= -wmax) temp = -wmax;
ew = temp - wz;
if(ew >= 0) sign = 1.0f;
if(ew < 0) sign = -1.0f;
wz = wz + sign * acc * SAMPLE_TIME;
uzp = uzp + wz * SAMPLE_TIME;
return uzp;
}
void control(float uZpOut, float k, float i, float dcl){ //pi-regulator
e = uZpOut - (float)enc.getPulses() / 16.1f * PI / 180.0f;
dutyCycleK = abs(e * k);
dutyCycleI = abs(dutyCycleI + e * i);
dutyCycle = dutyCycleK + dutyCycleI;
if(dutyCycle >= dcl) dutyCycle = dcl;
if(e >= 0){
in2.write(dutyCycle);
in1.write(0);
}else{
in1.write(dutyCycle);
in2.write(0);
}
}
};
Serial pc(PD_5, PD_6);
Serial bluetooth(PD_8, PD_9);
EventQueue eventQueue;
ControlLoop system1(PB_3, PB_8, PA_2, PA_3, 5800);
ControlLoop system2(PB_3, PB_8, PA_2, PA_3, 5800);
ControlLoop system3(PB_3, PB_8, PA_2, PA_3, 5800);
ControlLoop system4(PB_3, PB_8, PA_2, PA_3, 5800);
ControlLoop system5(PB_3, PB_8, PA_2, PA_3, 5800);
ControlLoop system6(PB_3, PB_8, PA_2, PA_3, 5800);
int c = 0;
void uartOutF(){
pc.printf("%i %f %f %f %f %f %f;\n", c, system1.uzp,system6.uzp,system2.uzp,system3.uzp,system4.uzp,system5.uzp);
c++;
}
void move1m(){
system1.zpOutput(1, 1, 1);
}
void move2m(){
system2.zpOutput(2, 1, 1);
}
void move3m(){
system3.zpOutput(3, 1, 1);
}
void move4m(){
system4.zpOutput(4, 1, 1);
}
void move5m(){
system5.zpOutput(5, 1, 1);
}
void move6m(){
system6.zpOutput(6, 1, 1);
}
int main() {
pc.baud(115200);
eventQueue.call_every(1, move1m);
eventQueue.call_every(1, move2m);
eventQueue.call_every(1, move3m);
eventQueue.call_every(1, move4m);
eventQueue.call_every(1, move5m);
eventQueue.call_every(1, move6m);
eventQueue.call_every(10, uartOutF);
eventQueue.dispatch_forever();
}
Firstly, i thought it's because of printf function, but i tried to disable it and monitoring with led. It's still executing slower than real time.
1 Answer
6 years ago.
Hello Alex,
Maybe it's because the EventQueue is starving. You can check it for example as follows:
...
Timer timer;
int buf[100];
int i = 0;
void move() {
buf[i++] = timer.read_us();
timer.reset();
if (i == 100) {
timer.stop();
for (int j = 0; j < i; j++) {
pc.printf("%d: 'move' called after %d us\r\n", j, buf[j]);
}
eventQueue.break_dispatch();
}
system1.zpOutput(1, 1, 1);
system2.zpOutput(2, 1, 1);
system3.zpOutput(3, 1, 1);
system4.zpOutput(4, 1, 1);
system5.zpOutput(5, 1, 1);
system6.zpOutput(6, 1, 1);
}
int main() {
pc.baud(115200);
eventQueue.call_every(1, move);
timer.start();
eventQueue.dispatch_forever();
}
move should be called after <= 1000 us for each iteration. Otherwise the eventQueue is starving and probably you need a faster hardware to run the controller in real time.
Hi, Zoltan, thank you for the answer. I tried your code, and the result is: function "move" was called in 998us in all 100 cases. But I also tried another code:
code2
#include "mbed.h"
#include "rtos.h"
#include "QEI.h"
DigitalOut led(PC_1);
void ledSw(){
led=!led;
}
Ticker timey;
int main() {
timey.attach(&ledSw, 5.0f);
}
Here, I switch the led in Interruption every 5 sec. And even in such simple program there is a delay. And the mistake is getting bigger with time. Firstly, it seemed ok, but then, after 2 minutes, delaay was about 1.5 sec. So i suspect the timer in controller is slower than it should be. How can i check it? Is it hardware or software problem?
posted by 08 Nov 2019What is your hardware? Is it a NUCLEO-F103RB board? If it is a Blue Pill or a custom board equipped with an external crystal oscillator then to select the correct clock source add an mbed_app.json file :
mbed_app.json
{
"target_overrides": {
"*": {
"target.clock_source": "USE_PLL_HSE_XTAL"
}
}
}
I'm using Black STM32f407vet6, and i write code in mbed studio. I choose SeeedArchMax as a target, cause it has the same microcontroller and pinnames. I tried to add this file. It built without errors, but didn't help. The same delay. PS: maybe it's important: when i open this file in mbed studio it says: Failed to start JSON language server: Error: Failed to spawn node Perhaps it is not on the PATH. but compiling goes without aany errors.
posted by 08 Nov 2019I'm sorry. There was an error in the mbed_app.json. It's fixed now. Copy & paste it to your project and compile again.
It's still the same. Maybe i should try internal oscillator? PS. The error with json server is also there. Does it matter? PPS. I tried the same program on the bluepill, there it works fine, without delays. PPPS. The problem really was in USE_PLL_HSE_XTAL. I found file "system_clock.c" in mbed sources and commented lines, where it tries to set USE_PLL_HSE_EXTC. After that it began to work fine. Thank you! And your way to do it with json didn't work because of the error i've written above (and it appears when i open any json file). I could not find the solution, so if you know how to fix it, i'd love to hear it. Thanks again!
posted by 08 Nov 2019