Afficher données sur LCD pendant que mon capteur continue à faire des mesures

Bonjour,

Je voudrais savoir quel est le meilleur moyen de collecter des données pendant que l’on affiche une valeur moyennée de ces dernières par exemple. Le détecteur captant des “fronts montants” et pouvant être amené à être sollicité un très grand nombre de fois par secondes. L’idée serait de créer une fonction externe d’affichage avec un delay(2000) pour laisser le temps de lire, de moyenner puis d’afficher la mesure pendant que le capteur continue d’alimenter indépendamment les tableaux de mesures et de ce fait ne pas perdre pour autant en précision. Serait-il mieux d’avoir un autre microcontrôleur pour gérer ça à part? Dans ce cas comment gérer ça au mieux?

Pour l’instant je n’utilise qu’un seul µcontrôleur (nano). Voilà où j’en suis:

// Librairies
#include <LiquidCrystal.h>

// Configuring the LCD screen to display datas
LiquidCrystal lcd(3, 4, 12, 11, 10, 9);

// Variables
int mybutton = 7; // sensor input digital port
int counter = 0;  // one counter
int buttonState; // button state
int memoryState = LOW; // Recording the memory state
unsigned long time; // Time recording
float deltaN; // To calculate: numbers of pics received
float deltaTime; // To calculate: during delta t
float result; // Result 
// Tables
int increment = 0;
float timeTab[]={0};
int numberTab[]={0};

// Initialising
void setup() {
  // Define the entry as an input
  pinMode(mybutton, INPUT);
  // Initialize the LCD screen
  lcd.begin(16,2);
  delay(10); // fast pause to let initialization time
  lcd.setCursor(0, 0); // top left
  lcd.print("LCD OK") ;
  delay(1000); // pause of 2 secondes
  // Display the beginning of the program to users  
  lcd.clear();  
  lcd.setCursor(0, 0); // top left
  lcd.print("BENOIT M");
  delay(1000);
  lcd.setCursor(0, 1); // bottom left
  lcd.print("Loadings");
  delay(500);
  lcd.clear();
  // 
}
// Loop
void loop()
{
  increment++;
  // Reading the button state
  buttonState = digitalRead(mybutton);
  // IF the button has a different state than the registered one AND this state is "high"
  if((buttonState != memoryState) && (buttonState == HIGH))
  {
    // Increment the counter
    counter++;
    // Record the time
    time = millis();
    // Data processing
    timeTab[increment]={time};
    numberTab[increment]={counter};
    deltaTime = ((timeTab[increment]-timeTab[increment -1])/1000.0);
    deltaN= (numberTab[increment]-numberTab[increment -1]);
    result = (deltaN/deltaTime);
    // Display results
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("moyenne = ");      
    lcd.print(result);      
    lcd.setCursor(0,1);
    //lcd.print(timeTab[increment]);
  }
  // we record the state of the button for the next turn
  memoryState = buttonState;
}

Il faudrait que tu précises le "très grand nombre de fois par seconde". Si tu dépasses les centaines de milliers ça risque de devenir difficile. Sinon, c'est certainement faisable avec un nano.

Par contre, mettre un delay est la pire des idées que tu peux avoir... Il faut que tu te renseignes sur la gestion du temps sur Arduino, il y a énormément de posts sur ce sujet dans le forum et des tutos dans la partie française et la partie US.

Une possibilité, que je n'ai pas encore eu la possibilité de tester, serait d'utiliser ce qui est décrit ici.

hello
en dehors de ton problème d'affichage

ce n'est pas une bonne idée de nommer une variable "time".

ton prg ne mesure pas ce que tu imagines

que fait "increment" dans la loop à ton avis?

et comme tu l'utilises ensuite pour designer des cases dans un tableau pour y stoker et y lire des données....
de plus tu déclares "increment" en int

La condition dans

if((buttonState != memoryState) && (buttonState == HIGH))

est vraie si buttonstate est à HIGH et memorystate à LOW, tu peux l'écrire :

if (buttonState && !memoryState)

Bonjour,

Désolé pour ma réponse tardive. La question du post est "calculer/afficher pendant la prise de mesure". Vaut-il mieux mettre deux arduinos, ou quelle architecture de code adopter?..

Le delay() est utilisé uniquement dans le setup() donc aucune gène puisque le but est de calculer un delta t (variation de temps). Pour le problème de temps ce n'en est pas un puisque la fréquence de l'horloge est de 16 MHz. Féchantillonnage est de l'ordre du MHz donc largement suffisant pour mon capteur (en utilisant le théorème de Shannon).

De plus incrément sert à compter le nombre de pulses reçus. Je modélise mon signal reçu non pas par une fonction porte mais une fonction de Dirac, cela à été mon premier problème.
Je le détecte par un changement d'état.

Cdt,

Maxime.

Salut,

pas mal de choses à revoir dans ton code:

d'abord, évite d'utiliser des float pour des entiers.

ensuite tu as:

int numberTab={0};

qui équivaux à:

int numberTab[1] = 0;

soit:

int numberTab = 0;

ensuite dans ton loop tu as:

increment++;

puis:

numberTab[increment]={counter};

je te laisse découvrir où est l'erreur. :slight_smile:

maximeBenoit1110:
Féchantillonnage est de l'ordre du MHz donc largement suffisant pour mon capteur (en utilisant le théorème de Shannon).

Si la fréquence des impulsions est de l'ordre du Mhz, tu peux oublier digitalRead()

Bonjour,

Aucune erreur. Je débute en C, mon but étant de créer une matrice dans laquelle je vais venir stocker des entiers j’utilise bien int pour les incrémentations et float pour le temps. Je les initiale à 0 au départ. Peut être connaissez-vous un meilleur moyen de déclarer et utiliser des matrices, je suis preneur?

Etant donné que je ne connais pas encore la réponse de ce post, je ne me suis pas encore occupé de la partie traitement de données. Si j’arrive à stocker un nombre suffisant d’incréments entre chaque affichage, l’utilisation d’une matrice pourrait être pertinente: deltaN= (numberTab[increment]-numberTab[increment -i]); i représentant le nombre d’occurences entre 2 delta T. Sinon je pourrais parcourir le tableau en faisant comptant le nombre d’occurences entre deux valeurs de temps données, espacées de i par exemple. A voir lequel est le plus coûteux en temps de calcul. Cela viendra dans un second temps je l’ai laissé à 1 pour l’instant ce qui est inutile mais reste juste.

Votre réponse est complètement hors sujet mais vous m’avez fait part d’une remarque utile concernant digitalRead(). La fréquence d’échantillonage max en utilisant cette fonction est de 204MHz (donc 102Mhz réellement exploitables expérimentallement). Petit erratum.

Auriez vous des conseils en ce qui concerne la question de ce post?

Tu es bien sûr de toi.
Bonne suite.

Si vous parlez du fait qu'en utilisant des entiers il faut utiliser int et des nombres réels des float oui. Mais la partie traitement de donnée n'est en aucun cas le sujet et n'a pas à interférer je ne m'en occuperai que dans un second temps.

Bonne suite à vous aussi.

Tu dis

L'idée serait de créer une fonction externe d'affichage avec un delay(2000) pour laisser le temps de lire, de moyenner puis d'afficher la mesure pendant que le capteur continue

Donc le delay n'est pas dans le setup ? Come je l'ai dit plus haut, delay est ton pire ennemi. Pendant la durée du delay, tu bloques ton microcontrôleur, il ne fait rien donc surtout pas des mesures...

Si je comprends bien ce que tu veux savoir c'est si le LCD est assez rapide pour afficher les variations de ta moyenne pendant que ton microcontrôleur fais ses mesures ?

Il faudrait préciser de quel écran tu parles. Si c'est un LCD genre 2 lignes de 16 caractères pour afficher des nombres :
1 J'ai peur qu'il soit trop lent, mais tu ne nous as pas encore donné ta cadence d'acquisition donc difficile de répondre.
2 De plus, si tu affiches des chiffres très vite, ce sera illisible. Le microcontrôleur est bien plus rapide que toi et que tes yeux.

Si tu veux afficher une courbe, alors c'est un autre type d'écran, genre oled ou tft qui te faut.

Merci lesept. Je n'y connais pas grand chose et sur le code que j'ai posté on voit clairement que je me suis un peu perdu à force d'essayer des choses différentes. Avant de coder et de corriger l'orthographe, il faut que je comprenne la logique!

Le type d'instrument est un dosimètre qui sera calibré avec un échantillon d'ouraline puis j'appliquerai une conversion en µSievert, donc normalisé à l'Homme et adapté à la mesure de la contamination (et non de l'irradiation). Il existe différents types de rayonnements, pour ma part je suis équipé de 2 tubes Geiger-Muller (mesure de l'effet Compton): SMB20 (Russe) et J305BY (Chinois). La fréquence d'échantillonage est variable, pour donner un ordre d'idée:
https://www.irsn.fr/FR/connaissances/Installations_nucleaires/Les-accidents-nucleaires/accident-fukushima-2011/fukushima-2018/Pages/0-fukushima-daiichi-2018-sommaire.aspx#.W6PK_fY6_IU
On lit que dans les zones qui craignent on parle de 50mSv/an soit 8760 mSv/h.
Si je ne me trompe pas et reprennez moi gentillement si c'est le cas. 10^6Hz pour échantillonnage max donc on peut collecter 6.10^7cpm soit 5.10^5µSv/h.
D'après ce calcul je suis large, d'autant plus qu'il faut aussi considérer la sensibilité des capteurs qui est inférieure.

Cela donne une idée de mon projet perso pour lequel j'ai peu de temps. Il existe différents codes sur le net. J'avais écris quelques algos qui ne servent pas à grand chose à mon sens car comme tu le précises je me sers d'un delay qui bloque tout pendant la mesure. C'est l'erreur principale qui fausse la mesure. Je ne peux pas afficher le résultat si le compteur s'affole. A moins de stopper la mesure pendant l'affichage et de reprendre une moyenne plus tard auquel cas je bloque l'écran.

D'où la question de mon post. A mon faible niveau en électronique et langage C je n'ai que des idées sans rien de concret. C'est pourquoi je me suis dis pourquoi pas tenter un forum et partager cette réponse qui à mon sens peut être utile à de nombreux projets. Avant de partir autant se lancer dans la bonne direction.

On lit que dans les zones qui craignent on parle de 50mSv/an soit 8760 mSv/h.

Je ne comprends pas ce calcul. Il y a 8760 heures par an donc 50/8760=5.7 micro SV/h

Si je ne me trompe pas et reprennez moi gentillement si c’est le cas. 10^6Hz pour échantillonnage max donc on peut collecter 6.10^7cpm soit 5.10^5µSv/h.

Là non plus je ne comprends pas.

Mais je pense que tu n’as pas encore les idées bien claires sur ce que tu veux faire avec ton afficheur

Il faut que tu définisses ce que tu veux afficher et quand tu veux l’afficher. Je te l’ai dit plus haut. Afficher une valeur tous les centièmes de seconde n’a pas de sens. Toutes les secondes c’est déjà plus réaliste mais est ce nécessaire ?

Tu peux t’en tenir à afficher une valeur toutes les deux ou trois secondes, voire même plus lentement encore, je ne pense pas que ton niveau de dose varie si vite.

Dans ce cas, ton code sera tout simple. Tu crées un chrono et chaque fois qu’il arrive à une valeur choisie, par exemple trois secondes soir 3000 ms,tu affiches la valeur courante de ce que tu veux afficher.

Un chrono c’est une variable de type unsigned long que tu initialises avec

 chrono = millis() ;

Tu vérifiés dans la loop que tu arrives au terme

if (chrono - millis () > duree) 
{
chrono = millis() ;
 là fera l'affichage}

Re,

Oui faute lourde, en répondant très vite j’ai multiplié mais il faut diviser évidemment. Je te laisse le soin de refaire les calculs et de me dire si ça te paraît acceptable. Je suis moins sûr pour la précision max sur la détection même si cela me parait aller. L’idée était de faire un comparatif entre ce que notre corps peut accepter « au max » (cf données fukushima) vs ce que mon capteur peut détecter au max (échantillonage arduino) et voir si ce sera dans les bornes.

J’ai les idées claires. Les emmisions et les réceptions sont des phénômènes probabilistes => aléatoires et je veux ainsi améliorer ma précision sur la valeur moyenne instantanée reçue. Couper toutes les 3 secondes pour reprendre une seconde après pour moi n’a pas de sens dans ce cas de figure. En thermodynamique cela ne m’aurait pas géné (pour un système fermé dans les CNTP soumit à de « faibles » variations de T°) de faire ça avec un thermomètre et en prennant soin de vérifier sa précision. Car on peut écrire tous les bons programmes que l’on veut mais c’est inutile de lire une température de 20°C si ton capteur à une précision de +/-15 °C, en exagérant bien sûr.

J’ai cru voir que tu t’intéressais au sujet et je pense avoir trouver la réponse à ma question. Elle réside en seul mot. J’ai eu souvenir des requêtes effectuées sur des serveurs pendant que d’autres s’exécutées pour ne pas géner l’expérience utilisateur. J’ai regardé et ça se fait aussi en C. On parle de programmation asynchrone. Je t’envoi 2 liens:

http://sametmax.com/la-difference-entre-la-programmation-asynchrone-parallele-et-concurrente/
Il y a quelques bibliothèques dans celui-ci:
http://p.loussouarn.free.fr/arduino/asynchrone/asynchrone.html

Je vais essayer de creuser là dedans.
J’espère que ces liens vous seront utiles.