====== Vélos interactifs ======
[[https://github.com/woutgg/ofxGenericDmx/blob/master/ofxGenericDmx_RawDmxExample/src/ofApp.cpp|Gestion du DMX]]
===== Installation du driver FTDI =====
Tous les boîtiers ENTTEC utilisent une puce FTDI pour la communications à travers le port USB. Voici la [[https://www.youtube.com/watch?v=jynlynjOOek|procédure]] pour l'installer sur une RPI4 :
wget https://ftdichip.com/wp-content/uploads/2022/07/libftd2xx-arm-v8-1.4.27.tgz
tar -xvf libftd2xx-arm-v8-1.4.27.tgz
sudo cp release/build/lib* /usr/local/lib
cd /usr/local/lib
ls
sudo ln -s libftd2xx.so.1.4.27 libftd2xx.so
sudo chmod 0755 libftd2xx.so.1.4.27
Brancher le boîtier ENTTEC
sudo rmmod ftdi_sio
sudo rmmod usbserial
cd
cd release/examples
make
cd EEPROM/read
ls
sudo ./read
===== Installation du addon ofxGenericDmx =====
Installation de la librairie ftdi :
sudo apt-get install libftdi-dev
Pour certaines distributions, il pourrait être nécessaire d'autoriser l'utilisateur à accéder à l'interface via son port USB. Des solutions diverses sont détaillées [[https://getdlight.com/wiki/index.php/Interfaces_DMX#Linux|ici]]
wget https://github.com/woutgg/ofxGenericDmx/archive/refs/heads/master.zip
cd openFrameworks/addons/ofxGenericDmx/ofxGenericDmx_EnttecDmxUsbProExample
make
startx ./bin/ofxGenericDmx_EnttecDmxUsbProExample -- -s off
Si vous souhaitez partir d'un projet vierge, il faudra ajouter des instructions pour le linker lors de la compilation :
Dans le fichier config.make du projet :
sudo nano config.make
Vérifiez les lignes suivantes :
PROJECT_LDFLAGS=-Wl,-rpath=./libs
PROJECT_LDFLAGS+=-lftdi
===== Code =====
// g++ -Wall -o compteur compteur.c -l wiringPi
// ./compteur
#include
#include
#include
#define COMPTEUR 26
#define TEMOIN 19
int drapeau = 0;
int main()
{
wiringPiSetupGpio();
pinMode (COMPTEUR, INPUT);
pullUpDnControl(COMPTEUR, PUD_UP);
pinMode (TEMOIN, OUTPUT);
digitalWrite(TEMOIN, LOW);
while(1) {
if ((digitalRead(COMPTEUR) == LOW) && (drapeau == 0)) {
digitalWrite(TEMOIN, HIGH);
delay(20);
drapeau = 1;
}
if (digitalRead(COMPTEUR) == HIGH) {
drapeau = 0;
}
}
return 0;
}
=== ofApp.h ===
#pragma once
#include "ofMain.h"
#include "ofxGenericDmx.h"
#include "ofUtils.h"
#include
#include "Compteur.hpp"
#define DMX_DATA_LENGTH 513
#define TEMOIN1 19
#define TEMOIN2 27
#define ROUE 2.27
class ofApp : public ofBaseApp{
public:
void setup();
void update();
void draw();
//pointer to our Enntec DMX USB Pro object
DmxDevice* dmxInterface_;
//our DMX packet (which holds the channel values + 1st byte for the start code)
unsigned char dmxData_[DMX_DATA_LENGTH];
// Compteurs
Compteur compteur1;
Compteur compteur2;
ofTrueTypeFont myfont;
};
=== ofApp.cpp ===
#include
#include "ofApp.h"
//--------------------------------------------------------------
void ofApp::setup(){
ofSetFrameRate( 44 );
//zero our DMX value array
memset( dmxData_, 0, DMX_DATA_LENGTH );
//open the device
dmxInterface_ = ofxGenericDmx::openFirstDevice();
if ( dmxInterface_ == 0 ) printf( "No Enttec Device Found\n" );
else printf( "isOpen: %i\n", dmxInterface_->isOpen() );
//frames = 0;
printf("ofxGenericDmx addon version: %s.%s\n", ofxGenericDmx::VERSION_MAJOR, ofxGenericDmx::VERSION_MINOR);
// Initialisation valeurs
compteur1.set(TEMOIN1, ROUE, ofGetCurrentTime().getAsMilliseconds());
compteur2.set(TEMOIN2, ROUE, ofGetCurrentTime().getAsMilliseconds());
// Affichage
myfont.load("arial.ttf", 32);
// WiringPi
wiringPiSetupGpio();
}
//--------------------------------------------------------------
void ofApp::update(){
dmxData_[401] = 80;
dmxData_[402] = 160;
dmxData_[403] = 255;
//force first byte to zero (it is not a channel but DMX type info - start code)
dmxData_[0] = 0;
if ( ! dmxInterface_ || ! dmxInterface_->isOpen() ) {
printf( "Not updating, enttec device is not open.\n");
}
else{
//send the data to the dmx interface
dmxInterface_->writeDmx( dmxData_, DMX_DATA_LENGTH );
}
compteur1.mettreAJour();
compteur2.mettreAJour();
}
//--------------------------------------------------------------
void ofApp::draw(){
ofBackground(0x21, 0X80, 0XC3);
compteur1.afficher(0, 0, myfont);
compteur2.afficher(640, 0, myfont);
}
=== Compteur.hpp ===
#include "ofUtils.h"
#include "ofGraphics.h"
#include "ofTrueTypeFont.h"
#include
class Compteur
{
public:
// Constructeur
Compteur();
void set(uint8_t _pinTemoin, float _roue, uint64_t _tempsDepart);
//Accesseurs et mutateurs
//void setX(int x);
//void setY(int y);
//int getX() const;
//int getY() const;
// Autres méthodes
void afficher(int x, int y, ofTrueTypeFont police);
void mettreAJour();
private:
int x, y;
int pinTemoin;
float roue;
int compteur;
uint64_t temps, tempsDepart;
uint16_t distance;
float vitesseIntantanee;
float vitesseMax;
ofTrueTypeFont policeVitesse, policeDistance, policeLabel;
};
=== Compteur.cpp ===
#include "Compteur.hpp"
//--------------------------------------------------------------
Compteur::Compteur()
{
compteur = 0;
temps = 0;
vitesseIntantanee = 0.0;
vitesseMax = 0.0;
policeVitesse.load("AUDIMRG_.TTF", 12);
policeDistance.load("arial.ttf", 50);
policeLabel.load("arial.ttf", 20);
distance = 0;
}
//--------------------------------------------------------------
void Compteur::afficher(int x, int y, ofTrueTypeFont police)
{
ofPushMatrix();
ofTranslate(x, y);
ofSetCircleResolution(100);
ofSetLineWidth(3);
// Dessin du compteur
ofPushMatrix();
ofTranslate(150, 800);
// Aiguille de la vitesse Max
ofSetColor(255, 0, 0);
ofFill();
ofPushMatrix();
ofRotateDeg(60 + vitesseMax * 4);
ofDrawTriangle(-6, 0, 0, 90, 6, 0);
ofPopMatrix();
// Aiguille de la vitesse instantanée
ofSetColor(0, 0, 0);
ofPushMatrix();
ofRotateDeg(60 + vitesseIntantanee * 4);
ofDrawTriangle(-6, 0, 0, 90, 6, 0);
ofPopMatrix();
// Dessin du cadran
ofSetColor(255, 255, 255);
ofFill();
ofDrawCircle(0,0,20);
ofSetColor(0,0,0);
ofNoFill();
ofDrawCircle(0,0,100);
ofDrawCircle(0,0,20);
char nombre[3];
for (int i = 0; i < 61; i += 5) {
ofPushMatrix();
ofRotateDeg(4 * i - 120);
sprintf(nombre, "%i", i);
policeVitesse.drawString(nombre, -policeVitesse.stringWidth(nombre) / 2, -115);
ofDrawLine(0, -100, 0, -110);
ofPopMatrix();
}
ofSetColor(0, 0, 0);
char labelCompteur[255];
sprintf(labelCompteur, "Vitesse max.");
policeLabel.drawString(labelCompteur, -policeLabel.stringWidth(labelCompteur) / 2, 130);
ofPopMatrix();
// Affichage de la distance
ofPushMatrix();
ofTranslate(320, 750);
ofSetColor(0, 0, 0);
ofFill();
ofDrawRectangle(00, 00, 300, 100);
ofSetColor(255, 255, 255);
char ligneDistance[255];
sprintf(ligneDistance, "%i m", distance);
policeDistance.drawString(ligneDistance, 290 - policeDistance.stringWidth(ligneDistance), 75);
ofSetColor(0, 0, 0);
char labelDistance[255];
sprintf(labelDistance, "Distance parcourue");
policeLabel.drawString(labelDistance, 20, 180);
ofPopMatrix();
ofPopMatrix();
}
//--------------------------------------------------------------
void Compteur::mettreAJour() {
if (digitalRead(pinTemoin) == 1) {
digitalWrite(pinTemoin, 0);
compteur++;
uint64_t tempsCourant = ofGetCurrentTime().getAsMilliseconds();
vitesseIntantanee = (3.6 * 1000 * roue) / (tempsCourant - temps);
if (vitesseMax < vitesseIntantanee) {
vitesseMax = vitesseIntantanee;
}
temps = tempsCourant;
}
// Mise à zéro de la vitesse si la roue est arrêtée
if ((ofGetCurrentTime().getAsMilliseconds() - temps) > 6000) {
vitesseIntantanee = 0;
}
distance = (int)(roue * compteur);
}
//--------------------------------------------------------------
void Compteur::set(uint8_t _pinTemoin, float _roue, uint64_t _tempsDepart)
{
pinTemoin = _pinTemoin;
roue = _roue;
tempsDepart = _tempsDepart;
}
===== Démarrage automatique =====
sudo nano /etc/systemd/system/compteur.service
[Unit]
Description=Met en route le compteur des vélos
[Service]
Type=simple
WorkingDirectory=/home/pi/openFrameworks/apps/myApps/velosInteractifs/
ExecStart=/home/pi/openFrameworks/apps/myApps/velosInteractifs/./compteur
Restart=on-failure
RestartSec=1
User=pi
Group=pi
[Install]
WantedBy=multi-user.target
sudo systemctl enable compteur.service
sudo systemctl status compteur.service
Construction d'un autre service pour la course :
sudo nano /etc/rc.local
Ajouter avant la ligne exit 0
startx ./home/pi/openFrameworks/apps/myApps/velosInteractifs/bin/velosInteractifs -- -s off &
Il faut aussi désactiver les sorties audio par l'HDMI. Ajouter ,noaudio à la fin de la ligne dtoverlay=vc4-kms-v3d dans le fichier /boot/firmware/config.txt :
sudo nano /boot/firmware/config.txt
dtoverlay=vc4-kms-v3d,noaudio
{{tag>raspberry_pi sylvain OpenFrameworks}}