Mesure la vitesse d'un hand spinner avec la photo resistance (LDR); utilise le Timer, la console et la LDR.

Dependencies:   mbed

Ca tourne vite ! et une photoresistance (LDR) est lente !

La boucle du programme:

  1. Calibration du capteur
  2. Mesures
  3. Affichage sur la console

Le code utilise un Timer pour mesurer le temps écoulé, des fonctions et des structures.

Console

La vitesse de la communication USB est configurée à 115.200 baud (par défaut elle est de 9600.) A cette vitesse on peut se permettre d'envoyer chaque mesure sur la console et on reste dans les 1ms par boucle.

Au début, a 9600 bauds, on a regroupé les mesures par paquet de 1.000 pour les afficher d'un coup. Pendant la boucle on ne fait que remplir un tableau de float[1000] (il semble avoir du mal á aller au delá de 1000?) et apres les mesures on dump (affiche) le tableau.

Physique

La carte est assez rapide pour faire environs 30.000 mesures par seconde. Donc théoriquement mesurer des vitesses de rotation jusqu'a 15.000 tours/s ! La premiere limite qu'on atteindra est la latence de la photoresistance. A priori entre 10 et 500 ms et ce n'est pas linéaire. Elle met plus de temps (j'ai lu jusqu'à une seconde !?) pour augmenter sa résistance après avoir été éclairée.

Premières visu

Après avoir visualisé les mesures par paquets de 1.000. Il semble y avoir un autre phénomène. On observe une sorte de peigne, comme si une mesure sur deux ne rencontrait pas de résistance (valeur a 1). Mais ce n'est pas systématique non plus. https://docs.google.com/spreadsheets/d/1bWVamwfsqNKRFRfbD6L3g7Slo4lBYWXPn2ICLtPI5HI/edit?usp=sharing

Avec capa

Avec la capa de 10µF on a une courbe plus lisse.

Avec sortie des valeurs

afficher chaque valeur ralenti un peu la boucle, mais on reste à 1 ms par mesure, ce qui est suffisant.

On constate mieux le problème de saturation. Si la LDR est bien éclairé elle reste à 1.0, elle met du temps à re-descendre, mais montre des oscillations dès qu'on ne sature plus (pas besoin d'attendre 500ms!). On voit du 3 à 20 Hz environs, avec 25 points d'amplitude.

Sur une oscillation on pourra faire environs 50 mesures et voir un écart de 25 points. Ca reste largement suffisant.

A suivre ...

Next

  • Il faut juste indiquer les conditions d'éclairage:
    • LED rouge si on a trop de lumiere (on sature á 1)
    • LED bleu si on a pas assez de lumiere (a determiner)
    • LED orange si on a pas assez d'amplitude
  • Passer le AnalogIn de float (32b) à unsigned short (16b) https://developer.mbed.org/handbook/C-Data-Types
  • FFT https://developer.mbed.org/questions/tag/FFT/?sort=votes
  • Faire clignoter une LED a la vitesse du HandSpinner pour faire un effet stroboscopique et "arrêter" l'image.
  • Accélérer le HandSpinner avec un électro-aimant. (principe du moteur électrique).

Reference

Committer:
BrnVrn
Date:
Sun Jun 11 19:06:45 2017 +0000
Revision:
11:ba42369ffdc0
Parent:
10:49bc07cc747d
Moyenne glissante

Who changed what in which revision?

UserRevisionLine numberNew contents of line
BrnVrn 0:b99ba38a8a1c 1 #include "mbed.h"
BrnVrn 0:b99ba38a8a1c 2
BrnVrn 0:b99ba38a8a1c 3
BrnVrn 0:b99ba38a8a1c 4 DigitalOut myled(LED2); // Pas encore utilisé
BrnVrn 10:49bc07cc747d 5 AnalogIn phototo(A1); // Renvoie un float entre [1.0 ; 0.0]
BrnVrn 0:b99ba38a8a1c 6 // Light => no resistance
BrnVrn 0:b99ba38a8a1c 7 // Dark => high resistance
BrnVrn 11:ba42369ffdc0 8
BrnVrn 10:49bc07cc747d 9 Serial pc(USBTX, USBRX);
BrnVrn 0:b99ba38a8a1c 10
BrnVrn 5:eedebdeb0fac 11 const int changements_par_tour = 3*2; // HandSpinner avec 3 branches
BrnVrn 0:b99ba38a8a1c 12 const int tours_par_mesure = 2;
BrnVrn 11:ba42369ffdc0 13 const int timeout_ms = 4 * 1000; // 4 secondes
BrnVrn 11:ba42369ffdc0 14 const int TAILLE_RECORD = 1000;
BrnVrn 6:d9a1f4e2085b 15
BrnVrn 6:d9a1f4e2085b 16 struct Seuil {
BrnVrn 6:d9a1f4e2085b 17 float haut;
BrnVrn 6:d9a1f4e2085b 18 float bas;
BrnVrn 6:d9a1f4e2085b 19 };
BrnVrn 3:bceac350caa9 20
BrnVrn 3:bceac350caa9 21 Timer t; // https://developer.mbed.org/handbook/Timer
BrnVrn 3:bceac350caa9 22 // https://developer.mbed.org/questions/61002/Equivalent-to-Arduino-millis/
BrnVrn 3:bceac350caa9 23
BrnVrn 6:d9a1f4e2085b 24 Seuil calibration() {
BrnVrn 6:d9a1f4e2085b 25 float v, v_max, v_min, delta;
BrnVrn 6:d9a1f4e2085b 26 Seuil s;
BrnVrn 3:bceac350caa9 27
BrnVrn 3:bceac350caa9 28 v = phototo.read();
BrnVrn 3:bceac350caa9 29 v_max = v;
BrnVrn 3:bceac350caa9 30 v_min = v;
BrnVrn 3:bceac350caa9 31
BrnVrn 3:bceac350caa9 32 t.reset();
BrnVrn 3:bceac350caa9 33 t.start();
BrnVrn 5:eedebdeb0fac 34 for (int i=0; i<200 ; i++) {
BrnVrn 7:f0253646e129 35 v = phototo.read(); // float entre [1.0 ; 0.0]
BrnVrn 7:f0253646e129 36 //phototo.read_u16(); // @TODO renvoie un entier [65535 ; 0] (plus rapide)
BrnVrn 3:bceac350caa9 37 if (v > v_max) v_max = v;
BrnVrn 3:bceac350caa9 38 else if (v < v_min) v_min = v;
BrnVrn 3:bceac350caa9 39 wait_ms(5);
BrnVrn 3:bceac350caa9 40 }
BrnVrn 3:bceac350caa9 41 t.stop();
BrnVrn 6:d9a1f4e2085b 42 delta = (v_max - v_min) / 3.0;
BrnVrn 6:d9a1f4e2085b 43 s.haut = v_max - delta;
BrnVrn 6:d9a1f4e2085b 44 s.bas = v_min + delta;
BrnVrn 10:49bc07cc747d 45 pc.printf("Calibration [%.3f ; %.3f] [%.3f; %.3f] sur %d ms.\t", v_max, s.haut, s.bas, v_min, t.read_ms());
BrnVrn 6:d9a1f4e2085b 46 return s;
BrnVrn 3:bceac350caa9 47 }
BrnVrn 3:bceac350caa9 48
BrnVrn 0:b99ba38a8a1c 49
BrnVrn 8:99ac7f0ccebc 50 void affiche_mesures(float mesures[], int nb_mesures) {
BrnVrn 9:622cb3c52f16 51 if ( nb_mesures > TAILLE_RECORD ) nb_mesures = TAILLE_RECORD;
BrnVrn 10:49bc07cc747d 52 pc.printf("\r\n---------------------------------\r\n");
BrnVrn 10:49bc07cc747d 53 for (int i=0; i < nb_mesures ; i++) pc.printf("%f;", mesures[i]);
BrnVrn 10:49bc07cc747d 54 pc.printf("\r\n---------------------------------\r\n");
BrnVrn 7:f0253646e129 55 }
BrnVrn 7:f0253646e129 56
BrnVrn 7:f0253646e129 57
BrnVrn 0:b99ba38a8a1c 58 int main() {
BrnVrn 11:ba42369ffdc0 59 pc.baud( 115200 ); // 9600 14400 57600 115200
BrnVrn 11:ba42369ffdc0 60 //pc.format(8, SerialBase::None, 1); // Optional (default)
BrnVrn 0:b99ba38a8a1c 61
BrnVrn 10:49bc07cc747d 62 pc.printf("Demarrage ! \r\n");
BrnVrn 3:bceac350caa9 63
BrnVrn 1:3f385f24a7de 64 bool jour_ou_nuit, precedent;
BrnVrn 5:eedebdeb0fac 65 int changements, mesures;
BrnVrn 0:b99ba38a8a1c 66 int temps_par_tour_ms;
BrnVrn 7:f0253646e129 67 Seuil seuil;
BrnVrn 11:ba42369ffdc0 68 float value, valpre, moy;
BrnVrn 9:622cb3c52f16 69 float record[TAILLE_RECORD];
BrnVrn 2:3e1a580a3dde 70
BrnVrn 0:b99ba38a8a1c 71
BrnVrn 0:b99ba38a8a1c 72 while(true) {
BrnVrn 3:bceac350caa9 73
BrnVrn 11:ba42369ffdc0 74 seuil = calibration();
BrnVrn 11:ba42369ffdc0 75 valpre = seuil.haut; // initialise la valeur "precedente"
BrnVrn 0:b99ba38a8a1c 76
BrnVrn 5:eedebdeb0fac 77 changements = 0; mesures = 0;
BrnVrn 5:eedebdeb0fac 78 t.reset();
BrnVrn 0:b99ba38a8a1c 79 t.start();
BrnVrn 4:c34e09c71684 80 while ( ( changements < ( changements_par_tour * tours_par_mesure ) )
BrnVrn 3:bceac350caa9 81 && ( t.read_ms() < timeout_ms ) ) {
BrnVrn 0:b99ba38a8a1c 82
BrnVrn 5:eedebdeb0fac 83 value = phototo.read();
BrnVrn 7:f0253646e129 84 //printf("v %f\r\n", value); // debug, mais bien trop lent!
BrnVrn 9:622cb3c52f16 85 if (mesures < TAILLE_RECORD) record[mesures] = value;
BrnVrn 11:ba42369ffdc0 86 mesures++; // Attention de ne pas depasser!
BrnVrn 0:b99ba38a8a1c 87
BrnVrn 11:ba42369ffdc0 88 moy = (value + valpre) / 2.0; // on lisse
BrnVrn 11:ba42369ffdc0 89 valpre = value;
BrnVrn 11:ba42369ffdc0 90 if (moy > seuil.haut) jour_ou_nuit = true;
BrnVrn 11:ba42369ffdc0 91 else if (moy < seuil.bas) jour_ou_nuit = false;
BrnVrn 5:eedebdeb0fac 92 else continue;
BrnVrn 1:3f385f24a7de 93
BrnVrn 1:3f385f24a7de 94 if ( jour_ou_nuit != precedent ) {
BrnVrn 1:3f385f24a7de 95 precedent = jour_ou_nuit;
BrnVrn 0:b99ba38a8a1c 96 changements = changements + 1;
BrnVrn 0:b99ba38a8a1c 97 }
BrnVrn 0:b99ba38a8a1c 98 }
BrnVrn 0:b99ba38a8a1c 99 t.stop();
BrnVrn 5:eedebdeb0fac 100
BrnVrn 10:49bc07cc747d 101 pc.printf(" %d mesures et %d changements \t", mesures, changements);
BrnVrn 0:b99ba38a8a1c 102
BrnVrn 4:c34e09c71684 103 if ( t.read_ms() >= timeout_ms ) {
BrnVrn 10:49bc07cc747d 104 pc.printf("Timeout ... \r\n");
BrnVrn 4:c34e09c71684 105 continue;
BrnVrn 4:c34e09c71684 106 }
BrnVrn 4:c34e09c71684 107
BrnVrn 0:b99ba38a8a1c 108 temps_par_tour_ms = t.read_ms() / tours_par_mesure;
BrnVrn 0:b99ba38a8a1c 109 if (temps_par_tour_ms != 0)
BrnVrn 10:49bc07cc747d 110 pc.printf("Un tour en %d ms ;\t %d tours/seconde \r\n", temps_par_tour_ms, 1000/temps_par_tour_ms);
BrnVrn 0:b99ba38a8a1c 111 else
BrnVrn 10:49bc07cc747d 112 pc.printf("Etrange ! le temps mesure est nul !?\r\n");
BrnVrn 8:99ac7f0ccebc 113 affiche_mesures(record, mesures);
BrnVrn 0:b99ba38a8a1c 114 wait_ms(100);
BrnVrn 0:b99ba38a8a1c 115 }
BrnVrn 0:b99ba38a8a1c 116 }
BrnVrn 2:3e1a580a3dde 117
BrnVrn 2:3e1a580a3dde 118