Go Down

Topic: Eclairage à led de vélo (7.5W à l’avant et 3 W à l’arrière) avec Arduino (Read 5753 times) previous topic - next topic

Fquihifaissal

Script intégral en C sur l'IDE Arduino :

Code: [Select]

#include // include la bibliothèque Wire.h

#define MPU_ADDRESS 0x68  // I2C address of the MPU-6050

#define X  0        // X axis
#define Y  1        // Y axis
#define Z  2        // Z axis
float acc_total_vector;

int acc_raw[3] = {0,0,0};

/**
* Configure la plage de fonctionnement de l'accéléromètre :
*  - accéléromètre: +/-2g

*
* @return void
*/
void setup() {
analogReference(EXTERNAL);
Serial.begin(19200);
Wire.begin();  
// Configure power management
Wire.beginTransmission(MPU_ADDRESS); // Start communication with MPU
Wire.write(0x6B);                    // Request the PWR_MGMT_1 register
Wire.write(0x00);                    // Apply the desired configuration to the register
Wire.endTransmission();              // End the transmission

// Configure the acceleromter's sensitivity
Wire.beginTransmission(MPU_ADDRESS); // Start communication with MPU
Wire.write(0x1C);                    // Request the ACCEL_CONFIG register
Wire.write(0x00);                    // Apply the desired configuration to the register : ±8g
Wire.endTransmission();              // End the transmission

// Configure low pass filter
Wire.beginTransmission(MPU_ADDRESS); // Start communication with MPU
Wire.write(0x1A);                    // Request the CONFIG register
Wire.write(0x00);                    // Set Digital Low Pass Filter about ~43Hz
Wire.endTransmission();              // End the transmission

Wire.endTransmission(true);        //end the transmission
}

void loop() {
Wire.beginTransmission(MPU_ADDRESS);// Start communicating with the MPU-6050
Wire.write(0x3B);                   // Send the requested starting register
Wire.endTransmission(false);             // End the transmission
Wire.requestFrom(MPU_ADDRESS,6);   // Request 14 bytes from the MPU-6050

// Wait until all the bytes are received
while(Wire.available() < 6);

acc_raw[X]  = (Wire.read() << 8 | Wire.read())/ 16384.0; // Add the low and high byte to the acc_raw[X] variable
acc_raw[Y]  = (Wire.read() << 8 | Wire.read())/ 16384.0; // Add the low and high byte to the acc_raw[Y] variable
acc_raw[Z]  = (Wire.read() << 8 | Wire.read())/ 16384.0; // Add the low and high byte to the acc_raw[Z] variable

acc_total_vector = sqrt(pow(acc_raw[X], 2) + pow(acc_raw[Y], 2) + pow(acc_raw[Z], 2));

Serial.print(acc_raw[X]);
Serial.print("/");
Serial.print(acc_raw[Y]);
Serial.print("/");
Serial.print(acc_raw[Z]);
Serial.print("/");
Serial.println(acc_total_vector);
delay(10);

}



Résultats moniteur Arduino:

1g suivant +X :




1g suivant -Y :





1g suivant +Z:



Conclusion:

Quant aux différents filtres, j'ai utilisé le filtre passe-bas numérique intégré dans le MPU6050 avec une bande passante d'environ 45Hz, quand j'essaie de bouger le capteur pour voir les réponses suivant plusieurs axes, les réponses sont quasi-stables dans le moniteur série d'IDE Arduino, le fait d'implanter des équations récurrentes de différents types de filtre (pass_bas pass_haut passe bande ...), c'est facile, mais je n'y vois pas l'intérêt, car tous les résultats qu'on trouve sur le moniteur série Arduino, sont soit 1g suivant X soit 1g suivant Y soit 1g suivant Z.


Allumer un feu stop après un freinage ou un arrêt normal du vélo, est tout à fait possible avec un accéléromètre détectant la décélération, toutefois cela nécessite une étude comparatives de plusieurs accéléromètres analogiques et numériques, sans oublier les autres solutions technologiques pour répondre à cette problématique, comme par exemple un compteur de vitesse (Tr/min)

iutgeiisoissons

Pourquoi ne pas avoir utilisé une bibliothèque dédiée pour le MPU 6050 ??????
Mais en général, avec ces bibliothèques, la configuration est difficile….
donc c'est vraiment bien, ce que vous avez fait.

Est-ce que vous avez fait des essais du capteur MPU6050 dans une voiture et vérifier les dynamiques de l'accélération avec une application smartphone ???????

si tu mets
Code: [Select]

[url=https://servimg.com/view/19537397/16][img]https://i.servimg.com/u/f38/19/53/73/97/z10.png[/img][/url]


on verra l'image


iutgeiisoissons

Bref, les compteurs de vélos (odomètre capteur magnet KY03) qui mesurent la vitesse grâce à un compte tour de la roue pourrait aussi mesurer la décélération et activé un STOPT arrière.
Mais quelle pourrait être la précision de cette méthode ? Faut-il mettre plusieurs aimants sur la roue ? Faut-il filtrer la valeur de la  décélération ?

De plus, il existe des éclairages arrière  vélos qui donnent la direction (clignotant droit et gauche) sans fil, mais sur un vélo, il n'y qu'à tendre la main à droite ou à gauche donc c'est inutile.
Mais pour un velomobile (vélo caréné), cela est intéressant
http://velorizontal.1fr1.net/t17956-velomobile-electric-leiba-x-stream-iut-aisne

Voici un bel article avec 2 arduinos et une communication bluetooth
https://create.arduino.cc/projecthub/simonwongwong/bluetooth-enabled-bicycle-turn-signal-2f4f5d
Mais les matrices de leds ne permettent pas d'être vu de jour (pas assez de lumen)

L'article suivant utilise une télécommande 4 boutons
https://github.com/sdebby/Arduino_bike_blink
Donc une télécommande et un récepteur, voici en voici l'électronique
http://www.wzmicro.com/rf.htm
Cela ne coute rien, mais il faudra mettre le compteur de vélo sur l'Arduino arrière pour avoir un feu stop


Donc, un compteur vélo avec Bluetooth va être réalisé et commander l'éclairage arrière comme on peut l'observer sur la figure suivante.
Le compteur avec son afficher a permis  de vérifier  le bon fonctionnement de la programmation et s'il fallait filtrer la mesure de la décélération
Il faudra prendre des Arduino Pro et pas nano pour leurs faibles consommations sur la batterie.
Mais pour vérifier la programmation le nano a été utilisé.

L'indication droite et gauche est évidemment clignotante ainsi que le stop et lors de la décélération.
Mais on aurait pu mettre une 4éme led, pour un feu stop mais cela n'a pas été fait.
Le bouton poussoir stop est inutile, puisque la décélération est mesurée et active automatiquement l'éclairage arrière.

Le compteur vélo a 4 aimants sur la roue pour augmenter la précision des mesures de la vitesse dans les basses vitesses.
Avec l'utilisation de la mesure en milliseonde à chaque quart de roue
L'erreur de la vitesse est déterminée par l'équation suivante avec 4 aimants
DeltaVitesse=(2010*3.6/4)/(Timer+1)( Timer)         pour Timer=25ms=>2.78km/h  pour vitesse 72km/h    
La précision correspond à l'équation suivante
Précision=1/(Timer+1)       donc à 72km/h précisons de 3.8%  et à 18km/h 1%

Etant donné que l'accélération est déterminée aussi pour chaque quart de roue tournée, l'erreur de l'accélération correspondra aux équations suivantes
DeltaAccelera=(277)/(Timer+1)( Timer)        pour Timer=25ms=>0.42m/s^2   pour vitesse 72km/h  
DeltaAccelera=(277)/(Timer+1)( Timer)        pour Timer=100ms=>0.027m/s^2   pour vitesse 18km/h  

Pour ne pas avoir de décélération intempestive, le calcul de la décélération se fera seulement si l'erreur de mesure de la vitesse est plus faible que sa variation.
Etant donné que la propriété de la routine d'interruption extérieure n'est pas si facile à imposer par rapport à routine d'interruption timer sur Atmel, il n'y aura pas d'interruption timer.

Voici le code
Code: [Select]

#include <LiquidCrystal.h>
#include <SoftwareSerial.h>
//#include <TimerOne.h>


#define led13     13       //    
#define BPLeft    12       //
#define Night     11       //
#define BPRight   10       //
#define BPStop     9       //
 

LiquidCrystal lcd(8, 3, 4, 5, 6, 7);   // LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
// Configuration des variables

 float Time=0;
 float  TO=0;
 float  temps=0;
 float  Time1=0;              
            float kph=0;
            float kph1=0;
            float distance=0;

            float deceler=0;
            float erreur=0;
            bool stop=0;
            bool flagnight=0;
            bool attendre=0;
            
            byte   buffer1=0;
            String readString;

// the setup function runs once when you press reset or power the board
void setup() {
 
pinMode(led13, OUTPUT);   //led carte arduino
pinMode (BPLeft, INPUT_PULLUP);
pinMode (Night, INPUT_PULLUP);
pinMode (BPRight, INPUT_PULLUP);
pinMode (BPStop, INPUT_PULLUP);

 lcd.begin(16, 2);                   //modifier pour un afficheur 20x4
 Serial.begin(9600);     //57600
 //SoftwareSerial mySerial(0, 1);   // RX, TX mais il n'y a pas trop le choix sur la nano


//  Timer1.initialize(10000);           // initialize timer1, and set a 0,1 second period =>  100 000  pour 0.01s  10 000
//  Timer1.attachInterrupt(Routinetimer1);   // attaches le sous programme  Routinetimer1 as a timer overflow interrupt

  TCCR2B = (TCCR2B & 0b11111000) | 0x01;         //pin 3  32khz    

attachInterrupt(0, interrup2, RISING);   // il vaut mieux utiliser  KY003 tout ou rien   RISING, FALLING, CHANGE
TO = millis();                                  
}//fin setup

void interrup2() // la fonction appelée par l'interruption externe n°0
{//digitalWrite(led13,HIGH);
Time=(millis()-TO);  //mesure du temps     //micros()    millis()
TO=millis();

distance=(distance+(2.01/4));     //perimetre/4 aimants
kph1=kph;                            
if (Time>=500) {kph=0;deceler=0; }
          else {kph=((2.010*1000*3.6)/(Time*4));   //kph=perimetre/time  avec 4 aimants   //
                erreur=(kph/(Time-2));                                                                            
                if ( (kph<(kph1-erreur)))  {deceler=(((kph-kph1)*277)/Time);} else {deceler=0;}  
                }              // en m/s^2  277=1000milliseconde/3.6      
if (deceler<-40) {deceler=-40; }
if (deceler>40) {deceler=40; }
//  digitalWrite(led13,LOW);   de la routine interr exterieur durée 0.7ms
}



// Interruptions  tous les 100ms fait par le timer1***********************************

//void Routinetimer1()  {
//  temps++;  
//}//fin routineinterruption


///////////////////////////////////////////// Boucle correspondant à la fonction main
void loop() {  
Time1=(millis()-TO);
if (Time1>=500) {kph=0;deceler=0;}   //remise à 0, lorsqu'il n'y a plus d'interruption
attendre=0;

  lcd.setCursor(0,0);  // (X,Y)                              
  lcd.print(kph,1);
  lcd.print("kph    ");
  lcd.setCursor(9,0);  // (X,Y)                                
  lcd.print(distance/1000,2);
  lcd.print("km  ");
 
    lcd.setCursor(0,1);  // (X,Y)                            
    lcd.print(deceler,1);
    lcd.print("m/s");
    lcd.print((char)94);
    lcd.print("2 ");

    if  (deceler<(-2)) {stop=1;lcd.setCursor(10,1);lcd.print("STOP");Serial.print(2); }  
    if  (deceler>0)    {stop=0,lcd.setCursor(10,1);lcd.print("    "); }
    if  (digitalRead(BPStop)==0) {stop=1;lcd.setCursor(10,1);lcd.print("STOP");Serial.print(2); }  
    if (digitalRead(BPLeft)==0)     {Serial.print(1); }
    if (digitalRead(BPRight)==0 )   {Serial.print(3); }
    if (digitalRead(BPRight)==0 && digitalRead(BPStop)==0   )    {distance=0;}   //remise à zero du compteur
    if  (digitalRead(BPStop)==0) {stop=1;lcd.setCursor(10,1);lcd.print("STOP");Serial.print(2); }
 if ((digitalRead(Night)==0) && (flagnight==0) && attendre==0 )      {flagnight=1;Serial.print(0);attendre=1; }   //eteindre la lumiere
 if ((digitalRead(Night)==0) && (flagnight==1) && attendre==0)      {flagnight=0;Serial.print(4);attendre=1;}   //allume lumiere
 if (flagnight==1)  {lcd.setCursor(15,0);lcd.print("N"); }      //lumiere
 if (flagnight==0)  {lcd.setCursor(15,0);lcd.print(" "); }
 
/*Serial.print(Time,0);
Serial.print(";");
Serial.print(kph,1);
Serial.print(";");
Serial.print(deceler,1);
Serial.println(";");  */
delay(100);            
  
} // fin loop



iutgeiisoissons

la suite du post precedent

Voici le résultat de la mesure de la vitesse et la deceleration avec excel, du programme precedent


Pas envie de mettre 2 fils d'alimentation et 1 fil de communication entre le compteur et l'éclairage arrière entre le compteur et la partie éclairage arrière. Donc une commination série Bluetooth HC06 a été choisie.
Il sera possible d'indiquer sur le compteur rétroéclairer, l'état de la batterie arrière.

Le code de la récepteur et qui gère le clignotement
Code: [Select]

#include <SoftwareSerial.h>
#include <TimerOne.h>
//#include <math.h>

 
#define led12     12       //
#define led11     11       //
#define led10     10       //

            byte  temps12=0;
            byte  temps11=0;
            byte  temps10=0;
            byte c=0;
            bool flag12=0;
            bool flag11=0;
            bool flag10=0;
            bool flagnight=0;
            


void setup() {
pinMode(led12, OUTPUT);   //lumiere gauche, direction
pinMode(led11, OUTPUT);   //lumiere centrale, stop et eclairage
pinMode(led10, OUTPUT);   //lumiere gauche, direction


Serial.begin(9600);    
 //SoftwareSerial Serial(0, 1);   // RX, TX mais il n'y a pas trop le choix sur la nano

 Timer1.initialize(400000);           // initialize timer1, and set a 0,1 second period =>  100 000  pour 0.01s  10 000
 Timer1.attachInterrupt(Routinetimer1);   // attaches le sous programme  Routinetimer1 as a timer overflow interrupt
                            
}//fin setup




// Interruptions  tous les 400ms fait par le timer1***********************************
void Routinetimer1()  {
  temps12++;
  temps11++;
  temps10++;
if (temps12<15 && flag12==1)  {if ( digitalRead(12)== 1 ) {digitalWrite(12,LOW);}  else {digitalWrite(12,HIGH);}}  //clignotement pendant 15=6s/0.4s  gauche
if (temps12>15 && flag12==1)  {flag12=0;digitalWrite(led12,LOW);}

if (temps10<15 && flag10==1)  {if ( digitalRead(10)== 1 ) {digitalWrite(10,LOW);}  else {digitalWrite(10,HIGH);}}  //clignotement pendant 15=6s/0.4s droite
if (temps10>15 && flag10==1)  {flag10=0;digitalWrite(led10,LOW);}

if (temps11<15 && flag11==1)  {if ( digitalRead(11)== 1 ) {digitalWrite(11,LOW);}  else {digitalWrite(11,HIGH);}}  //clignotement pendant 15=6s/0.4s stop
if (temps11>15 && flag11==1)  {flag11=0;
                               if (flagnight==1) {digitalWrite(11,HIGH);}
                               if (flagnight==0) {digitalWrite(11,LOW);}
                              }
}//fin routineinterruption



///////////////////////////////////////////// Boucle correspondant à la fonction main
void loop() {  

while (Serial.available()) { c=Serial.read();//Serial.print(c,DEC);  
if (c==48)        {digitalWrite(led11,LOW);flagnight=0;}       //0 arret en continu
if (c==49)        {digitalWrite(led12,HIGH);digitalWrite(led10,LOW);flag12=1;flag10=0;temps12=0;}        //1  direction gauche +5s
if (c==50)        {digitalWrite(led11,HIGH);flag11=1;temps11=0;}                                         //2  feu stop
if (c==51)        {digitalWrite(led10,HIGH);digitalWrite(led12,LOW);flag10=1;flag12=0;temps10=0;}        //3  direction droite +5s
if (c==52)        {digitalWrite(led11,HIGH);flagnight=1;}                                                //4  allumage en continu
                            }

} // fin loop






A la place de faire de nombreux essais, sur le vélo pour vérifier le programme de la mesure vitesse et de la décélération, un Arduino génère les impulsions de l'aimant.




Voici le code du générateur de front qui fait varier la vitesse pour verifier le bon fonctionnement du programme
Code: [Select]

#include <LiquidCrystal.h>
#include <SoftwareSerial.h>
#include <TimerOne.h>
#include <math.h>


 
#define led12     12       //



LiquidCrystal lcd(9, 3, 4, 5, 6, 7);   // LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
// Configuration des variables



unsigned    int   temps=0;
unsigned    int tempsmono=0;
            float  tempsperiode=0;
            float   tempsdecelerat;
            float  tempsdec=0;
            float  a=0;
            float  b=0;
            float deceleration;
            bool flag;
            

// the setup function runs once when you press reset or power the board
void setup() {
 

pinMode(led12, OUTPUT);   //

 Serial.begin(9600);     //57600

  Timer1.initialize(1000);           // initialize timer1, and set a 0,1 second period =>  100 000  pour 0.01s  10 000
  Timer1.attachInterrupt(Routinetimer1);   // attaches le sous programme  Routinetimer1 as a timer overflow interrupt

  TCCR2B = (TCCR2B & 0b11111000) | 0x01;         //pin 3  32khz    


  a=0.144;                 //((400-40)/tdecel);   400  correspond à 4.5km/h , 40 à 45km/h utilsation 4 aimants    (4.5-45)/(2.5s*3.6)=4.5m/s^2
  b=40;                    //coefficient de le deceleration
    Serial.print(a,3);
    Serial.print(";");
    Serial.println(b,3) ;                              
}//fin setup



// Interruptions  tous les 1ms fait par le timer1***********************************
void Routinetimer1()  {
temps++;
tempsperiode++;
tempsmono++;

//*
if (tempsperiode<50)  {deceleration=2000;}     //creation profil acceleration et decele
if (tempsperiode>=50 &&  tempsperiode<2500)  {deceleration=-0.2*(tempsperiode-50)+400;        
                                              if (deceleration<40) {deceleration=40;}
                                              }    //acceleration
if (tempsperiode>=2500 &&  tempsperiode<3500)  {deceleration=40;}                                              
if (tempsperiode>=3500 &&  tempsperiode<6000)  {deceleration=a*(tempsperiode-3500)+b;}      //deceleration  

if (tempsperiode>=6000 && tempsperiode<7000 )  {deceleration=1000;}
if (tempsperiode>=7000)  {tempsperiode=0;}
//*/
              
//Serial.print(tempsperiode,0) ;
//Serial.print(";");
//Serial.println(deceleration,0) ;    
//deceleration=40;           //4 aimants,  400=>4.5km/h   40=>45km/h    valeur fixe de vitesse
  
if (temps>=deceleration  && flag==0) {digitalWrite(led12,HIGH);tempsmono=0;flag=1;temps=0; }  //monostable=10ms
if (flag==1 && tempsmono>=4)        {digitalWrite(led12,LOW);flag=0;}




}//fin routineinterruption


///////////////////////////////////////////// Boucle correspondant à la fonction main
void loop() {  
 


} // fin loop


Avec la batterie, du compteur, on pourrait faire aussi un éclairage blanc vers l'avant
Mais, cela sera une autre histoire….



iutgeiisoissons

#34
Sep 17, 2020, 08:08 pm Last Edit: Sep 17, 2020, 08:09 pm by iutgeiisoissons
Voici le programme du capteur accéléromètre MPU6050 mais avec un ESP32+OLED et un filtre passe bas du troisième ordre, pour un éclairage automatique arrière de vélo.

La méthode de test et des explications sont téléchargeables sur ce lien
https://www.fichier-pdf.fr/2020/09/17/esp32-mpu6050-arduino-filtre-passe-bas-1hz/

Code: [Select]

#include "Arduino.h"
#include "heltec.h"
#include "Wire.h"
//#include "BluetoothSerial.h"    //https://randomnerdtutorials.com/esp32-bluetooth-classic-arduino-ide/
                                  //


#define MPU_ADDRESS 0x68  // I2C address of the MPU-6050
int Te=100000  ; //periode d'echantillonnage micro seconde  =>0.1s

int16_t accX=0;
int16_t accY=0;
int16_t accZ=0;

 float accX_0=0;
 float accY_0=0;
 float accZ_0=0;

float accY_1 = 0;  // recurence n-1
float accY_2 = 0;  // recurence n-2
float accY_3 = 0;  // recurence n-3
float YaFout=0;
float YaF =0;
float YaF1 =0;
float YaF2 =0;
float YaF3 =0;

float  Y[127];     //12.7s



byte var=1;
byte i=0;   //incrementation for te curve
bool flagmesure=1;
bool flagenvoie=1;
bool flagstop=0;
bool flagfrein=0;
bool flagrear=0;
bool flaglight=0;
int16_t temps=0;
int16_t tensionbatt;




hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
uint32_t cp0_regs[18];

//******************************************************************
void IRAM_ATTR onTimer() {      //IRAM et DRAM   routine d'interruption toutes les TE 0.1s
//digitalWrite(33,HIGH);
 portENTER_CRITICAL_ISR(&timerMux);

xthal_set_cpenable(1);  xthal_save_cp0(cp0_regs);   // // Save FPU registers
if ( digitalRead(25)== 1 ) {digitalWrite(25,LOW);}  else {digitalWrite(25,HIGH);}    //led sur la carte heltec

flagmesure=1;
    
  xthal_restore_cp0(cp0_regs);  xthal_set_cpenable(0);  // and turn it back off
  portEXIT_CRITICAL_ISR(&timerMux);
  
//  digitalWrite(33,LOW);
}//fin routine interrupt







//*********************************
void setup(){
pinMode(0, INPUT_PULLUP);   //bouton prg carte heltec ESP32
pinMode(25, OUTPUT);   //led
//pinMode(13, OUTPUT);   //mesure temps instruction oscilloscope
pinMode(21, OUTPUT);   // lecture batterie lithium
 
 Serial.begin(115200);

 Wire.begin(4,15,400000);       //Wire.begin(I2C_SDA, I2C_SCL);       0x3C oled   et MPU6050  broche 4 et 15

  Heltec.begin(true /*DisplayEnable Enable*/, false /*LoRa Disable*/, true /*Serial Enable*/);
  Heltec.display->flipScreenVertically();
  Heltec.display->setFont(ArialMT_Plain_24);           //10, 16, 24
  Heltec.display->setTextAlignment(TEXT_ALIGN_LEFT);

 
Wire.beginTransmission(MPU_ADDRESS);
 Wire.write(0x6B);  // PWR_MGMT_1 register
 Wire.write(0x00);     // set to zero (wakes up the MPU-6050)
 Wire.endTransmission();              // End the transmission

// Configure the acceleromter's sensitivity
Wire.beginTransmission(MPU_ADDRESS); // Start communication with MPU
Wire.write(0x1C);                    // Request the ACCEL_CONFIG register
Wire.write(0x00);                     // Apply the desired configuration to the register : ±2g=±20ms^-2     1g=16384
//Wire.write(0b00010000);             // Apply the desired configuration to the register : ±8g=±20ms^-2  1g=4096
Wire.endTransmission();              // End the transmission

// Configure low pass filter
Wire.beginTransmission(MPU_ADDRESS); // Start communication with MPU
Wire.write(0x1A);                    // Request the CONFIG register
//Wire.write(0x00);                    // Set Digital Low Pass Filter about ~260Hz   DLPF_CFG
Wire.write(0x06);                    // Set Digital Low Pass Filter about ~5Hz   DLPF_CFG
Wire.endTransmission();              // End the transmission

Wire.endTransmission(true);        //end the transmission

  timer = timerBegin(0, 80, true);
  timerAttachInterrupt(timer, &onTimer, true);
  timerAlarmWrite(timer, Te, true);      
  timerAlarmEnable(timer);

}


//************************
void loop(){

//if ( digitalRead(13)== 1 ) {digitalWrite(13,LOW);}  else {digitalWrite(13,HIGH);}     //teste du temps de la boucle
if (digitalRead(0)==0)   {var++;delay(1500); }    //utilisation du bouton prg de la carte ESP32 heltec
if (var>=5)   {var=1;flagenvoie=1; }              //4 valeurs pour afficher les valeurs numeriques ou courbes ou pause ou envoie des données
if ( touchRead(13)<30 )   {flagfrein=1;} else {flagfrein=0;}    //touchRead(13)



if ((flagmesure==1 && (var==1 | var==2)))   {    //mesure tous les 0.1ms
  temps++;
Wire.beginTransmission(MPU_ADDRESS);
Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);           // End the transmission
Wire.requestFrom(MPU_ADDRESS,6);   // Request 16 bytes from the MPU-6050

// Wait until all the bytes are received
while(Wire.available() < 6);

accX  = (Wire.read() << 8 | Wire.read()); // reading registers: 0x3B et 0x3C     MSB et LSB
accY  = (Wire.read() << 8 | Wire.read()); // reading registers: 0x3D
accZ  = (Wire.read() << 8 | Wire.read()); // reading registers: 0x3F

accX_0=accX/1638.0;   //en m/s^2  pour initilisation à 2*gravitation
accY_0=accY/1638.0;
accZ_0=accZ/1638.0;

accY_3=accY_2;
accY_2=accY_1;  //recurence n-2
accY_1=accY_0;  //recurence n-1

YaF3=YaF2;
YaF2=YaF1;
YaF1=YaF;         //filtre numerique passe bas 3éme orde Frequence de coupure=1Hz
YaF=accY_0+3*accY_1+3*accY_2+3*accY_3+0.278059*YaF3-1.18289*YaF2+1.76*YaF1;   //filtre numerique passe bas  Frequence de coupure=1Hz
YaFout=YaF/66;        //55 en theorie

i++;
if (i>=127) {i=0;}
//Y[i]=accY_0;    //sans filtre
Y[i]=YaFout;      //avec filtre    

if (YaFout>=2)  {flagstop=1;temps=0;}     //declenchement lumiere peandant 5seconde clignotant
if (YaFout<=-1) {flagstop=0;flagrear=0;temps=0;flaglight=0;}   //si acceleration arret lumiere arriere
if (flagstop==1 && temps<=50) {flagrear=1;}
if (temps>50) {flagrear=0;flaglight=0;}  
if (flagrear==1) {       if (flaglight== 1) {flaglight=0;}  else {flaglight=1;}     }  
                      

flagmesure=0;
 }  //fin if flagmesure




switch (var) {
  case 1:        //affichage value
//mesure de la charge de la batterie lithium 18650
digitalWrite(21,LOW);                    //active le pont diviseur
tensionbatt=analogRead(37);              //avec pont diviseur 100K et 220k  4.2V=>1.3125  donc 1630 decimale
tensionbatt=(tensionbatt/39+4);      //(volt*10) 12 bits 4096    0.35V chute de tension dans le transitor     3.3*3.2/409.6=1/39
tensionbatt = map(tensionbatt, 30, 42, 0, 100);    //map(value, fromLow, fromHigh, toLow, toHigh)   % de la charge
                                                   //2.9V=>-8%   3V=>0%    4.2V=100%    

//affichage  acceleration Y et  poucentage de la charge de la batterie
Heltec.display->clear();       //affichage numerique acceleration si appuie sur PRG
//Heltec.display->drawString(0, 0, "IUT GEII Soissons");
//Heltec.display->drawString(0, 11, "X "+String(accX_0,1)+"   ");
Heltec.display->drawString(0, 0, "Y "+String(accY_0,1)+"  ");          //acceleration filtré à 5HZ par le MPU6050
Heltec.display->drawString(83,0, String(tensionbatt)+"%");           //en poucentage de la charge
Heltec.display->drawString(0, 25,"Yf"+String(YaFout,1)+"   ");
Heltec.display->drawString(83, 25,String(flagfrein));
Heltec.display->drawString(100, 25,String(flaglight));
Heltec.display->display();
 break;  //case 1

case 2:       //affichage curve
 Heltec.display->clear();
 Heltec.display->drawHorizontalLine(0,32,127);  //(x,y,length)      //trace les axes
 for (byte im = 0; im <= 127; im++) {    // affichage de la courbe
 Heltec.display->setPixel(im,(32-Y[im]*3));   //mettre la courbe au millieu et augmenter l'echelle de 3
 Heltec.display->display();  }
 break;  //case 2

case 3:       //mode pause

break;  //case 3



case 4:       //send data monitor
if (flagenvoie>=1) {
 for (byte im = 0; im <= 127; im++) {    // affichage de la courbe
 Serial.print( Y[im]);Serial.println(";"); }
 Serial.println("stop");
flagenvoie=0;     }
break;  //case 4
 

 }//end switch
 
 
 }//end loop



Le programme complet avec l'odomètre arrive, mais le programme sera moins lisible, donc on préfère le décomposer en plusieurs programmes.

iutgeiisoissons

Voici le programme du compteur de velo avec un capteur a effet hall et un aimant avec un ESP32+OLED qui gere plus facilement la commande du feu arriére que le capteur d'acceleration.
Les explications sont ici
https://www.fichier-pdf.fr/2020/10/02/esp32-odometre-alarme-capacimetrertc-heure/
le MPU6050 a été gardé pour realiser une alarme.
Il reste plus qu'à faire un tracker avec un GPS et l'envoie d'une notification…..
Mais aussi  realiser un boitier mécanique étanche, car pour l'instant ce n'est pas terrible


on va s'inpirer du boitier suivant


g2gaston

#36
Oct 21, 2020, 11:26 am Last Edit: Oct 23, 2020, 05:31 pm by g2gaston
J'ai essayé votre programme sur un ESP32 TTGO avec un oled couleur d'aliexpress
Mais j'ai un souci car je n'arrive pas à afficher quelques choses sur le oled pourtant j'ai bien télécharge les bibliothèques comme expliqué ici, ainsi que d'inclure les chemins ou sont les bibliothèques et le driver.
cela compile bien
https://github.com/Xinyuan-LilyGO/TTGO-T-Display
https://www.instructables.com/Select-Color-Display-for-ESP32/

La variable i s'incrémente bien sur le moniteur série donc l'ESP32 fonctionne
Pourriez-vous m'eclairer, SVP, car je suis dans le brouillard

Je mets  le minimum du programme pour faire fonctionner le oled ici

Code: [Select]
#include <TFT_eSPI.h>
#include <SPI.h>
//#include "WiFi.h"
#include <Wire.h>
//#include <Button2.h>
#include "esp_adc_cal.h"

#include <C:\Users\geii\Documents\Arduino\libraries\TFT_eSPI\User_Setups\Setup25_TTGO_T_Display.h>
//#include <C:\Users\geii\Documents\Arduino\libraries\TFT_eSPI\User_Setups\Setup24_ST7789.h>
//#include <User_Setup.h\Setup25_TTGO_T_Display.h>


//#include <C:\Users\geii\Documents\Arduino\libraries\TFT_eSPI\User_Setups/Setup18_ST7789.h>
//#include <C:\Users\geii\Documents\Arduino\libraries\TFT_eSPI\TFT_Drivers/ST7789_Defines.h>


//#define ST7789_DRIVER
//#define ILI9341_DRIVER

//#define CGRAM_OFFSET      // Library will add offsets required


//#define TFT_MOSI            19    //SDA
//#define TFT_SCLK            18    //SCL
//#define TFT_CS              5     //CS
//#define TFT_DC              16    //RS
//#define TFT_RST             23    //reset

//#define TFT_BL          4  // Display backlight control pin

#define TFT_BACKLIGHT_ON HIGH  // HIGH or LOW light OLED or not



//#define TFT_WIDTH  135
//#define TFT_HEIGHT 240
TFT_eSPI tft = TFT_eSPI (TFT_WIDTH, TFT_HEIGHT);  // édité



/*
#define LOAD_GLCD
#define LOAD_FONT2
#define LOAD_FONT4
#define LOAD_FONT6
#define LOAD_FONT7
#define LOAD_FONT8
#define LOAD_GFXFF

#define SMOOTH_FONT
*/


//#define SPI_FREQUENCY  27000000
//#define SPI_FREQUENCY    40000000   // Maximum for ILI9341


//#define SPI_READ_FREQUENCY  6000000 // 6 MHz is the maximum SPI read speed for the ST7789V

char buff[512];
int vref = 1100;
int i;

#define ADC_PIN 34

void setup()
{
 
Serial.begin(115200);

pinMode(2, OUTPUT);   //led
//pinMode(34, INPUT);   //led

tft.init();
tft.setRotation(1);
tft.fillScreen(TFT_BLACK);
tft.setTextSize(2);
tft.setTextColor(TFT_WHITE);
tft.setCursor(0, 0);
tft.setTextDatum(MC_DATUM);


if (TFT_BL > 0) { // TFT_BL has been set in the TFT_eSPI library in the User Setup file TTGO_T_Display.h
         pinMode(TFT_BL, OUTPUT); // Set backlight pin to output mode
         digitalWrite(TFT_BL, TFT_BACKLIGHT_ON); // Turn backlight on. TFT_BACKLIGHT_ON has been set in the TFT_eSPI library in the User Setup file TTGO_T_Display.h
    }
   

tft.setTextSize(1);
uint16_t v = analogRead(ADC_PIN);
float battery_voltage = ((float)v / 4095.0) * 2.0 * 3.3 * (vref / 1000.0);
String voltage = "Voltage :" + String(battery_voltage) + "V";
Serial.println(voltage);
tft.fillScreen(TFT_BLACK);
tft.setTextDatum(MC_DATUM);
tft.drawString(voltage, tft.width() / 2, tft.height() / 2 );
delay(1000);
tft.drawString("Press again to wake up", tft.width() / 2, tft.height() / 2 );
delay(1000);

     tft.fillRect(0,0,240,135, TFT_BLUE); // erase the screen display
     tft.setTextSize(3);   // (num colonne , num ligne)
     tft.setCursor(0, 35); // (x colonne , y ligne) - F6CZV
     tft.print("VFO"); // F6CZV
delay(1000);

}




void loop()
{
  i++;
  if ( digitalRead(2)== 1 ) {digitalWrite(2,LOW);}  else {digitalWrite(2,HIGH);}
  Serial.println(i);
//tft.setRotation(0);

tft.fillScreen(TFT_RED);
delay(1000);
tft.fillScreen(TFT_BLUE);
//espDelay(1000);
delay(1000);
tft.fillScreen(TFT_GREEN);
delay(1000);
}


il y a une instrumentation de velo sur ce forum ici, j'ai envoyé un mail mais sans reponse
http://cyclurba.fr/forum/570020/dn-codage-protocole-sn-rie-bbs0x.html?from=571&discussionID=18542&messageID=638753&rubriqueID=102&pageprec



lesept

Ca peut venir du fait que le constructeur

Code: [Select]
TFT_eSPI tft = TFT_eSPI(135, 240); // Invoke custom library
est avant les define des pins du SPI.

J'utilise ce même module TTGO et ça fonctionne bien.
Il faut sélectionner

Code: [Select]
#define ILI9341_DRIVER

dans le fichier User_Setup.h de la bibliothèque TFT_eSPI. Les autres lignes doivent commentées :
Code: [Select]
// Only define one driver, the other ones must be commented out
#define ILI9341_DRIVER
//#define ST7735_DRIVER      // Define additional parameters below for this display
//#define ILI9163_DRIVER     // Define additional parameters below for this display
//#define S6D02A1_DRIVER
//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI
//#define HX8357D_DRIVER
//#define ILI9481_DRIVER
//#define ILI9486_DRIVER
//#define ILI9488_DRIVER     // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high)
//#define ST7789_DRIVER      // Full configuration option, define additional parameters below for this display
//#define ST7789_2_DRIVER    // Minimal configuration option, define additional parameters below for this display
//#define R61581_DRIVER
//#define RM68140_DRIVER
//#define ST7796_DRIVER
//#define SSD1963_480_DRIVER    // Untested
//#define SSD1963_800_DRIVER    // Untested
//#define SSD1963_800ALT_DRIVER // Untested


A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

Go Up