Ü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.
- 7500 megtekintés
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.
- A hozzászóláshoz be kell jelentkezni
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...
- A hozzászóláshoz be kell jelentkezni
Aha... Itt találtam egy qt- mintát.
Azt meg tudná világítani valaki, hogy a gomb lenyomás esemény elkapása hol történik?
A mintakódodat hova kell tenni? Hogyan észleled a 34-ik gpio-n az esemény bekövetkezését? Ez nem egészen világos még.
--
G.
- A hozzászóláshoz be kell jelentkezni
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ő ?
- A hozzászóláshoz be kell jelentkezni
Értem, de majd lehet, hogy kérdezek... ha szabad. :)
--
G.
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
- A hozzászóláshoz be kell jelentkezni
Igen. Ezt olvasom én is. De kellhet neki egy modul(?)
"Kézzel" kell létrehozni ezeket minden induláskor?
--
G.
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
É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.
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
subscribe
* Én egy indián vagyok. Minden indián hazudik.
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
Még az érdekelne, hogy ha a fileChanged eseménykor (signal) mi az új tartalom.
Tehát a /tmp/testfile fájl tartalma megváltozott, akkor mi lett az új tartalom. Ez az showModified()-ban csak kérdezzem le egy sima fájlművelettel a /tmp/testfile tartalmát?
--
G.
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni