Zugriff auf GPIOs

Alles rund um die Programmierung mit Qt
Antworten
Rompestronk
Beiträge: 1
Registriert: 25. Juli 2018 11:01
Wohnort: Erzgebirge

Zugriff auf GPIOs

Beitrag von Rompestronk » 31. Juli 2018 10:41

Ich grüße euch!

In einem meiner Projekte versuche ich in einem QWidgets-Projekt auf die GPIOs eines Pi-Zero|zum entwickeln Pi1 zuzugreifen und dort je nach Pegel zu reagieren. Qt Version ist 5.10 auf Raspbian Jessie CLI / Host Ubuntu 18.04. Da ich jetzt insgesamt schon eine Woche herumprobiere und bisher keinen Erfolg hatte nun meine Frage; Was ist für euch der "beste" bzw. sicherste Weg die GPIO-Werte als Interrupt zu nutzen um bspw den Inhalt eines labels zu ändern? Wie geht ihr dabei vor?

Ansätze bisher waren QSocketNotifier und QFileSystemwatcher. Wäre es sinnvoller einfach mit QFile und Timer zu arbeiten?

Meine Versuche beinhalten unter anderem:

Code: Alles auswählen

#ifndef GPIOTRACKER_H
#define GPIOTRACKER_H

#include <QObject>
#include <QFile>
#include <QSocketNotifier>
#include <QDebug>
#include <QTimer>

typedef enum
{
    high = 1,
    low = 0
}gpiovalue_t;

class GpioTracker
      : public QObject
{
    Q_OBJECT

public:
    QString path = "/sys/class/gpio/gpio";

//___________Full-GPIO-Paths____________________
//    QString gpio4  = "/sys/class/gpio/gpio4";
//    QString gpio17 = "/sys/class/gpio/gpio17";
//    QString gpio22 = "/sys/class/gpio/gpio22";
//    QString gpio27 = "/sys/class/gpio/gpio27";
//______________________________________________

    QSocketNotifier *notifier;
    QFile file;
    int gpio;

    explicit GpioTracker(int gpio_nr, QObject *parent = nullptr);
    void connectGpio(int gpio_nr);
    ~GpioTracker();

    int lastValue;
    gpiovalue_t gpio4, gpio17, gpio22, gpio27;

signals:
    void gpioChanged(int value, int gpio);

public slots:
    void handle_readNotification(int socket);

private slots:
    void updateDebouncing();

private:
    int originalValue;
    int fd; //filedescriptor
    QTimer interval;
};

#endif // GPIOTRACKER_H

Code: Alles auswählen

#include "gpiotracker.h"

#include <fcntl.h>
#include <unistd.h>

GpioTracker::GpioTracker(int gpio_nr, QObject *parent)
   : QObject(parent)
{
    gpio = gpio_nr;
    QString filename = "/sys/class/gpio/gpio" + QString::number(gpio) + "/";
    QFile exportFile(filename +  "export");
    exportFile.open(QIODevice::WriteOnly);
    QString gpioNumber = QString::number(gpio);
    exportFile.write(gpioNumber.toUtf8());
    //mit diesem Ansatz habe ich die Gpios vor Ausführung der Executable/Debug mit einem Script initialisiert:
    QFile *file = new QFile();
    auto pathname = QStringLiteral("%1%2/value").arg(path).arg(gpio);
    qDebug() << pathname;
    file->setFileName(pathname);
//    QFile test;
//    test.setFileName("/sys/class/gpio/gpio4");
//    test.open(QIODevice::ReadOnly | QIODevice::Text);
//    qDebug() << test.readAll();
    //check if GPIO exists_____________
    if( !file->exists() )
    {
        qDebug() << pathname << " file does not exist";
        return;
    }
    qDebug() << file->readAll();
    //try opening GPIO_________________
    fd = open(pathname.toUtf8().data(), O_RDONLY|O_NONBLOCK);
    if( fd==-1 ){
        qDebug() << "can not open " << pathname;
        return;
    }
        notifier = new QSocketNotifier( fd,
                                        QSocketNotifier::Read,
                                        this );
        connect( notifier,
                 &QSocketNotifier::activated,
                 this,
                 &GpioTracker::handle_readNotification );
        qDebug() << "Notifiier connected!";

        QTimer *interval = new QTimer(this);
        connect(interval, SIGNAL(timeout()), this, SLOT(updateDebouncing()));
        //interval->start(3);

    //or this instead of the above approach -> also didnt work out so?!
//    QString filename = "/sys/class/gpio/gpio" + QString::number(gpio) + "/";

//    QFile exportFile(filename +  "export");
//    exportFile.open(QIODevice::WriteOnly);
//    QString gpioNumber = QString::number(gpio);
//    exportFile.write(gpioNumber.toUtf8());

//    QFile directionFile(filename + "direction");
//    directionFile.open(QIODevice::WriteOnly);
//    directionFile.write("in");

//    QFile edgeFile(filename + "edge");
//    edgeFile.open(QIODevice::WriteOnly);
//    edgeFile.write("both");

//    QFile* file = new QFile(filename + "value");
//    QSocketNotifier notifier(file->handle(), QSocketNotifier::Read);
//    connect(&notifier, &QSocketNotifier::activated, this, &GpioTracker::handle_readNotification);
}

GpioTracker::~GpioTracker()
{
    if( fd>=0 )
    {
        close(fd);
    }
    this->deleteLater();
    qDebug() << "gpio closed";
}

void GpioTracker::updateDebouncing()
{
    auto pathname = QStringLiteral("%1%2/value").arg(path).arg(gpio);
    if(file.fileName() != pathname)
    file.setFileName(pathname);
    int currentValue = file.readAll().toInt();
    if (lastValue == currentValue)
    {
        emit gpioChanged(currentValue, gpio);
    }
}

void GpioTracker::handle_readNotification(int /*socket*/)
{
    auto pathname = QStringLiteral("%1%2/value").arg(path).arg(gpio);
    if(file.fileName() != pathname)
    file.setFileName(pathname);
    int currentValue = file.readAll().toInt();
    originalValue = file.readAll().toInt();
//    static int failureCntr;
    if(file.readAll().toInt() != originalValue)
    {
//_________________Result=HIGH____________________________
        if(file.readAll() == "1")
        {
            currentValue = file.readAll().toInt();
            if (currentValue != lastValue) {
                interval.start(3);
            }
            lastValue = currentValue;
        }
//_________________Result=LOW____________________________
        if(file.readAll() == "0")
        {
            currentValue = file.readAll().toInt();
            if (currentValue != lastValue) {
                interval.start(3);
            }
            lastValue = currentValue;
        }
    }
}
//    static int failureCntr;
//    if(file.readAll() == "1")
//    {
//      emit gpioChanged(high, this);
//    }
//    else if(file.readAll() == "0")
//    {
//      emit gpioChanged(low, this);
//    }
//    else
//    {
//      failureCntr++;
//      qDebug() << "Failure Count: " << failureCntr;
//    }

Code: Alles auswählen

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

Code: Alles auswählen

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "gpiotracker.h"
#include <QFileSystemWatcher>
#include <QFile>
#include <QObject>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    GpioTracker* enter_key = new GpioTracker(4, this);
    GpioTracker* back_key = new GpioTracker(17, this);
    connectGpio(enter_key);
    connectGpio(back_key);
    qDebug() << "keys connected!";
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::connectGpio(GpioTracker* gpiotracker)
{
    QObject::connect(
        gpiotracker,
        SIGNAL(gpioChanged(int, int)),
        this,
        SLOT(handle_GpioValue(int, int))
    );
    qDebug() << "gpioChanged connected";
}

void MainWindow::handle_GpioValue(int value, int gpio)
{
    auto temp = gpio;
    auto printable = QStringLiteral("%1 is %2").arg(temp).arg(value);
    ui->label->setText(printable);
    qDebug() << "gpio value changed!";
}
QFile öffnet sich nicht:

Code: Alles auswählen

QIODevice::write (QFile, "/sys/class/gpio/gpio4/export"): device not open
"/sys/class/gpio/gpio4/value"
QIODevice::read (QFile, "/sys/class/gpio/gpio4/value"): device not open
...und das obwohl ich root bin (durch Terminal parameter in QtCreator) und der Pfad stimmt. :?:

Anbei noch ein Screenshot der GPIO Zustände [input, low-active, getestet mit opensource tool "gpiotest-master"] um festzustellen, dass diese durch mein startscript richtig konfiguriert sind.

Ich bin Qt-Neuling und diese ganze Situation bringt mich zur Verzweiflung. Ähnliche Ergebnisse habe ich mit dem Filesystemwatcher.

Vielen Dank schonmal,
Erwin Rompe
Dateianhänge
gpio-test_from_2018-07-31_10-18-02.png
gpio-test_from_2018-07-31_10-18-02.png (112.03 KiB) 208 mal betrachtet

Antworten