RPi Qt GPIO, Tactile switch

Fórumok

Üdv!

Adott egy TFT RPi-hez, ill ehhez adnak tactile switch-eket (gombokat). (TFT http://adafru.it/1601)
Ez ha jól tudom az ún GPIO-n kapcsolódik az RPi-n. Ezeket a gombokat ill. a lenyomásukat (eseményeket) el lehet érni Qt (C++) segítségével is?

Csinált már ilyet valaki?

update:
A GPIO documentation, amin a TFT is van.

--
G.

Hozzászólások

Ez thread mintha ilyesmiről szólna.
Kérdés, hogy qemu-ban tudom-e tesztelni ezt a tactile switch gombot.

--
G.

Hát én így érem el a 34-ik gpio-t...qt-ből (habár ebben nem sok qt van :) inkább csak sima c)

...
FILE* f = fopen("/sys/class/gpio/gpio34/value", "rb");
if(f != NULL)
{
int i;
if(fscanf(f, "%d", &i) == EOF)
emit message(QString("RUBE failed EOF! [%1]").arg(errno));
fclose(f);
return i;
}
...

szerk.: Ahogy látom a linkedet neked a GPIO #23, #22, #21, and #18 kell...

Hát én ezt roppant egyszerűen oldottam meg, igaz valószínűleg nem a leghatékonyabb módon...
Én létrehoztam egy szálat (QThread-től származó class) amelyik állandóan (10ms sleep-el a while-ban) nézi az általam érdekes
GPIO-k értékeit, és amennyiben változás történt akkor emit-elek egy signált amelyet a megfelelő
osztályokban létrehozott slotok kapnak el.
Értelem szerűen ezt a szálat a main-ben indítom el az ablak(ok) létrehozása előtt, és a kilépés gomb megnyomásakor
állítom le. Nekem ez egy teljes képernyős progiban fut és amikor valaki megnyomja a kilép gombot akkor a pi-t le is
állítom, mert így kell nekem...
így érthető ?

Nálam a RPi-n nincs:
/sys/class/gpio/gpio23/value
/sys/class/gpio/gpio22/value
/sys/class/gpio/gpio21/value
...stb.

A /sys/class/gpio könyvtárban van:
export, unexport állományok és két symlink:
gpiochip0 -> ../../devices/virtual/gpio/gpiochip0
gpiochip250 -> ../../devices/platform/bcm2708_spi.0/spi_master/spi0/spi0.1/stmpe-gpio.0/gpio/gpiochip250

A GPIO eléréséhez kell kernel modul? Vagy nálam miért hiányoznak az említett "value" fájlok?

--
G.

Létre kell hozni őket: https://www.kernel.org/doc/Documentation/gpio/sysfs.txt
echo 23 > export
echo 22 > export
echo 21 > export
echo 27 > export
echo 18 > export

(Minden újraindításkor meg kell tennem.)

Ez létrehozza a megfelelő könyvtárstruktúrát. De ha megnyomok (és lenyomva tartok) egy gombot (pl. #18) nem íródik a /sys/class/gpio/gpio18/value
fájlba semmi, pontosabban marad a 0 érték.
Mit hagyok ki?

--
G.

Ez alapján próbáltam egy python tesztet:


#!/usr/bin/env python

import time
import RPi.GPIO as GPIO

def main():

GPIO.setmode(GPIO.BCM)

# setup pin 22 as an input
GPIO.setup(22,GPIO.IN)

while True:
if GPIO.input(22):
print "Button pressed"

time.sleep(0.1)

print "Button pushed"

GPIO.cleanup()

if __name__=="__main__":
main()

A python progi nem írta ki gombnyomásra a "Button pressed" feliratot. Valami hiányzik még. :(

--
G.

Érdekes a dolog. Ez alapján a "Tactile switch as power button" működik.
A feliratok a TFT alatt ezek voltak egyébként a pin-ekhez:

#23 #22 #21/#27 #18

A #21 alatt #27 is van, és igazából az működik. :o

De a lényeg, hogy a gombok ezzel működnek, csak C/C++-ból kellene elérnem, ill. (pl.) a /sys/class/gpio/gpio18/value fájlba nem íródik be az "1" érték.
A fájlok és tartalmaik:

'action_low': "0"
'direction': "in"
'edge': "none"
'uevent': ""
'value': "0"

--
G.

Működnek a gombok és az állapotok. Köszönet Gordon Hendersonnak. :)
https://projects.drogon.net/raspberry-pi/wiringpi/the-gpio-utility/
http://wiringpi.com/
http://wiringpi.com/download-and-install/


sudo apt-get install git-core
git clone git://git.drogon.net/wiringPi
cd wiringPi
./build

Pl. a pin #18 beállítása:

# pin #18 create:
gpio export 18 in
# internal pull-up resistor, ez hiányzott:
gpio -g mode 18 up
# pin #18 állapota
gpio -g read 18

Az alapértelemezett állapot "1" és a gombnyomásra "0" értéket ad vissza.

Végre megvan, már csak Qt - C/C++-ban kell elérnem. :)

--
G.

subscribe

* Én egy indián vagyok. Minden indián hazudik.

GPIO Qt-ben ezeket találtam:
http://hertaville.com/2012/11/18/introduction-to-accessing-the-raspberr…
https://qt-project.org/doc/qt-4.8/qsocketnotifier.html
http://qt-project.org/forums/viewthread/41824

Ez egy minta projekt:
https://github.com/kenaaker/BeagleBoneBlack

Ebben van egy "gpio_keypad.cpp", ez a szép megoldás a GPIO button lenyomás esemény kezelésére?

// gpio_keypad.h
#ifndef GPIO_KEYPAD_H
#define GPIO_KEYPAD_H

#include
#include
#include
#include
#include "adafruit_bbio_gpio.h"

class gpio_keypad : public QObject {
Q_OBJECT
public:
gpio_keypad(QString sw_pin, QString in_key_name);
~gpio_keypad();
int keypad_fd(void); /* Return the file descriptor for the keypad interrupt device */
QString const keyname(void); /* Return the name of the key for this object */
signals:
void button_pushed(int on_off);
private:
Adafruit_bbio_gpio *this_gpio; /* GPIO object for this pin */
QFile keypad_value; /* GPIO keypad value file for keypad file. */
QString key_name; /* User name for this key */
QSocketNotifier *keypad_notifier;
char current_value; /* The last value read from the GPIO */
public slots:
void ready_read(int);
};


// gpio_keypad.cpp
#include "gpio_keypad.h"
#include

gpio_keypad::gpio_keypad(QString sw_pin, QString in_key_name) {

this_gpio = new Adafruit_bbio_gpio(sw_pin.toStdString());
if (!this_gpio) {
abort();
} else {
QString gpio_value_path;
key_name = in_key_name;
gpio_value_path = QString::fromStdString(this_gpio->gpio_get_path());
// qDebug() << "keypad path=" << gpio_value_path;
keypad_value.setFileName(gpio_value_path); /* Set up the value file */
this_gpio->gpio_set_direction("in");
this_gpio->gpio_set_edge("both"); /* Interrupt on rising edge */
keypad_value.open(QFile::ReadOnly);
keypad_notifier = new QSocketNotifier(keypad_value.handle(), QSocketNotifier::Exception);
keypad_notifier->setEnabled(true);
connect(keypad_notifier, SIGNAL(activated(int)), this, SLOT(ready_read(int)));
} /* endif */
}

gpio_keypad::~gpio_keypad() {
keypad_value.close();
this_gpio->gpio_set_edge("none"); /* Don't generate interrupts. */
delete keypad_notifier;
delete this_gpio;
}

int gpio_keypad::keypad_fd(void) {
return keypad_value.handle();
} /* keypad_fd */

QString const gpio_keypad::keyname(void) {
return(key_name);
} /* keyname */

void gpio_keypad::ready_read(int) {
QByteArray line;
keypad_value.seek(0);
char last_value = current_value;
line = keypad_value.readAll();
// qDebug() << "bytes_read=" << line.size();
if (line.size() < 1) {
abort();
} else {
current_value = line[0];
emit button_pushed(current_value);
} /* endif */
if (current_value != last_value) {
// qDebug() << "key" << key_name << "switch value changed, old=" << last_value << "current_value" << current_value;
} /* endif */

Bár itt a gpio portok beállítása is benne van (export ...stb.), ami nem biztos, hogy jó, mert a "gpio -g mode #pin_num up" is kellene. Lsd. itt

--
G.

Egy egyszerű C++ mintát kipróbáltam: http://hertaville.com/2012/11/18/introduction-to-accessing-the-raspberr…
GPIOClass.cpp (GPIOClass.h)
GPIOtest1.cpp

A mintában levő gpio17 pin-t átírtam 18-ra és szépen működött. A konzolon irogatta a pin státuszát ("1"), majd gombnyomásra kiírta a gombnyomás eseményét ("Pressed")... stb.

Szóval már csak Qt alatt kellene megoldanom ezt. :)

--
G.

Teszt jelleggel csináltam egy /tmp/testfile állományt emuláció gyanánt. Tartalma: 1
Az echo 0 > /tmp/testfile paranncsal próbálom szimulálni a "socket" változást.
Qt-ben ezt próbáltam:


// mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include
#include
#include

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

// QSocketNotifier *****************************************************
QFile file("/tmp/testfile");
if(file.open(QFile::ReadOnly)) {
QSocketNotifier sn(file.handle(), QSocketNotifier::Read, this);
sn.setEnabled(true);
connect(&sn, SIGNAL(activated(int)), this, SLOT(socket_on_changed()));
}
}

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

/* onChangedSocket */
void MainWindow::socket_on_changed()
{
ui->lineEdit->setText("Socket on changed...");
QMessageBox msgBox;
msgBox.setText("Socket on changed...");
msgBox.exec();
}

Valamit kihagyok az biztos, de mit? A /tmp/testfile tartalmi változása nem csinál semmit a Qt app-ban. Mi hiányzik még?
Egy emittálás kellene valahova? (emit ....)

--
G.

Azt hiszem megvan. Nem a QSocketNotifier kell, hanem a QFileSystemWatcher.

Egy mintát találtam könyvtármódosulásra itt, amit teszt jelleggel módosítottam fájlra:

MyClass.h

#ifndef MYCLASS_H
#define MYCLASS_H

#include
#include

class MyClass : public QWidget
{
Q_OBJECT

public:
MyClass(QWidget* parent=0)
:QWidget(parent){}

~MyClass(){}

public slots:
void showModified(const QString& str)
{
Q_UNUSED(str)
// QMessageBox::information(this,"Directory Modified", "Your Directory is modified");
QMessageBox::information(this,"File Modified", "Your File is modified");
}
};

#endif // MYCLASS_H

MyClass.cpp

#include
#include
#include

#include "MyClass.h"

int main(int argc, char* argv[])
{
QString const FILEPATH = "/tmp/testfile";

QApplication app(argc, argv);
QFileSystemWatcher watcher;
//watcher.addPath("/tmp");
watcher.addPath( FILEPATH );

//QStringList directoryList = watcher.directories();
//Q_FOREACH(QString directory, directoryList)
// qDebug() << "Directory name" << directory <<"\n";
qDebug() << "File name: " << FILEPATH <<"\n";

MyClass* mc = new MyClass;

//QObject::connect(&watcher, SIGNAL(directoryChanged(QString)), mc, SLOT(showModified(QString)));
QObject::connect(&watcher, SIGNAL(fileChanged(QString)), mc, SLOT(showModified(QString)));

return app.exec();
}

Futtatás hatására a /tmp/testfile tartalmának módosításával felugrik egy Qt ablak. :)
Szépen működik. Tehát ha minden igaz, akkor a GPIO kezelhető hasonlóképpen.

--
G.

Nem tudom, hogy mennyire szép, de működik:

void MainWindow::fileChanged(const QString & path)
// void showModified(const QString& path)
{
// get the file content
QFile file("/tmp/testfile");
if(!file.open(QIODevice::ReadOnly))
{
qDebug() << "Error opening file: " << file.error();
return;
}

QTextStream instream(&file);
QString line = instream.readLine();

qDebug() << "First line: " << line;
file.close();
// end of file content reading
QMessageBox::information(this,"File changed","The File changed: " + path + ", content: " + line);
}

--
G.