Interface Gainable en Qt sur RPi

grand merci !

tu connait le raspberry pi ? car je veux creer un menu tactile avec ma machine a etats :

(j'ai tous ce qu'il faut au niveau materiel ) mais je ne sais pas trop comment mi prendre pour creer ce menu .
j'ai installer tans bien que mal qt creator mais il fait beuger mon rpi , il peut faire de la compilation croiser mais je pas tres competent ! je voudrais rester en c++
que me conseillez vous ?

Perso s'il s'agit de faire une petite interface rapidement, j'utiliserais python

Qt pourquoi pas, je ne l'ai jamais utilisé vraiment, je n'aime pas les outils cross plateforme

ci j'utilise python , je suis obliger de transformer ma machine a etat en python?

Ben oui... mais si vous ne connaissez pas python restez en C++

la création d'une interface est laborieuse sauf à utiliser un framework en effet et Qt est populaire pour cela (regardez wxWidgets ou SFML éventuellement)

Bonjour,

J'interviens sur ce point car j'avais promis a Ludo de lui montrer comment j'avais résolut mon souhait de faire 1 interface graphique communiquant entre Arduino et Rpi.

La version de mon code fonctionne pour mes besoins, mais je voulais l'améliorer, donc je n'ai rien envoyé encore.

Coté Rpi, j'utilise python et Tkinter, je ne suis pas un pro du code.

J'utilise une liaison série filaire entre Arduino et Rpi

Je n'ai pas vos talents à tous les 2.

J'ai donc définis un protocole personnel pour envoyer et recevoir, c'est peut être un peu lourd et pas trés rapide, je n'ai pas pour l'instant rencontré de PB de synchronisation.

J'avance lentement (je n'y passe pas assez de temps).

J'essaie de passer par le Bluetooth (Rpi<--->HC05) je n'ai pas résolut le bug.

Enfin bref.

Je veux bien montrer ce que j'ai et que je suis en train de restructurer, j'hésitais à le faire car c'est pas au top.

Mais j'aimerais bien avoir l'avis de JML sur le trio python (qui n'est pas si compliqué) Tkinter, et liaison série pour faire un truc blindé pour une appli comme celle de Ludo.

j'utilise souvent python et Tkinter est bien aussi

concernant la communication entre Arduino et Python, j'ai un petit tuto la dessus

J’avais déjà fait mon code sur python ! Mais j’ai des variables local qui posait problème !

Merci, je regarderais cela à tête reposée.

J’avais eu aussi une librairie de machines à état python ! Je retrouve cela et je vais le poster ! Donc cela serait plus facile si tout est en python ! As tu des logiciels pour cela , car je voudrais qu’il fonctionne avec ou sans internet !

#/usr/bin/python3 # -*- coding:UTF-8 -*
import time
import RPi.GPIO as GPIO # Ajouter la gestion des GPIO

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

relaiAutoEteHiver = 26
relaiComp = 5
relaiV4V = 6
relaiVentUnitExt = 13
relaiVitessVentExt = 16
relaiVentUnitInt = 19
relaiVitessVentInt = 20

GPIO.setup(relaiAutoEteHiver,GPIO.OUT, initial = GPIO.HIGH)
GPIO.setup(relaiComp,GPIO.OUT, initial = GPIO.HIGH)
GPIO.setup(relaiV4V,GPIO.OUT, initial = GPIO.HIGH)
GPIO.setup(relaiVentUnitExt,GPIO.OUT, initial = GPIO.HIGH)
GPIO.setup(relaiVitessVentExt,GPIO.OUT, initial = GPIO.HIGH)
GPIO.setup(relaiVentUnitInt,GPIO.OUT, initial = GPIO.HIGH)
GPIO.setup(relaiVitessVentInt,GPIO.OUT, initial = GPIO.HIGH)

pinThermostats = 17

GPIO.setup(pinThermostats,GPIO.IN)

consigneExt = 13.5 # Consigne temperature de l'automatique 13,5°C // pour test 23.5
consigneCa = 30.0
consigneVentExtFr = 25.0
consigneVentExtCh = 5.0
consigneVentIntFr = 23.0
consigneVentIntCh = 23.0
consigneDemarageVentUnitIntCh = 35.0
consigneDegElectric = 5.0

millis = lambda: int(round(time.time()))
tempoComp = 10
tempoDepartComp = millis()
tempoDegCh = 25
tempoDepartDegCh = millis()
tempoV4VDegEl = 5
tempoDepartV4VDegEl = millis()
tempoCompDegEl = 5
tempoDepartCompDegEl = millis()

# Lecture température DS18B20
def lireFichier(emplacement):
    
    fichTemp = open(emplacement)
    contenu = fichTemp.read()
    fichTemp.close()
    return contenu
    
# Recuperation temperature DS18B20
def recupTemp(contenuFich):
    
    temperature = float(contenuFich)
    temperature = temperature / 1000
    return temperature
    
# Mon code 
try:
    while True:
        
        contenuFich = lireFichier("/sys/bus/w1/devices/28-01192ee0cfef/temperature")  # contenuFich la temperature
        temperatureExt = recupTemp(contenuFich)
        consigneDelta = temperatureExt - 6
        
        print("%s" %time.strftime("%d/%m/%y %H:%M"))
        print("TempExt: " + str(temperatureExt)+"°C")
        print("TempDeltacanicule: " + str(consigneDelta))
        print("tempoDepartComp: " + str(tempoDepartComp))
        print("tempoDepartDegCh : " + str(tempoDepartDegCh))
        print("millis: "+ str(millis()))
        
        etatThermostats = GPIO.input(pinThermostats)
           
        if temperatureExt <= consigneExt:
            GPIO.output(relaiAutoEteHiver, GPIO.LOW)
            print("MODE CHAUFFAGE")
            
            if etatThermostats == 0:
                GPIO.output(relaiVentUnitExt, GPIO.LOW)
                print("relaiVentUnitExterieur oN")
                
                if temperatureExt < consigneVentExtCh:
                    GPIO.output(relaiVitessVentExt, GPIO.LOW)
                    print("relaiVentGrandeVitesse oN")
                else:
                    GPIO.output(relaiVitessVentExt, GPIO.HIGH)
                    print("relaiVentPetiteVitesse oN")
                    
                if millis() > (tempoDepartComp + tempoComp):
                    GPIO.output(relaiComp, GPIO.LOW)
                    print("relaiComp oN")
                    
                    if millis() > (tempoDepartDegCh + tempoDegCh):
                        GPIO.output(relaiComp, GPIO.HIGH)
                    #GPIO.output(relaiVentUnitExt, GPIO.HIGH)
                    #GPIO.output(relaiVitessVentExt, GPIO.HIGH)
                        print("tousRelais oFF")
                        print("degivrage Chauffage oN")
                    
                        if temperatureExt < consigneDegElectric:
                            print("degivrage Electrique")
                        
                            if millis() > (tempoDepartV4VDegEl + tempoV4VDegEl):
                                GPIO.output(relaiV4V, GPIO.LOW)
                                print("relaiV4V oN")
                                if millis() > (tempoDepartCompDegEl + tempoCompDegEl):
                                    GPIO.output(relaiComp, GPIO.LOW)
                                    print("relaiComp oN")
                                    
                            else:
                                tempoDepartCompDegEl = millis()
                        else:
                            tempoDepartV4VDegEl = millis()
                            print("degivrage Naturel")
                else:
                    tempoDepartDegCh = millis()
            else:
                tempoDepartComp = millis()
                GPIO.output(relaiComp, GPIO.HIGH)
                GPIO.output(relaiVentUnitExt, GPIO.HIGH)
                GPIO.output(relaiVitessVentExt, GPIO.HIGH)
                print("tousRelais oFF")    
                
        elif temperatureExt >= consigneExt:
            GPIO.output(relaiAutoEteHiver, GPIO.HIGH)
            print("MODE FROID")
            if temperatureExt > consigneCa:
                print("MODE CANICULE")
            if etatThermostats == 0:
                GPIO.output(relaiVentUnitExt, GPIO.LOW)
                GPIO.output(relaiV4V, GPIO.LOW)
                print("relaiV4V On")
                print("relaiVentUnitExterieur oN")
                
                if millis() > (tempoDepartComp + tempoComp):
                    GPIO.output(relaiComp, GPIO.LOW)
                    print("relaiComp oN")
                
                if temperatureExt > consigneVentExtFr:
                    GPIO.output(relaiVitessVentExt, GPIO.LOW)
                    print("relaiVentGrandeVitesse oN") 
                else:
                    GPIO.output(relaiVitessVentExt, GPIO.HIGH)
                    print("relaiVentPetiteVitesse oN")
            else:
                tempoDepartComp = millis()
                GPIO.output(relaiComp, GPIO.HIGH)
                GPIO.output(relaiV4V, GPIO.HIGH)
                GPIO.output(relaiVentUnitExt, GPIO.HIGH)
                GPIO.output(relaiVitessVentExt, GPIO.HIGH)
                print("tousRelais oFF")
                     
except KeyboardInterrupt: # Appui ctrl+c pour effacer et eteindre tous les relais
    print("Fin Programme !")
    GPIO.cleanup()

c'est qu'un debut !

la maniere de faire la state machine :

import RPi.GPIO as GPIO
from statemachine import StateMachine, State, Transition


GPIO.setmode(GPIO.BCM)
AC_POWER_PIN = 17  # Example GPIO to turn on/off the air conditioner

# Configure the GPIO
GPIO.setup(AC_POWER_PIN, GPIO.OUT)


def gpio_turn_ac_on():
    GPIO.output(AC_POWER_PIN, GPIO.HIGH)
    print("GPIO: Ar-condicionado ligado.")

def gpio_turn_ac_off():
    GPIO.output(AC_POWER_PIN, GPIO.LOW)
    print("GPIO: Ar-condicionado desligado.")


# Classe da Máquina de Estados
class AirConditionerStateMachine(StateMachine):
    off = State('Off', initial=True)
    on = State('On')

    turn_on = off.to(on, on=gpio_turn_ac_on)
    turn_off = on.to(off, on=gpio_turn_ac_off)


if __name__ == "__main__":
    ac = AirConditionerStateMachine()

    try:
        print(f"Current state: {ac.current_state.name}")

        ac.turn_on()
        print(f"Current state: {ac.current_state.name}")

        ac.turn_off()
        print(f"current state: {ac.current_state.name}")
    finally:
        GPIO.cleanup()

En règle général on installe Qt Creator sur son PC et on demande la génération d'un exécutable pour Raspberry, comme Qt est multiplateforme.
Ca fait longtemps que je n'ai pas utilisé Qt Creator, donc je ne pourrais pas te guider plus :frowning:

je me suis amusé à tester sur mon RPi, c'est un peu comme le vélo, ça revient vite.

J'ai installé à la main les packages nécessaires à la compilation manuelle

sudo apt-get install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools
sudo apt-get install qt5-qmake qtbase5-dev
sudo apt-get install cmake

vous pouvez vérifier la version installée

qmake -v

ça me répond

QMake version 3.1
Using Qt version 5.15.8 in /usr/lib/arm-linux-gnueabihf

donc c'est bon.


Ensuite on peut essayer un petit code, on crée un répertoire pour le projet

mkdir qt_menu_example

on va dans ce répertoire

cd qt_menu_example

vous utilisez l'éditeur de texte que vous voulez et créer le fichier main.cpp qui contient le code suivant (on crée l'interface à la main)

#include <QApplication>
#include <QMainWindow>
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QDebug>

void logAction1() {
  qDebug() << "Action 1";
}

void logAction2() {
  qDebug() << "Action 2";
}

void logAction3() {
  qDebug() << "Action 3";
}

int main(int argc, char *argv[]) {
  QApplication app(argc, argv);

  QMainWindow window;

  // la menu bar
  QMenuBar *menuBar = window.menuBar();

  // le menu File avec l'action exit pour quitter le programme
  QMenu *fileMenu = menuBar->addMenu("File");
  QAction *exitAction = new QAction("Exit", &window);
  fileMenu->addAction(exitAction);
  QObject::connect(exitAction, &QAction::triggered, &app, &QApplication::quit);

  // Le menu Edit (vide ici)
  QMenu *editMenu = menuBar->addMenu("Edit");

  // Le menu avec nos actions
  QMenu *actionsMenu = menuBar->addMenu("Actions");
  QAction *action1 = new QAction("Action 1", &window);
  QAction *action2 = new QAction("Action 2", &window);
  QAction *action3 = new QAction("Action 3", &window);

  actionsMenu->addAction(action1);
  actionsMenu->addAction(action2);
  actionsMenu->addAction(action3);

  // on attache les callbacks
  QObject::connect(action1, &QAction::triggered, &logAction1);
  QObject::connect(action2, &QAction::triggered, &logAction2);
  QObject::connect(action3, &QAction::triggered, &logAction3);

  window.setWindowTitle("Exemple Qt Pull-Down Menu");
  window.resize(400, 300);
  window.show();

  return app.exec();
}

ensuite vous créez le fichier cmake qui sert à préparer la compilation CMakeLists.txt et qui contient

cmake_minimum_required(VERSION 3.5)

project(QtMenuExample)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)

find_package(Qt5 COMPONENTS Widgets REQUIRED)

add_executable(QtMenuExample main.cpp)
target_link_libraries(QtMenuExample Qt5::Widgets)

ensuite on crée un répertoire pour la coompilation

mkdir build

On va dans ce répertoire

cd build

On génère les fichiers de configuration nécessaires à la construction d'un projet ( exécuter la commande cmake dans le répertoire parent)

cmake ..

Après la génération des fichiers de construction, on peut passer à la phase de construction en utilisant l'outil de build correspondant à votre projet (par exemple, make, Visual Studio, etc.).

ici on va simplement utiliser make puisqu'on fait tout à la main

make

et une fois la compilation effectuée, si vous faites un ls vous verrez qu'il y a un binaire QtMenuExample prêt pour vous.

tapez ./QtMenuExample pour lancer votre application et vous avez une petite fenêtre qui s'ouvre avec votre menu
image

et si vous choisissez une de vos actions vous verrez dans le terminal que la callback est bien appelé.

Voilà. si maintenant vous voulez que votre application Qt utilise le port série, il faut utiliser QtSerialPort et régler la config pour correspondre à ce que fait votre arduino (8N1 à 115200 bauds par exemple)


PS:

Si vous avez un message de warning dans le terminal

qt.qpa.xcb: QXcbConnection: XCB error: 148 (Unknown), sequence: 191, resource id: 0, major code: 140 (Unknown), minor code: 20

c'est lié à la façon dont QT parle à X11 et on peut supprimer les warnings liés à XCB en faisant

export QT_LOGGING_RULES="qt.qpa.xcb=false"

super merci cela marche a merveille ! me reste plus qu'as etudier ce code pour l'adapter as ma machine a etat c++

c'est nouveau pour moi de coder de ce genre ! au niveau des fichiers Qt il se trouve ou dans la framboise et pour les widgets cela ce passe comment car Qt est pas dans le menu framboise et programmation du raspi ?

En commençant par le début
Qt est un framework (un cadre de travail). C'est un regroupement de bibliothèques destinées à faciliter la création d'un interface homme machine depuis la simple création d'un widget genre pendule sur la page d'accueil windows du Pc jusqu'à l'interface complet d'un programme. Ce framework est multiplateforme purement C++.
QtCreator est l'outils qui permet d'utiliser facilement Qt (ide plus divers outils).
Si le projet est réduit il est possible de travailler directement sur la Pi.
Qt comme QtCreator sont disponibles pour la framboise mais doivent être installés voire compilés.
Si le projet est important il faut faire de la cross compilation. C'est à dire compiler sur le pc, l'exécutable résultant étant directement envoyé sur la Pi. (Dans ce cas Qt sera compilé sur le Pc et envoyé sur la Pi)
Dans les deux cas il existe de nombreux tuto pour faires ces opérations qui ne sont pas vraiment niveau débutant.
Pour ce qui est de coder c'est du C++ et la notice d'utilisation est très complète. Il existe juste une forme spécifique qui ne présente pas de difficultés particulières pour relier les widgets entre eux.

Oui c’est ce que fait mon petit code ci dessus.

Salut ! Si je veux incorporer mon code :

Et étant donné que j’ai deux « main » comment dois-je procéder pour le mélanger avec celui de Qt ?
Merci

Snif :cry: un petit coup de pouce :+1:

un petit coup de pouce pour quelle partie ?

si c'est pour refaire tout le développement en Qt, c'est plus qu'un coup de pouce là... (et je suis en déplacement, juste sur mon iPhone...)