1
Vos projets / Re : Boite de mesure de vitesse Arduino
« le: avril 25, 2021, 12:51:32 pm »
Bonjour à tous,
Bon, il semble que je me sois mal expliqué sur mes intentions et que j'ai mis beaucoup trop de temps à venir partager les infos que j'avais, j'en suis navré
Sachez que ma démarche n'est pas commerciale, j'autorise les particuliers à s'inspirer et même à reproduire, mais j'ai pris le parti de protéger contre la commercialisation, ce n'est pas la même chose. A date, je n'en ai vendu que deux et n'espère pas en vendre beaucoup plus, je ne le fait que pour satisfaire les personnes qui en veulent une mais n'ont pas les connaissance pour le faire eux même. Pour la fabrication, c'est très artisanal, les composants se trouvent sur Ebay très facilement, la quincaillerie vient de Leroy-Merlin et certains éléments sont imprimés en PLA.
Il est tout à fait possible que ça fonctionne avec d'autre TCO que TCV9, mais je ne suis pas en mesure de tester.
N'étant pas moi même programmeur Arduino, je n'ai visiblement pas eu la bonne démarche de partage, j'espère que ce post rétablira un peu les choses.
Pour ceux que ça intéresse encore un peu, voici le code, qui a été écrit par un membre de mon club et pas du tout avec les informations glanées ici. Je partage d'ailleurs les petits bénéfices avec lui
Le seul truc que nous ne sommes pas arrivé à faire, c'est de faire clignoter la LED verte lorsque la vitesse est stabilisée et ce, jusqu'à ce quel se fige allumée. Dans le meilleur des cas elle clignote une fois au début...
Bonne journée
Bon, il semble que je me sois mal expliqué sur mes intentions et que j'ai mis beaucoup trop de temps à venir partager les infos que j'avais, j'en suis navré
Sachez que ma démarche n'est pas commerciale, j'autorise les particuliers à s'inspirer et même à reproduire, mais j'ai pris le parti de protéger contre la commercialisation, ce n'est pas la même chose. A date, je n'en ai vendu que deux et n'espère pas en vendre beaucoup plus, je ne le fait que pour satisfaire les personnes qui en veulent une mais n'ont pas les connaissance pour le faire eux même. Pour la fabrication, c'est très artisanal, les composants se trouvent sur Ebay très facilement, la quincaillerie vient de Leroy-Merlin et certains éléments sont imprimés en PLA.
Il est tout à fait possible que ça fonctionne avec d'autre TCO que TCV9, mais je ne suis pas en mesure de tester.
N'étant pas moi même programmeur Arduino, je n'ai visiblement pas eu la bonne démarche de partage, j'espère que ce post rétablira un peu les choses.
Pour ceux que ça intéresse encore un peu, voici le code, qui a été écrit par un membre de mon club et pas du tout avec les informations glanées ici. Je partage d'ailleurs les petits bénéfices avec lui
Le seul truc que nous ne sommes pas arrivé à faire, c'est de faire clignoter la LED verte lorsque la vitesse est stabilisée et ce, jusqu'à ce quel se fige allumée. Dans le meilleur des cas elle clignote une fois au début...
Code: [Sélectionner]
//Type de Carte: Adafruit ItsyBitsy 5V
//Port Com:
//Programmer: ArduinoISP
// NOTE: OK le 04/11/2020 sur impulsion Arduino 25ms/10ms/75ms --> 120km/h, 300km/h, 40km/h
// NOTE: v10 OK le 28/12/2020, sauf l'envoi vers TC:
// - ne pas envoyer de 0
// - envoyer la vitesse une seule fois qaund elle est stabilisée
/****************************************************************************************************************
https://learn.adafruit.com/introducting-itsy-bitsy-32u4/pinouts
https://letmeknow.fr/shop/fr/ecrans/185-afficheur-lcd-4-lignes-20-caracteres-bleu-i2c-4894479443361.html
https://www.arduino.cc/reference/en/language/functions/interrupts/interrupts/
https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/
Blink
D7: capteur input d
Pour les calculs, diamètre des rondelles => 5.88 cm
5.88 x 3.1416 = 18.472608 cm de circonférence
18.47 x 87 = 1606.89 cm => 16,0689 m réels
100km/h / HO <==> 1.15km/h
1.15km/h x 1000m/km / 3600s/h <=> 0.319m/s = 32cm/s
1 tour = 18.47cm
==> 100km/h <--> 1.7tr/s ???????
==> 1.7tr/s / 20 aimants => 1/(1,7 x20)= 29ms entre 2 aimants ??????
pulse 100ms = 2tr = 200km/h
120km/h / HO <==> 1.38km/h
1.38km/h x 1000m/km / 3600s/h <=> 0.38m/s = 38cm/s
==> 120km/h = 2tr/sec
2tr/sec / 20 aimant = 1sec/(2tr x 20 aimants) = 25ms
******************************************************************************************************************/
//======================================================================
// V1.5
// Add 2 LEDs:
// GREEN: flash when speed is stable
// YELLOW: ON when in Freeze
// Ajout du temps pour parcourir 1m a vitesse stabilisée.
//======================================================================
#define FALSE false
#define TRUE true
#define LED_BUILTIN 13
#define LED_VERT 8
#define LED_JAUNE 4
#define LED_OFF 0
#define LED_ON 1
#define CAPTEUR_IN_D7 7 // D7 also interrupt pin
#define CAPTEUR_IN_A0 A0
#define SW 11
#define SCL 3
#define SDA 2
#define SENSOR_ON 1
#define SENSOR_OFF 0
bool sensor_state = 0;
unsigned char sw_status, sw_state;
#define COUNT 0
#define FREEZ 1
#define CLEAR 2
#define END_FREEZ 3
//--- v12 ----
#define MIN_SERIAL_TEMPO 10000 // 5 sec = 5000 millisecond
#define MAX_SPEED_ERR 0.10 // 10%
volatile byte sense;
unsigned long ref_time, new_time, delta_t;
unsigned long lcd_time, lcd_new_time, ref_time_avg;
unsigned long serial_time, serial_new_time; // PA v11
volatile unsigned long pulse_cnt = 0;
volatile unsigned long pulse_cnt_tot = 0;
float speed_i, speed_avg, speed_avg_lcd; // vitesse instantannée entre 2 aimants, vitesse moyenne par tour, vitesse moyenne pour affichage
float serial_speed_avg, speed_avg_delta, speed_avg_delta_pos, speed_avg_delta_neg; // PA v11
//-------------------------------------------------------------------------------------
// Les 3 constantes suivantes sont à ajuster avec le systeme de mesure
//-------------------------------------------------------------------------------------
const float circonf_cm = 18.47; // Circonference de la roue de mesure en cm
const int nb_aimants = 20; // Nb d'aimants par circonference
const int scale = 87; // echelle HO
//------------------- NE pas modifier --------------------------------------------------
float circonf = (circonf_cm * scale) / 100; // Circonférence réelle en m
float interval = circonf / nb_aimants; // Intervale entre 2 aimants en m.
float intervalHO = circonf_cm / nb_aimants; // Intervale entre 2 aimants en cm.
//-------------------------------------------------------------------------------------
// La constante suivante est à ajuster en fonction de la distance voulue pour le calcul du temps (UM)
//-------------------------------------------------------------------------------------
const int UM_DIST = 98; // distance de mesure en cm
volatile float distance = 0; // distance parcourue
volatile float dist_avg = 0;
volatile float dist_tot = 0;
volatile float dist_totHO = 0;
float conv_kmh = 3.6; // 3600 sec / 1000m
int afield;
unsigned long debounce_time, new_debounce_time;
unsigned long sensor_time_rise, sensor_time_fall;
unsigned long time_UM, time_UM_new;
volatile float dist_UM;
bool fg_speed_stable, fg_UM_cnt, fg_UM_cnt_end;
unsigned long LED_VERT_Blink = 0;
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display
// the setup function runs once when you press reset or power the board
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
pinMode(LED_VERT, OUTPUT);
pinMode(LED_JAUNE, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
int tempo = 20;
Serial.begin(115200);
while (tempo > 0) {
delay(100);
tempo--;
if(Serial) tempo = 0;
; // wait for serial port to connect. Needed for native USB
}
digitalWrite(LED_BUILTIN, LOW);
digitalWrite(LED_JAUNE, LED_OFF);
digitalWrite(LED_VERT, LED_OFF);
// initialize digital pin SWitch as an input.
pinMode(SW, INPUT_PULLUP);
// initialize digital pin CAPTEUR_D7 as an output.
pinMode(CAPTEUR_IN_D7, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(CAPTEUR_IN_D7), sens_change, CHANGE);
// pinMode(CAPTEUR_IN_A0, AnalogInput); // NO need to define analog pins
afield = analogRead(CAPTEUR_IN_A0);
lcd.init(); // initialize the lcd
lcd.init();
// Print a message to the LCD.
lcd.backlight();
lcd.setCursor(0, 0); // (x, y)
lcd.print(" La Box a Laurent J ");
lcd.setCursor(0, 2); // (x, y)
lcd.print("Vers 1.5 18-02-2021");
lcd.setCursor(0, 3); // (x, y)
lcd.print(" Circonf. 18.47cm ");
Serial.println(" La Box a Laurent J ");
Serial.println("Vers 1.5 18-02-2021");
delay(5000);
ref_time = 0;
distance = 0;
dist_avg = 0;
pulse_cnt = 0;
ref_time_avg = 0;
sw_status = COUNT;
sw_state = 1;
serial_speed_avg = 0;
speed_avg_delta_pos = 1;
speed_avg_delta_neg = 1;
time_UM = 0;
dist_UM = 0;
fg_speed_stable = FALSE;
fg_UM_cnt = FALSE;
fg_UM_cnt_end = FALSE;
}
// the loop function runs over and over again forever
void loop() {
if(sense > 0)
{
//digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
//new_time = millis();
if(ref_time != 0)
{
delta_t = new_time - ref_time;
speed_i = (3600 * sense * interval) / delta_t; // vitesse instantanée en m/s
}
ref_time = new_time;
sense = 0;
if(ref_time_avg != 0)
{
speed_avg = (3600 * dist_avg)/(new_time - ref_time_avg); // 3.6 = (3600 sec/h * 1000 ms/sec) / 1000m/km
dist_avg = 0; // PA v10
ref_time_avg = new_time; // PA v10
if (speed_avg != 0)
{
serial_speed_avg = (serial_speed_avg * 7) + speed_avg; // PA V11: moyenne sur 8 echantillons
serial_speed_avg = serial_speed_avg / 8;
speed_avg_delta = speed_avg - serial_speed_avg; // v11: calculate positiv and negativ delta
if (speed_avg_delta < 0)
{
speed_avg_delta_neg = -speed_avg_delta;
speed_avg_delta_neg = speed_avg_delta_neg / serial_speed_avg;
}
else
{
speed_avg_delta_pos = speed_avg_delta;
speed_avg_delta_pos = speed_avg_delta_pos / serial_speed_avg;
}
}
else
{
serial_speed_avg = 0;
speed_avg_delta_pos = 1;
speed_avg_delta_neg = 1;
}
}
else
{
ref_time_avg = new_time;
}
}
lcd_new_time = millis();
serial_new_time = lcd_new_time; // v12
if((lcd_new_time - lcd_time) > 1000)
{
// PA
lcd.setCursor(0, 0);
if(fg_UM_cnt_end == TRUE)
lcd.print("Pls: Temp: ");
else
lcd.print("Pls: ");
lcd.setCursor(0, 1);
lcd.print("Dist.en m: ");
lcd.setCursor(0, 2);
lcd.print("Dist.en km: ");
lcd.setCursor(0, 3);
lcd.print("Vit.moy.: km/h");
lcd.setCursor(5, 0);
lcd.print(pulse_cnt_tot);
lcd.setCursor(15, 0);
lcd.print((float)time_UM/1000);
lcd.setCursor(13, 1);
lcd.print(dist_totHO/100);
lcd.setCursor(13, 2);
lcd.print(dist_tot/1000);
lcd.setCursor(10, 3);
lcd.print(speed_avg);
#ifdef DEBUG
Serial.print("pulse_cnt: ");
Serial.print(pulse_cnt_tot);
Serial.print(" - distance_avg (m): ");
Serial.print(dist_avg);
Serial.print(" - speed_avg (km/h): ");
#endif
// ------------- v11 --------------------------------
if(serial_speed_avg != 0)
{
if((serial_new_time - serial_time) > MIN_SERIAL_TEMPO)
{
/* speed_avg_delta = speed_avg - serial_speed_avg;
if (speed_avg_delta < 0)
{
speed_avg_delta_neg = -speed_avg_delta;
speed_avg_delta_neg = speed_avg_delta_neg / serial_speed_avg;
}
else
{
speed_avg_delta_pos = speed_avg_delta;
speed_avg_delta_pos = speed_avg_delta_pos / serial_speed_avg;
}
*/
if((speed_avg_delta_pos < MAX_SPEED_ERR) && (speed_avg_delta_neg < MAX_SPEED_ERR))
{
digitalWrite(LED_VERT, LED_ON);
LED_VERT_Blink = 10;
Serial.println(serial_speed_avg); // envoi serie pour TC
serial_time = serial_new_time;
speed_avg_delta_pos = 1;
speed_avg_delta_neg = 1;
fg_speed_stable = TRUE;
}
else if ( LED_VERT_Blink > 0)
{
LED_VERT_Blink--;
if (LED_VERT_Blink == 0)
{
digitalWrite(LED_VERT, LED_ON);
}
else if (LED_VERT_Blink == 7)
{
digitalWrite(LED_VERT, LED_OFF);
}
}
else
{
digitalWrite(LED_VERT, LED_OFF);
fg_speed_stable = FALSE;
}
}
}
else
{
serial_time = serial_new_time;
}
//------------------ v11 end -----------------------
if (sw_status == COUNT)
{
speed_avg = 0; // PA v10 à VERIFIER !!!! le 25-12-2020
}
lcd_time = lcd_new_time;
//ref_time_avg = 0;
//dist_avg = 0; // PA v10
pulse_cnt = 0;
}
if((digitalRead(SW) == 0) && (sw_state == 0))
{
sw_state = 1000; // debounce
if(sw_status == END_FREEZ) // FREEZ --> CLEAR
{
sw_status = CLEAR;
digitalWrite(LED_VERT, LED_ON);
digitalWrite(LED_JAUNE, LED_OFF);
dist_tot = 0;
dist_totHO = 0;
pulse_cnt_tot = 0;
speed_avg = 0;
fg_speed_stable = FALSE;
time_UM = 0;
fg_UM_cnt = FALSE;
fg_UM_cnt = FALSE;
fg_UM_cnt_end = FALSE;
}
else if (sw_status == COUNT)
{
sw_status = FREEZ;
digitalWrite(LED_JAUNE, LED_ON);
}
}
else if(digitalRead(SW) == 1)
{
if (sw_state > 0)sw_state--; // debounce
else if(sw_status == CLEAR) // CLEAR --> COUNT
{
sw_status = COUNT;
digitalWrite(LED_VERT, LED_OFF);
}
else if (sw_status == FREEZ)
{
sw_status = END_FREEZ;
//digitalWrite(LED_JAUNE, LED_OFF);
}
}
}
void sens_change() {
delayMicroseconds(100); // debounce delay 10µs
if(digitalRead(CAPTEUR_IN_D7) == 1)
{
sensor_time_rise = micros();
if((sensor_time_rise - sensor_time_fall) > 2000) { // if delay > 10ms
if((sensor_state == SENSOR_OFF) && (sw_status == COUNT))
{
new_time = millis();
sense++;
pulse_cnt++;
pulse_cnt_tot++;
distance += interval;
dist_avg += interval;
dist_tot += interval;
dist_totHO += intervalHO;
sensor_state = SENSOR_ON;
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
if(fg_speed_stable == TRUE)
{
if(fg_UM_cnt == FALSE)
{
time_UM_new = new_time;
fg_UM_cnt = TRUE;
fg_UM_cnt_end = FALSE;
dist_UM = 0;
digitalWrite(LED_VERT, LOW);
}
else if (dist_UM < UM_DIST) // en cm
{
time_UM = new_time - time_UM_new;
dist_UM += intervalHO;
}
else
{
digitalWrite(LED_VERT, HIGH);
fg_UM_cnt_end = TRUE;
}
}
else
{
dist_UM = 0;
//time_UM = 0;
fg_UM_cnt = FALSE;
if(fg_UM_cnt_end != TRUE)
{
dist_UM = 0;
time_UM = 0;
}
//digitalWrite(LED_VERT, LOW);
}
}
}
}
else // if(digitalRead(CAPTEUR_IN_D7) == 0)
{
if(sensor_state == SENSOR_ON)
{
sensor_time_fall = micros();
if((sensor_time_fall - sensor_time_rise) > 2000) { // if delay > 10ms
sensor_state = SENSOR_OFF;
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
}
}
}
}
Bonne journée