Cours:DevoirPOO2 classes
Révision datée du 6 octobre 2023 à 14:30 par Bjacquot (discussion | contributions)
#ifndef ECLAIRAGEDIMMABLE_H
#define ECLAIRAGEDIMMABLE_H
#include <QObject>
class EclairageDimmable : public QObject
{
Q_OBJECT
public:
explicit EclairageDimmable(QObject *parent = nullptr);
bool isOn;
unsigned int puissance; // entre 1 et 4
public slots:
void allumer();
void eteindre();
void augmenterPuissance();
void diminuerPuissance();
protected:
virtual void appliquerConsigne();
signals:
};
#endif // ECLAIRAGEDIMMABLE_H
|
#include "eclairagedimmable.h"
#include <QDebug>
EclairageDimmable::EclairageDimmable(QObject *parent) : QObject(parent)
{
isOn=false;
puissance=1;
}
void EclairageDimmable::allumer()
{
isOn=true;
appliquerConsigne();
}
void EclairageDimmable::eteindre()
{
isOn=false;
appliquerConsigne();
}
void EclairageDimmable::augmenterPuissance()
{
if (puissance<4) puissance++;
appliquerConsigne();
}
void EclairageDimmable::diminuerPuissance()
{
if (puissance>1) puissance--;
appliquerConsigne();
}
void EclairageDimmable::appliquerConsigne()
{
qDebug() << "je suis "<< (isOn==true?"allumée":"éteinte")<< " à la puissance "<<puissance;
}
|
#ifndef BARREGRAPHE_H
#define BARREGRAPHE_H
#include "eclairagedimmable.h"
#include "gpio.h"
using namespace exploringRPi;
class Barregraphe : public EclairageDimmable
{
public:
Barregraphe(int pinLed1, int pinLed2, int pinLed3, int pinLed4);
protected:
GPIO led1;
GPIO led2;
GPIO led3;
GPIO led4;
void appliquerConsigne() override;
};
#endif // BARREGRAPHE_H
|
#include "barregraphe.h"
Barregraphe::Barregraphe(int pinLed1, int pinLed2, int pinLed3, int pinLed4)
:led1(pinLed1),led2(pinLed2),led3(pinLed3),led4(pinLed4)
{
led1.setDirection(OUTPUT);
led2.setDirection(OUTPUT);
led3.setDirection(OUTPUT);
led4.setDirection(OUTPUT);
}
void Barregraphe::appliquerConsigne()
{
EclairageDimmable::appliquerConsigne();
v if (isOn==false)
{
led1.setValue(LOW);
led2.setValue(LOW);
led3.setValue(LOW);
led4.setValue(LOW);
}
else
{
if (puissance==1)
{
led1.setValue(HIGH);
led2.setValue(LOW);
led3.setValue(LOW);
led4.setValue(LOW);
}
else if (puissance==2)
{
led1.setValue(HIGH);
led2.setValue(HIGH);
led3.setValue(LOW);
led4.setValue(LOW);
}
else if (puissance==3)
{
led1.setValue(HIGH);
led2.setValue(HIGH);
led3.setValue(HIGH);
led4.setValue(LOW);
}
else
{
led1.setValue(HIGH);
led2.setValue(HIGH);
led3.setValue(HIGH);
led4.setValue(HIGH);
}
}
}
|
#ifndef LEDDIMMABLE_H
#define LEDDIMMABLE_H
#include "eclairagedimmable.h"
enum numeroPWM{ PWM0, PWM1 };
class ledDimmable : public EclairageDimmable
{
public:
ledDimmable(numeroPWM _numero);
protected:
int numeroGPIO;
int rapportCyclique;
void appliquerConsigne() override;
};
#endif // LEDDIMMABLE_H
|
#include "leddimmable.h"
#include <pigpio.h>
ledDimmable::ledDimmable(numeroPWM _numero)
: EclairageDimmable()
{
gpioInitialise();
if (_numero==PWM0) numeroGPIO=12;
else numeroGPIO=13;
appliquerConsigne();
}
void ledDimmable::appliquerConsigne()
{
EclairageDimmable::appliquerConsigne();
if (isOn==false)
{
gpioHardwarePWM(numeroGPIO,500,0);
}
else
{
gpioHardwarePWM(numeroGPIO,500,puissance*10000);
}
}
|
#ifndef GPIO_H
#define GPIO_H
#include<string>
#include<fstream>
using std::string;
using std::ofstream;
#define GPIO_PATH "/sys/class/gpio/"
namespace exploringRPi {
typedef int (*CallbackType)(int);
enum GPIO_DIRECTION{ INPUT, OUTPUT };
enum GPIO_VALUE{ LOW=0, HIGH=1 };
enum GPIO_EDGE{ NONE, RISING, FALLING, BOTH };
class GPIO {
private:
int number, debounceTime;
string name, path;
public:
GPIO(int number); // constructor exports pin
virtual int getNumber() { return number; }
// General Input and Output Settings
virtual int setDirection(GPIO_DIRECTION);
virtual GPIO_DIRECTION getDirection();
virtual int setValue(GPIO_VALUE);
virtual int toggleOutput();
virtual GPIO_VALUE getValue();
virtual int setActiveLow(bool isLow=true); // low=1, high=0
virtual int setActiveHigh(); // default state
virtual void setDebounceTime(int time) { this->debounceTime = time; }
// Advanced output: faster by keeping the stream open (~20x)
virtual int streamOpen();
virtual int streamWrite(GPIO_VALUE);
virtual int streamClose();
virtual int toggleOutput(int time); // thread invert output every X ms
virtual int toggleOutput(int numberOfTimes, int time);
virtual void changeToggleTime(int time) { this->togglePeriod = time; }
virtual void toggleCancel() { this->threadRunning = false; }
// Advanced input: detect input edges -- threaded and non-threaded
virtual int setEdgeType(GPIO_EDGE);
virtual GPIO_EDGE getEdgeType();
virtual int waitForEdge(); // waits until button is pressed
virtual int waitForEdge(CallbackType callback); // threaded callback
virtual void waitForEdgeCancel() { this->threadRunning = false; }
virtual ~GPIO(); // destructor unexports the pin
private:
int write(string path, string filename, string value);
int write(string path, string filename, int value);
string read(string path, string filename);
int exportGPIO();
int unexportGPIO();
ofstream stream;
pthread_t thread;
CallbackType callbackFunction;
bool threadRunning;
int togglePeriod; // default 100ms
int toggleNumber; // default -1 (infinite)
friend void* threadedPoll(void *value);
friend void* threadedToggle(void *value);
};
void* threadedPoll(void *value); // callback functions for threads
void* threadedToggle(void *value); // callback functions for threads
} /* namespace exploringRPi */
#endif // GPIO_H
|
#include "gpio.h"
#include<iostream>
#include<fstream>
#include<string>
#include<sstream>
#include<cstdlib>
#include<cstdio>
#include<fcntl.h>
#include<unistd.h>
#include<sys/epoll.h>
#include<pthread.h>
using namespace std;
namespace exploringRPi {
/**
*
* @param number The GPIO number for the RPi
*/
GPIO::GPIO(int number) {
this->number = number;
this->debounceTime = 0;
this->togglePeriod=100;
this->toggleNumber=-1; //infinite number
this->callbackFunction = NULL;
this->threadRunning = false;
ostringstream s;
s << "gpio" << number;
this->name = string(s.str());
this->path = GPIO_PATH + this->name + "/";
this->exportGPIO();
// need to give Linux time to set up the sysfs structure
usleep(250000); // 250ms delay
}
int GPIO::write(string path, string filename, string value){
ofstream fs;
fs.open((path + filename).c_str());
if (!fs.is_open()){
perror("GPIO: write failed to open file ");
return -1;
}
fs << value;
fs.close();
return 0;
}
string GPIO::read(string path, string filename){
ifstream fs;
fs.open((path + filename).c_str());
if (!fs.is_open()){
perror("GPIO: read failed to open file ");
}
string input;
getline(fs,input);
fs.close();
return input;
}
int GPIO::write(string path, string filename, int value){
stringstream s;
s << value;
return this->write(path,filename,s.str());
}
int GPIO::exportGPIO(){
return this->write(GPIO_PATH, "export", this->number);
}
int GPIO::unexportGPIO(){
return this->write(GPIO_PATH, "unexport", this->number);
}
int GPIO::setDirection(GPIO_DIRECTION dir){
switch(dir){
case INPUT: return this->write(this->path, "direction", "in");
break;
case OUTPUT:return this->write(this->path, "direction", "out");
break;
}
return -1;
}
int GPIO::setValue(GPIO_VALUE value){
switch(value){
case HIGH: return this->write(this->path, "value", "1");
break;
case LOW: return this->write(this->path, "value", "0");
break;
}
return -1;
}
int GPIO::setEdgeType(GPIO_EDGE value){
switch(value){
case NONE: return this->write(this->path, "edge", "none");
break;
case RISING: return this->write(this->path, "edge", "rising");
break;
case FALLING: return this->write(this->path, "edge", "falling");
break;
case BOTH: return this->write(this->path, "edge", "both");
break;
}
return -1;
}
int GPIO::setActiveLow(bool isLow){
if(isLow) return this->write(this->path, "active_low", "1");
else return this->write(this->path, "active_low", "0");
}
int GPIO::setActiveHigh(){
return this->setActiveLow(false);
}
GPIO_VALUE GPIO::getValue(){
string input = this->read(this->path, "value");
if (input == "0") return LOW;
else return HIGH;
}
GPIO_DIRECTION GPIO::getDirection(){
string input = this->read(this->path, "direction");
if (input == "in") return INPUT;
else return OUTPUT;
}
GPIO_EDGE GPIO::getEdgeType(){
string input = this->read(this->path, "edge");
if (input == "rising") return RISING;
else if (input == "falling") return FALLING;
else if (input == "both") return BOTH;
else return NONE;
}
int GPIO::streamOpen(){
stream.open((path + "value").c_str());
return 0;
}
int GPIO::streamWrite(GPIO_VALUE value){
stream << value << std::flush;
return 0;
}
int GPIO::streamClose(){
stream.close();
return 0;
}
int GPIO::toggleOutput(){
this->setDirection(OUTPUT);
if ((bool) this->getValue()) this->setValue(LOW);
else this->setValue(HIGH);
return 0;
}
int GPIO::toggleOutput(int time){ return this->toggleOutput(-1, time); }
int GPIO::toggleOutput(int numberOfTimes, int time){
this->setDirection(OUTPUT);
this->toggleNumber = numberOfTimes;
this->togglePeriod = time;
this->threadRunning = true;
if(pthread_create(&this->thread, NULL, &threadedToggle, static_cast<void*>(this))){
perror("GPIO: Failed to create the toggle thread");
this->threadRunning = false;
return -1;
}
return 0;
}
// This thread function is a friend function of the class
void* threadedToggle(void *value){
GPIO *gpio = static_cast<GPIO*>(value);
bool isHigh = (bool) gpio->getValue(); //find current value
while(gpio->threadRunning){
if (isHigh) gpio->setValue(HIGH);
else gpio->setValue(LOW);
usleep(gpio->togglePeriod * 500);
isHigh=!isHigh;
if(gpio->toggleNumber>0) gpio->toggleNumber--;
if(gpio->toggleNumber==0) gpio->threadRunning=false;
}
return 0;
}
// Blocking Poll - based on the epoll socket code in the epoll man page
int GPIO::waitForEdge(){
this->setDirection(INPUT); // must be an input pin to poll its value
int fd, i, epollfd, count=0;
struct epoll_event ev;
epollfd = epoll_create(1);
if (epollfd == -1) {
perror("GPIO: Failed to create epollfd");
return -1;
}
if ((fd = open((this->path + "value").c_str(), O_RDONLY | O_NONBLOCK)) == -1) {
perror("GPIO: Failed to open file");
return -1;
}
//ev.events = read operation | edge triggered | urgent data
ev.events = EPOLLIN | EPOLLET | EPOLLPRI;
ev.data.fd = fd; // attach the file file descriptor
//Register the file descriptor on the epoll instance, see: man epoll_ctl
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
perror("GPIO: Failed to add control interface");
return -1;
}
while(count<=1){ // ignore the first trigger
i = epoll_wait(epollfd, &ev, 1, -1);
if (i==-1){
perror("GPIO: Poll Wait fail");
count=5; // terminate loop
}
else {
count++; // count the triggers up
}
}
close(fd);
if (count==5) return -1;
return 0;
}
// This thread function is a friend function of the class
void* threadedPoll(void *value){
GPIO *gpio = static_cast<GPIO*>(value);
while(gpio->threadRunning){
gpio->callbackFunction(gpio->waitForEdge());
usleep(gpio->debounceTime * 1000);
}
return 0;
}
int GPIO::waitForEdge(CallbackType callback){
this->threadRunning = true;
this->callbackFunction = callback;
// create the thread, pass the reference, address of the function and data
if(pthread_create(&this->thread, NULL, &threadedPoll, static_cast<void*>(this))){
perror("GPIO: Failed to create the poll thread");
this->threadRunning = false;
return -1;
}
return 0;
}
GPIO::~GPIO() {
this->unexportGPIO();
}
} /* namespace exploringRPi */
|
#ifndef BOUTON_H
#define BOUTON_H
#include <QObject>
#include <QFileSystemWatcher>
#include "gpio.h"
using namespace exploringRPi;
class Bouton : public QObject
{
Q_OBJECT
public:
explicit Bouton(int nbBroche,GPIO_EDGE typeFront);
bool getValue();
private:
GPIO broche;
QFileSystemWatcher fileScanner;
signals:
void change();
public slots:
void evenementBroche();
};
#endif // BOUTON_H
|
#include "bouton.h"
Bouton::Bouton(int nbBroche, GPIO_EDGE typeFront) : QObject(), broche(nbBroche)
{
broche.setDirection(INPUT);
broche.setEdgeType(typeFront);
fileScanner.addPath(QString("/sys/class/gpio/gpio%1/value").arg(nbBroche));
connect(&fileScanner,SIGNAL(fileChanged(QString)),this,SLOT(evenementBroche()));
}
bool Bouton::getValue()
{
return broche.getValue();
}
void Bouton::evenementBroche()
{
emit change();
}
|