adding qtimer with wiringPiISR
-
Hello,
I have created a class
Capteur_Input
and one of the options in the constructor creates an interrupt usingwiringPiISR
wiringPiISR(m_pin, INT_EDGE_RISING, isrInput);
my class also has an attribute
m_impulsion
and I am incrementing this value each time that an interruption happens.this what my interrupt handler looks like
void Capteur_Input::isrCallback() { if(m_pin== Pin_vitesse) { increment_impulsion(); emit digital_inputChanged(m_impulsion); } else emit digital_inputChanged(m_value); }
in my main.cpp I created an instance of this class
static void isrInput_vitesse(); static Capteur_Input vitesse(Pin_vitesse,PUD_OFF,INT_EDGE_RISING,isrInput_vitesse); static void isrInput_vitesse() { vitesse.isrCallback(); }
every thing is working fine, the qml and C++ part.
and now I want to calculate the number of impulse detected per second. but I couldn't do it.
my class
Capteur_Input
also has a timer, I configured it in the constructorm_timer =new QTimer (this); m_timer->setTimerType(Qt::PreciseTimer); QObject::connect(m_timer, &QTimer::timeout, this, &Capteur_Input::onTimeout, Qt::DirectConnection); m_timer->start(500);
and I tried to test in the SLOT onTimeout() someting but this
qDebug()<<"VITESSEEEEEEEE"<<m_pin <<readPin()<<vitesse;
never shows up. I don't know why maybe because wiringPiISR is a thread and has a higher priority than the timer?
can someone explain to me please, how to make a timer that calculates the exact time and make the interrupt work in the same time?
the timer is working for the other instances of this class that are just inputs no interruptionsvoid Capteur_Input::onTimeout() { if(m_pin==Pin_vitesse) { int vitesse; calcul_vitesse = m_impulsion - calcul_vitesse; vitesse= int (calcul_vitesse/4*2.166); emit vitesse_Changed(vitesse); qDebug()<<"VITESSEEEEEEEE"<<vitesse; } else{ emit digital_inputChanged(readPin()); qDebug()<<"signal DIGITAL emitted"<<m_pin <<readPin(); } }
thank you !
-
I posted this in an other forum because it has been a while that I am stuck and it has to be fixed .. I am going to share the solution it may help someone https://stackoverflow.com/questions/66869600/timer-couldnt-work-with-wiringpiisr-qtquick-application/66873812?noredirect=1#comment118230663_66873812
static instances of QObject are also not supported
so the instance vitesse should be created after QApplication.
this will fix the problem :static void isrInput_vitesse(); static Capteur_Input *vitesse = nullptr; static void isrInput_vitesse() { if(!vitesse) //not initialized yet return; QMetaObject::invokeMethod( vitesse, "isrCallback", Qt::QueuedConnection ); //or blockingQueue if you need to handle it directly in Qt way. } and in the main fucntion int main(int argc, char *argv[]) { QApplication a(argc, argv); //..... your main application body vitesse = new Capteur_Input(Pin_vitesse,PUD_OFF,INT_EDGE_RISING,isrInput_vitesse); ctx->setContextProperty("vitesse", vitesse); //... }
the function
isrCallback
should be a slot -
@amina said in timer couldn't work with wiringPiISR:
and now I want to calculate the number of impulse detected per second
Then the timeout should be 1000 not 500.
Also, wouldn't it be enough to use the number of calls of your isrCallback()? I don't know why you are doing this complex calculations inside onTimeout. You should simply have a counter incremented inside isrCallback() which you read in onTimeout to get the number of calls and then set to 0 for the next timeout. -
@jsulm
I just wanted to test that's why there is 500.
my problem is that in the timeout function it never executes the instructions
under this condition I don't know why
if(m_pin==Pin_vitesse)
{
int vitesse;
calcul_vitesse=m_impulsion-calcul_vitesse;
vitesse= int (calcul_vitesse/4*2.166);
emit vitesse_Changed(vitesse);
qDebug()<<"VITESSEEEEEEEE"<<vitesse;
}
in the isrCallback I am incrementingm_impulsion
so I am counting the number of impulses and in my onTimeout fonction I am calculating the numbre of impulses each timeout.
and I am trying to calculate a speed m/s , each turn I have 4 impulses and 2.166 is the perimeter of the wheel -
-
@jsulm said in adding qtimer with wiringPiISR:
Why do you need this?
because I have two other instances of this class, so in the slot onTimeout I just want to calculate the speed of this instance and not for the others
static Capteur_Input vitesse(Pin_vitesse,PUD_OFF,INT_EDGE_RISING,isrInput_vitesse);
Capteur_Input frein(PinFrein,PUD_UP,NO_INTERRUPT); Capteur_Input clignotant_G(PinClignotnat_G,PUD_DOWN,NO_INTERRUPT);
maybe I should create 2 classes one for inputs and another for interruptions
-
@jsulm said in adding qtimer with wiringPiISR:
void Capteur_Input::onTimeout() { qDebug()<<"time is up"; if(m_pin== Pin_vitesse) { qDebug()<<"m_pin== Pin_vitesse"; int vitesse; vitesse= int (calcul_vitesse/4*2.166);//*0.001/3600; qDebug()<<"VITESSEEEEEEEE"<<m_pin <<readPin()<<vitesse; emit vitesse_Changed(vitesse); qDebug()<<"VITESSEEEEEEEE"<<m_pin <<readPin()<<vitesse; } else{ emit digital_inputChanged(readPin()); qDebug()<<"signal DIGITAL emitted m_pin"<<m_pin <<"value"<<readPin(); } }
and this is the output so there is an output for the other two instances(frein,clignotant_G) and not the one that is an interrupt (Vitesse)
time is up signal DIGITAL emitted m_pin 0 value 1 time is up signal DIGITAL emitted m_pin 2 value 0
the funny thing is that I used this same condition in the isrCallback and it is working this why i said maybe it is a thread problem ..
-
So it seems that your if condition is never true.
Ism_pin
coming from yourwiringPiISR
interrupt function or is it set to a certain value? Print these values before theif
clause. What value isPin_vitesse
?Edit:
Have you seen this?
- int wiringPiISR (int pin, int edgeType, void (*function)(void)) ;
The function will be called when the interrupt triggers. When it is triggered, it’s cleared in the dispatcher before calling your function, so if a subsequent interrupt fires before you finish your handler, then it won’t be missed. (However it can only track one more interrupt, if more than one interrupt fires while one is being handled then they will be ignored)
Could be possible that all your interrupts on
pin_vitesse
are getting ignored. What happens in your interrupt function? -
@Pl45m4
m_pin is one of the attributes of this class
Capteur_Input::Capteur_Input(int pin,int pud,int edge,void (*isrInput)(),QObject *parent):Capteur_(pin,parent)
and it contains the gpio pin of my sensor I devined them in my
capteur_Input.h
#define Pin_vitesse 3 #define PinFrein 0 #define PinClignotnat_G 2
void Capteur_Input::onTimeout() { qDebug()<<"time is up"<<m_pin; if(m_pin== Pin_vitesse) {
I added this before the condition and this is what I got as an output
time is up 0 signal DIGITAL emitted 0 1 time is up 2 signal DIGITAL emitted 2 0 time is up 0 signal DIGITAL emitted 0 1 time is up 2
so the instance
static Capteur_Input vitesse(Pin_vitesse,PUD_OFF,INT_EDGE_RISING,isrInput_vitesse);
is never executing the slot onTimeout ..the interrupts are not getting ingored, The interrupt function is incrementing an attribut m_impulsion and I am acually showing this number of pulses in the qml part so each interruption the number changes ..
-
@amina said in adding qtimer with wiringPiISR:
static Capteur_Input vitesse(Pin_vitesse,PUD_OFF,INT_EDGE_RISING,isrInput_vitesse);
Where exactly is this code located? You really need to debug your code to see whether vitesse is really created and what happens there.
-
@jsulm
it is located in my main.cppstatic void isrInput_vitesse(); static Capteur_Input vitesse(Pin_vitesse,PUD_OFF,INT_EDGE_RISING,isrInput_vitesse); static void isrInput_vitesse() { vitesse.isrCallback(); } int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); QQmlApplicationEngine engine; Capteur_Input frein(PinFrein,PUD_UP,NO_INTERRUPT); Capteur_Input clignotant_G(PinClignotnat_G,PUD_DOWN,NO_INTERRUPT); Capteur_ADC essence(-1,ADRESS,AIN1,DEVICE_ID); Capteur_ADC temperature(-1,ADRESS,AIN2,DEVICE_ID); QQmlContext* ctx = engine.rootContext(); ctx->setContextProperty("frein", &frein); ctx->setContextProperty("vitesse", &vitesse); ctx->setContextProperty("essence", &essence); ctx->setContextProperty("clignotant_G", &clignotant_G); ctx->setContextProperty("temperature", &temperature); const QUrl url(QStringLiteral("qrc:/main.qml")); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec(); }
I tried to debbug , and vitesse is created and is creating the timer , this is my constructor and it is executing the commands that starts a timer ..
Capteur_Input::Capteur_Input(int pin,int pud,int edge,void (*isrInput)(),QObject *parent):Capteur_(pin,parent) { m_pud=pud; m_impulsion=0; m_typeIO=INPUT; calcul_vitesse=0; wiringPiSetup(); switch (edge) { case NO_INTERRUPT: { pinMode(m_pin,INPUT); pullUpDnControl (m_pin, m_pud) ; } break; case INT_EDGE_SETUP: { pinMode(m_pin,INPUT); pullUpDnControl (m_pin, m_pud) ; wiringPiISR(m_pin, INT_EDGE_SETUP, isrInput); } break; case INT_EDGE_FALLING: { pinMode(m_pin,INPUT); pullUpDnControl (m_pin, m_pud) ; wiringPiISR(m_pin, INT_EDGE_FALLING, isrInput); } break; case INT_EDGE_RISING: { pinMode(m_pin,INPUT); pullUpDnControl (m_pin, m_pud) ; wiringPiISR(m_pin, INT_EDGE_RISING, isrInput); } break; case INT_EDGE_BOTH: { pinMode(m_pin,INPUT); pullUpDnControl (m_pin, m_pud) ; wiringPiISR(m_pin, INT_EDGE_BOTH, isrInput); } break; } m_timer =new QTimer (this); m_timer->setTimerType(Qt::PreciseTimer); QObject::connect(m_timer, &QTimer::timeout, this, &Capteur_Input::onTimeout, Qt::DirectConnection); m_timer->start(1000); }
-
I posted this in an other forum because it has been a while that I am stuck and it has to be fixed .. I am going to share the solution it may help someone https://stackoverflow.com/questions/66869600/timer-couldnt-work-with-wiringpiisr-qtquick-application/66873812?noredirect=1#comment118230663_66873812
static instances of QObject are also not supported
so the instance vitesse should be created after QApplication.
this will fix the problem :static void isrInput_vitesse(); static Capteur_Input *vitesse = nullptr; static void isrInput_vitesse() { if(!vitesse) //not initialized yet return; QMetaObject::invokeMethod( vitesse, "isrCallback", Qt::QueuedConnection ); //or blockingQueue if you need to handle it directly in Qt way. } and in the main fucntion int main(int argc, char *argv[]) { QApplication a(argc, argv); //..... your main application body vitesse = new Capteur_Input(Pin_vitesse,PUD_OFF,INT_EDGE_RISING,isrInput_vitesse); ctx->setContextProperty("vitesse", vitesse); //... }
the function
isrCallback
should be a slot