3

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);
    connect (m_timer,SIGNAL(timeout()),this,SLOT(onTimeout()));
    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()
{
    qDebug()<<"time is up"<<m_pin;

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

actually the slot onTimeout is working for these 2 instances

#define Pin_vitesse 3
#define PinFrein 0
#define PinClignotnat_G 2

Capteur_Input frein(PinFrein,PUD_UP,NO_INTERRUPT);
Capteur_Input clignotant_G(PinClignotnat_G,PUD_DOWN,NO_INTERRUPT);

and is not working for this one which is an interrupt static Capteur_Input vitesse(Pin_vitesse,PUD_OFF,INT_EDGE_RISING,isrInput_vitesse);

and this 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

the timer is working for the other instances and it is not working for the one that is an interrupt

mina
  • 185
  • 1
  • 7
  • It could be you have a loop on `emit vitesse_Changed(vitesse)` because the slot that the signal is connected to will run if it's a `DirectConnection`. Hence if you moved the qDebug call to the line before you may see it appear – 0RR Mar 30 '21 at 11:39
  • I moved it but it didn't appear :/ – mina Mar 30 '21 at 12:04
  • It seems that the event loops that handle timer events didn't work (main event loop). Do you have something like app.exec() ? Capteur_Input is QObject based with Q_OBJECT macro in the class definition? – tunglt Mar 30 '21 at 12:23
  • I edited my post , the timer works fine for the other instances of this class and the class Capteur_Input inherites fron Capteur_ which is a QObject class and contains the macro Q_OBJECT – mina Mar 31 '21 at 09:38

2 Answers2

3

Static QObject instance is not supported in Qt, as stated below (QObject reentrancy section ):

In general, creating QObjects before the QApplication is not supported and can lead to weird crashes on exit, depending on the platform. This means static instances of QObject are also not supported. A properly structured single or multi-threaded application should make the QApplication be the first created, and last destroyed QObject.

If you need a callback when isr interrupt comes up, a static pointer should work:

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.
}

The vitesse pointer should be initialized in main() after the initialization of QApplication instance.

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

       //...
 } 
tunglt
  • 1,022
  • 1
  • 9
  • 16
  • Thank you for clarifying. but I got an error when I tried to test this telling that `invokeMethod is not a membre of QObject` and also `QVariant::QVariant(void*)` is private within this context ctx->setContextProperty("vitesse", &vitesse); ^ – mina Mar 31 '21 at 08:01
  • 1
    My mistake, it means QMetaObject instead of QObject. I've edited my answerer. `isrCallback` should be declared as a Qt slot function. – tunglt Mar 31 '21 at 08:50
  • it fixed the first error and as you said I declared isrCallback as a slot `public slots: void isrCallback(); `but I still got these two errors :83: error: ‘QVariant::QVariant(void*)’ is private within this context ctx->setContextProperty("vitesse", &vitesse); ^ – mina Mar 31 '21 at 09:30
  • 83: error: use of deleted function ‘QVariant::QVariant(void*)’ ctx->setContextProperty("vitesse", &vitesse); ^ – mina Mar 31 '21 at 09:31
  • in the error when I click on the `declare private here` and `declare here` it leads me tho the `qvariant.h` and to this line `\private: // force compile error, prevent QVariant(bool) to be called inline QVariant(void *) = delete; // QVariant::Type is marked as \obsolete, but we don't want to // provide a constructor from its intended replacement, // QMetaType::Type, instead, because the idea behind these // constructors is flawed in the first place. But we also don't` – mina Mar 31 '21 at 09:36
  • 1
    As I don't have your codes, the setContextProperty() seems to use `vitesse` instance pointer as its "vitesse" properties. Try to modify it to `ctx->setContextProperty("vitesse", vitesse)` because vitesse variable is now a pointer, not a class instance. – tunglt Mar 31 '21 at 09:41
  • 1
    oh yes it is a pointer .. now it is working :D thank you A LO. it s been a while that I am trying to fix this ! THANK YOU again :D – mina Mar 31 '21 at 10:02
0

Your timeout signal might be interfered or delayed.

You may try to specify a Qt::Connectiontype to force Qt to treat your timeout signal as soon as it is emitted.

QObject::connect(m_timer, &QTimer::timeout, this, &Capteur_Input::onTimeOut, Qt::DirectConnection);

This will deliver the timeout signal to the ontimeOut slot as soon as it is emitted.

Pat. ANDRIA
  • 2,330
  • 1
  • 13
  • 27
  • I just edited my post , the timer is working correctly with the 2 others instances of this class that are not a interrupt. – mina Mar 31 '21 at 08:08