Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

adding qtimer with wiringPiISR



  • Hello,

    I have created a class Capteur_Input and one of the options in the constructor creates an interrupt using wiringPiISR

    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 constructor

    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(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 interruptions

    void 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 !



  • @amina

    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


  • Lifetime Qt Champion

    @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 incrementing m_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


  • Lifetime Qt Champion

    @amina said in adding qtimer with wiringPiISR:

    if(m_pin==Pin_vitesse)

    Why do you need this?



  • @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


  • Lifetime Qt Champion

    @amina put another qDebug before the if() - do you see its output?



  • @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 ..



  • @amina

    So it seems that your if condition is never true.
    Is m_pin coming from your wiringPiISR interrupt function or is it set to a certain value? Print these values before the if clause. What value is Pin_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 ..


  • Lifetime Qt Champion

    @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.cpp

    static 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);
    }
    


  • @amina

    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