Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2385 connectés 

 


 Mot :   Pseudo :  
  Aller à la page :
 
 Page :   1  2  3  4  5  ..  240  241  242  ..  278  279  280  281  282  283
Auteur Sujet :

[arduino] Topic Unique blabla @ Arduino

n°382643
Lermite
Posté le 22-09-2022 à 14:01:07  profilanswer
 

Reprise du message précédent :

marcoluni a écrit :

...Et d'ailleurs millis() n'est pas inopérant dans une interruption... je l'ai déjà fait dans quelques-uns de mes codes, cela a toujours fonctionné ...

Arrrgg... J'ai lu ça je ne sais plus où et l'ai pris pour argent comptant sans jamais prendre le temps de le vérifier: erreur inexcusable  :pfff:  
 
Je vais tester en virant le timer interrupt, le suspect n°1 des dysfonctionnement.
Je suis pratiquement certain que ça fonctionnera sans ce timer maudit.
Mais comme adapter mon code prend un certain temps et que j'ai plus important à faire (mettre à l'abri le bois de chauffage avant l'arrivée de la flotte) dans l'immédiat, je ne m'y collerai que ce soir.
 
Merci en tout cas pour cette info salvatrice  :jap:  
 
 

mood
Publicité
Posté le 22-09-2022 à 14:01:07  profilanswer
 

n°382661
rat de com​bat
attention rongeur méchant!
Posté le 22-09-2022 à 17:44:13  profilanswer
 

J'ai pas vraiment lu (j'ai choppé une cochonnerie de gros rhume, du coup je suis pas en très bon état...), mais si seulement quelque mesures de temps en temps sont fausses ça me fait penser au vieux soucis "atomic access". En gros tu dois avoir une INT qui se déclenche parfois juste au moment de lire une valeur et du coup ça donne n'importe quoi. En effet une valeur c'est probablement >8 bits, donc le µC doit exécuter plusieurs instructions à la suite et si entre temps la valeur est modfiée... https://www.nongnu.org/avr-libc/use [...] tomic.html

n°382682
Lermite
Posté le 22-09-2022 à 18:56:20  profilanswer
 

rat de combat a écrit :

J'ai pas vraiment lu (j'ai choppé une cochonnerie de gros rhume, du coup je suis pas en très bon état...), mais si seulement quelque mesures de temps en temps sont fausses ça me fait penser au vieux soucis "atomic access". En gros tu dois avoir une INT qui se déclenche parfois juste au moment de lire une valeur et du coup ça donne n'importe quoi. En effet une valeur c'est probablement >8 bits, donc le µC doit exécuter plusieurs instructions à la suite et si entre temps la valeur est modfiée... https://www.nongnu.org/avr-libc/use [...] tomic.html

Excellente explication qui correspond bien à ce que j'ai pu constater  :jap:  

n°382698
crazytiti
http://crazytiti.free.fr/
Posté le 22-09-2022 à 21:40:25  profilanswer
 

@rat de combat  [:invisible man]  
Je ne suis pas en état pour bien lire, mais en diagonale ça m'a l'air pas mal ton code.
Doit pas falloir grand chose pour que ça fonctionne correctement.
:bounce:


---------------
Le PC est une drogue... Téléchargez mes modèles 3D pour que j'ai du filament gratuit :-D https://www.printables.com/fr/@Crazytiti_1456354
n°382702
rat de com​bat
attention rongeur méchant!
Posté le 22-09-2022 à 22:31:46  profilanswer
 

Autre chose: Les variables globales utilisées dans le main/loop et dans une INT doivent être déclarées "volatile". Et il faut faire gaffe avec le atomic access comme je disais.

n°382703
jimbofarra​r
Poreux de la cafetière
Posté le 22-09-2022 à 23:11:37  profilanswer
 

rat de combat a écrit :

Autre chose: Les variables globales utilisées dans le main/loop et dans une INT doivent être déclarées "volatile". Et il faut faire gaffe avec le atomic access comme je disais.


Volatile est valable pour les variables sur 8 bits, au delà il faut utiliser la macro ATOMIC_BLOCK (en rajoutant #include <util/atomic.h> )


---------------
Bien des Shubs et des Zouls furent calcinés dans les profondeurs de l'énorme Sloar, en vérité, je vous le dis !
n°382707
rat de com​bat
attention rongeur méchant!
Posté le 22-09-2022 à 23:47:53  profilanswer
 

Non, tu mélanges deux choses.
 
volatile -> "cette variable peut changer de valeur à tout moment", toujours nécessaire
 
atomic -> "désactiver temporairement les INT pour éviter que la variable change en plein milieu de lecture". En principe uniquement nécessaire pour >8 bits mais en pratique il faudrait regarder ce que fait le compilateur, du moins si on fait lecture-écriture. Dans le doute un tel block ne fera pas de mal.

n°382709
jimbofarra​r
Poreux de la cafetière
Posté le 23-09-2022 à 00:31:09  profilanswer
 

rat de combat a écrit :

Non, tu mélanges deux choses.
 
volatile -> "cette variable peut changer de valeur à tout moment", toujours nécessaire
 
atomic -> "désactiver temporairement les INT pour éviter que la variable change en plein milieu de lecture". En principe uniquement nécessaire pour >8 bits mais en pratique il faudrait regarder ce que fait le compilateur, du moins si on fait lecture-écriture. Dans le doute un tel block ne fera pas de mal.


Va dire ça aux gars de chez arduino
 

Citation :

int or long volatiles
If the volatile variable is bigger than a byte (e.g. a 16 bit int or a 32 bit long), then the microcontroller can not read it in one step, because it is an 8 bit microcontroller. This means that while your main code section (e.g. your loop) reads the first 8 bits of the variable, the interrupt might already change the second 8 bits. This will produce random values for the variable.


 
https://www.arduino.cc/reference/en [...] /volatile/


Message édité par jimbofarrar le 23-09-2022 à 00:32:47

---------------
Bien des Shubs et des Zouls furent calcinés dans les profondeurs de l'énorme Sloar, en vérité, je vous le dis !
n°382710
rat de com​bat
attention rongeur méchant!
Posté le 23-09-2022 à 00:54:01  profilanswer
 

Désolé mais je ne vois rien qui contredit ce que je disais. Ils disent bien

Citation :

A variable should be declared volatile whenever its value can be changed by something beyond the control of the code section in which it appears, such as a concurrently executing thread. In the Arduino, the only place that this is likely to occur is in sections of code associated with interrupts, called an interrupt service routine.

et en plus

Citation :

If the volatile variable is bigger than a byte (e.g. a 16 bit int or a 32 bit long), then the microcontroller can not read it in one step, because it is an 8 bit microcontroller. This means that while your main code section (e.g. your loop) reads the first 8 bits of the variable, the interrupt might already change the second 8 bits. This will produce random values for the variable. [...] Remedy: [...] use the ATOMIC_BLOCK macro. Atomic operations are single MCU operations - the smallest possible unit.

n°382827
Lermite
Posté le 24-09-2022 à 17:04:23  profilanswer
 

A force de me prendre la tête sur un bout de code de mon Arduino, je bloque complètement.
Dans ce cas-là, bien souvent, il suffit d'expliquer le problème à quelqu'un d'autre Ca nous contraint à le percevoir différent au point que la solution nous paraisse subitement évidente [:tinostar]  
C'est précisément ce qui vient de m'arriver en rédigeant ce qui suit, que je laisse pour info puisque j'ai déjà trouvé la solution.
_____________________
 
Mes déboires avec les interruptions venaient très vraisemblablement du traitement trop lourd assigné à l'une d'entre elle alors que son intervalle de déclenchement peut tomber à 12 ms.
Mon Arduino s'en trouvait saturé au point de faire n'importe quoi.
 
Je cherche comment optimiser le traitement en question, en en déportant la plus grosse partie hors du traitement de l'impulsion, dans la section qui envoie les données au serveur une fois par minute et que je vais nommer post-traitement pour le différencier du traitement de l'impulsion.
 
Les impulsions en question sont celles de l'anémomètre qui mesure la vitesse du vent.
Chaque impulsion représente 2,4 km/h.
La vitesse du vent vaut donc 2400 / intervalle en ms entre deux impulsions
 
12 ms correspondent à 200 km/h, une vitesse qui j'espère ne sera jamais atteinte ni même approchée, mais j'aime autant ne pas risquer de plafonner les mesures même si mon anémomètre s'envolera sans doute bien avant que le vent atteigne 200 km/s.
 
Chaque minute, je dois obtenir:
 - la vitesse moyenne
 - la vitesse maximale
 
Dans le code actuel, tous ces calculs sont effectués dans le traitement de chaque impulsion. Schématiquement, la vitesse ponctuelle du vent est calculée sur chaque impulsion, elle est additionnée à un double servant ultérieurement à calculer la moyenne pondérée et la vitesse maxi est mise à jour.
C'est beaucoup trop lourd.
 
J'étais donc parti pour que chaque impulsion se contente d'insérer la valeur de millis() dans un tableau.
Le post traitement se chargerait des calculs.
Celui de la vitesse moyenne serait très simple puisqu'il n'utiliserait que la première et la dernière valeur du tableau.
Celui de la vitesse maximale serait à peine plus compliqué puisqu'il parcourrait tout le tableau à la recherche du plus petit intervalle entre deux valeurs.
 
Le hic, c'est que tabler sur un intervalle de 12 ms pendant une minute implique un tableau de 5000 unsigned long et ca dépasse bien sûr la mémoire dédiée aux variables globales.
 
L'intervalle minimal (donnant la vitesse maximale) pourrait être calculé par le traitement des impulsions.
Mais comment calculer la moyenne?
_____________________
 
L'idée qui m'est venue en tapant ce qui précède:
 
Dans le traitement de l'impulsion:
 - mettre à jour une variable contenant l'intervalle mini.
 - stocker dans deux variables le premier et le dernier millis() de la série d'impulsions
 - incrémenter le nombre d'impulsions
 
Dans le post-traitement:
 - la vitesse maxi est calculée directement à partir de l'intervalle mini stocké
 - la vitesse moyenne est calculée à partir de l'intervalle moyen valant (dernier millis() - premier millis())/nb d'impulsions
 
Ca alourdit un poil le traitement de l'impulsion mais en restant à priori dans les clous de ce que peut gérer mon Mega 2560
Le post-traitement s'en trouve lui allégé.
 
Bon, il me reste à le coder pour vérifier que ça fonctionne mais je suis confiant.
Le temps qu'on peut perdre sur un petit bout de code quand même  :pfff:

mood
Publicité
Posté le 24-09-2022 à 17:04:23  profilanswer
 

n°382831
docmaboul
Posté le 24-09-2022 à 17:47:19  profilanswer
 

Lermite a écrit :

et ça fait déjà pas lourd 4 octets  :sweat:  
 
Je pense toutefois à deux moyens d'optimiser mon truc:
 - remplacer les millisecondes en long par des minutes en int
 - ne plus stocker la quantité de pluie mais le nombre d'incrément:
 
Mon pluviomètre émet en effet une impulsion sous les 0.2794 mm d'eau, une valeur à la c.. impossible à arrondir, même à trois chiffres après la virgule.
L'idée est donc de ne stocker que le nombre d'impulsions, et n'appliquer le facteur x 0.2794 qu'au moment d'envoyer les valeurs au PC.
 
Je m'y colle de ce pas...


 
Ca dépend sur quoi on travaille :o
 
J'arrive après la bataille mais c'est contournable ta limite.
 
Si tu prends réellement une valeur toutes les minutes, tu peux calculer l'heure de chaque mesure à partir de son index dans le tableau. Dans ce cas, il faut juste un peu chiader l'attente entre deux mesures pour prendre en compte la durée du traitement (sinon tu attends 60s + le temps du traitement et tu as une dérive).
 
Sinon pour stocker les secondes sur 24 heures, tu as besoin de 17 bits (valeur max =  131 072). Le truc, c'est de les stocker en valeur relative et non pas absolue. Ca t'obligerait à ajouter une petite boucle qui viendrait mettre à jour tous ces temps à chaque nouvelle mesure pour qu'ils soient toujours relatif à maintenant.
 
Ensuite pour la pluie, tu peux aussi définir une valeur max, au pif-ô-mètre je dirais 15 bits, soit 10 mètres de pluie par minute :o
 
Ainsi sur 17 + 15 = 32 bits, tu stockes toute l'information dont tu as besoin et tes données tiennent en moins de 8 Ko. Dans ce cas tu utilises des int, et des opérateurs binaires pour affecter/extraire les valeurs qui vont bien (il suffit de faire des macros et ensuite c'est facile).
 
En ne stockant pas les temps, tu t'en sors avec 16 bits et tu peux même calculer tes données sur 48h :o

Message cité 1 fois
Message édité par docmaboul le 24-09-2022 à 17:57:30
n°382832
Lermite
Posté le 24-09-2022 à 17:58:39  profilanswer
 

docmaboul a écrit :


 
Ca dépend sur quoi on travaille :o
 
J'arrive après la bataille mais c'est contournable ta limite....

Effectivement, concernant le pluviomètre (la flotte), tu arrives après la bataille  :D  
Le traitement de chaque impulsion se contente déjà d'incrémenter le nombre d'impulsions, un simple int qui suffit amplement.
Le post-traitement n'a qu'à multiplier ce nombre d'impulsions par la hauteur d'eau représentée par une impulsion.
 
Des trois impulsions devant être gérées par des interruptions, celle du pluviomètre est la seule qui est assez légère pour ne poser aucun problème.
 
C'est surtout celle de l'anémomètre qui mettait la pagaille, non seulement parce qu'elle se déclenche le plus souvent, mais aussi parce que son traitement était de loin le plus lourd.
C'est ce que je viens de détailler avant la solution qui m'est venue dans le même temps.

n°382837
docmaboul
Posté le 24-09-2022 à 18:22:38  profilanswer
 

Lermite a écrit :

Effectivement, concernant le pluviomètre (la flotte), tu arrives après la bataille  :D  
Le traitement de chaque impulsion se contente déjà d'incrémenter le nombre d'impulsions, un simple int qui suffit amplement.
Le post-traitement n'a qu'à multiplier ce nombre d'impulsions par la hauteur d'eau représentée par une impulsion.


 
Mais tu calcules comment ta moyenne glissante sur 24h du coup ?
 

Citation :

Des trois impulsions devant être gérées par des interruptions, celle du pluviomètre est la seule qui est assez légère pour ne poser aucun problème.
 
C'est surtout celle de l'anémomètre qui mettait la pagaille, non seulement parce qu'elle se déclenche le plus souvent, mais aussi parce que son traitement était de loin le plus lourd.
C'est ce que je viens de détailler avant la solution qui m'est venue dans le même temps.


 
Je viens de lire rapidement. C'est effectivement la bonne logique de stocker de la donnée dans l'interruption et de la traiter plus tard (c'est un modèle producer/consumer en gros). Dans la partie consumer, tu commences par désactiver les interruptions, tu récupères tes données, tu réactives les interruptions, tu traites les données / fais ta vie. Si tu ne fais que copier des données dans la partie où tu désactives les interruptions, ça ne prendra que quelques cycles et tu ne perdras pas en précision.

n°382840
Lermite
Posté le 24-09-2022 à 18:31:04  profilanswer
 

docmaboul a écrit :


 
Mais tu calcules comment ta moyenne glissante sur 24h du coup ?

Le calcul des moyennes glissantes sur 1h et 24h est confié au PC qui reçoit les données.
L'arduino se contente de lui envoyer la flotte par minute, en plus de gérer de son côté le cumul qui se remet à zéro avec un poussoir.
 
Pour l'instant, les données sont transmises via une requête http. La page en question calcule via des requêtes SQL les moyennes glissantes sur 1h et 2h, puis insère le tout dans la BDD.
 
A terme, l'envoi des données devrait se faire directement par une requête SQL et le calcul des moyennes par un trigger, afin notamment d'éviter les requêtes http.

n°382844
docmaboul
Posté le 24-09-2022 à 18:44:48  profilanswer
 

C'est un peu l'arme nucléaire pour tuer une mouche ce système. Mais ça marche, c'est l'essentiel ;)
 
Tu as besoin de laisser ton PC allumé 24h/24 pour d'autres raisons ?

n°382848
Lermite
Posté le 24-09-2022 à 19:02:19  profilanswer
 

docmaboul a écrit :

Tu as besoin de laisser ton PC allumé 24h/24 pour d'autres raisons ?

Ce PC est celui qui fait office de serveur chez moi. Sa config est plus modeste que celui que j'utilise et que j’éteins ou mets en veille régulièrement.
Ce serveur doit tourner 24h/24 puisqu'il gère:
 - des caméras IP
 - serveur http qui ne sert pas qu'à l'Arduino
 - serveur MQTT (domotique/bidouillages honteux (tm))
 - client Bittorrent  :ange:  
 
Si ce PC n'avait que l'Arduino à gérer, j'ajouterais une mémoire flash à l'Arduino pour qu'il puisse y stocker les données en attendant leur rapatriement ultérieur sur PC mais vu que ce dernier est toujours en marche, autant lui balancer les données directement.

n°382857
Lermite
Posté le 24-09-2022 à 20:52:11  profilanswer
 

Rhhhaaa... soit j'ai un bug tellement gros que je ne le vois pas, soit mon Arduino ne sait pas compter.
 
La ligne problématique est celle-ci:
 
windSpeed=2400*anemoNbImps/(msAnemoImps[1]-msAnemoImps[0]);
 
Que l'on peut simplifier en:
a = 2400 * b / c
 
avec b = 239
et c = 59282
a = 72449.0   :heink:  
 
La formule équivaut à celle-ci:
 
a = 2400 / c * b
 
mais avec les mêmes valeurs de b et c, a vaut cette fois 0.0  :pfff:  
 
b et c sont des unsigned long.
a est un float mais même passé en double, j'obtiens les mêmes résultats aberrants  :fou:  
 
Devrais-je farcir la formule de casts?
 
EDIT: Ah oui, avec plein de casts en float, j'ai enfin le résultat attendu  [:tinostar]

Message cité 1 fois
Message édité par Lermite le 24-09-2022 à 20:58:21
n°382859
SuperSic
Posté le 24-09-2022 à 21:17:38  profilanswer
 

Ca craint la chaleur un ESP32 (ou Arduino) ? :??:
J'ai l'impression que l'un des mien est HS (je m'en suis servi comme "support" pour souder mon nouveau PCB donc probablement transmission de chaleur via les PIN), il n'est pas reconnu par Windows.


---------------
"Les soldats vivent. Et se demandent pourquoi." Toubib (La Compagnie noire) | [TU] Pronomoo
n°382861
Lermite
Posté le 24-09-2022 à 21:46:46  profilanswer
 

Tout composant électronique ne supporte la chaleur que dans une mesure qui lui est propre, et les circuits intégrés ne sont pas généralement les plus résistants de ce point de vue.
Une telle coïncidence serait surprenante donc je pense que ça sent le roussi hélas  :sweat:  

n°382862
SuperSic
Posté le 24-09-2022 à 22:28:47  profilanswer
 

C'est pas méchant, c'est pas bien cher et j'ai un ESP32 en rab donc je suis pas bloqué pour avancer.


---------------
"Les soldats vivent. Et se demandent pourquoi." Toubib (La Compagnie noire) | [TU] Pronomoo
n°382873
crazytiti
http://crazytiti.free.fr/
Posté le 25-09-2022 à 11:58:30  profilanswer
 

Oui m'enfin faut quand même y faire gaffe, avec la pandémie les esp32, stm32 et autres petites bidouilles avaient triplé de prix et /ou n'était plus en stock null part (coucou les contrôleurs de vol de drone passés de 15 à 70€ !)

 

Mais bon d'habitude ya un shield en métal sur les ESP32 et puis ça ne crève pas comme ça non plus, tu ne l'aurais pas physiquement abimé ?


Message édité par crazytiti le 25-09-2022 à 11:59:29

---------------
Le PC est une drogue... Téléchargez mes modèles 3D pour que j'ai du filament gratuit :-D https://www.printables.com/fr/@Crazytiti_1456354
n°382881
SuperSic
Posté le 25-09-2022 à 13:19:03  profilanswer
 

Je n'ai pas vérifié s'il fonctionnait avant de souder avec.
 
Je l'ai rebranché ce matin, il a été reconnu par Windows (c'était pas le cas hier soir) et j'ai pu flasher un programme dessus mais là, il est de nouveau plus reconnu par Windows.


---------------
"Les soldats vivent. Et se demandent pourquoi." Toubib (La Compagnie noire) | [TU] Pronomoo
n°382894
crazytiti
http://crazytiti.free.fr/
Posté le 25-09-2022 à 16:38:45  profilanswer
 

Ça sent le port USB foireux ça, essaye un autre cable/port/pc...


Message édité par crazytiti le 25-09-2022 à 16:38:53

---------------
Le PC est une drogue... Téléchargez mes modèles 3D pour que j'ai du filament gratuit :-D https://www.printables.com/fr/@Crazytiti_1456354
n°382906
SuperSic
Posté le 25-09-2022 à 18:25:56  profilanswer
 

J'en doute, le câble/port USB marchent bien avec un autre ESP32.


---------------
"Les soldats vivent. Et se demandent pourquoi." Toubib (La Compagnie noire) | [TU] Pronomoo
n°382909
Natopsi
☄️Just end it already!☄️
Posté le 25-09-2022 à 18:38:55  profilanswer
 

Le quartz de la puce USB série qui a pris un coup de chaud?


---------------
ACH/VDSHFRCoin◈1435mm⚡
n°382921
SuperSic
Posté le 25-09-2022 à 19:23:44  profilanswer
 

Aucune idée mais j'ai quand même bien avancé ce WE :
- soudage de la plaque de prototypage avec les différents éléments (exactement comme le détecteur d'ouverture de porte de garage mais sans la LED rouge)
- perçage du boitier en plastique qui accueille l'ESP32
- adaptation du code (encore celui du détecteur d'ouverture de porte de garage), pas parfait mais ça fait le job
- petite update de la doc avec un schéma pour expliquer où se trouve l'ensemble des câbles/composants
https://i.ibb.co/LkypqkF/esp32-mailbox-schema.png
 
J'ai un peu hésité à ajouter un buzzer pour signaler la réception d'un courrier/colis mais l'ESP étant à la cave, ça n'a pas vraiment d'intérêt.
 
Donc globalement, il ne reste plus qu'à passer le câble sous les pavés au niveau de la porte. Je vais tâcher de le faire avant qu'il fasse trop froid.


---------------
"Les soldats vivent. Et se demandent pourquoi." Toubib (La Compagnie noire) | [TU] Pronomoo
n°382937
Lermite
Posté le 25-09-2022 à 22:38:19  profilanswer
 

J'ai enfin réussi à gérer correctement mon anémomètre (qui convertit la vitesse du vent en impulsions) avec des interruptions.
Il aura notamment fallu alléger à mort le code des interruptions.
Autant c'était facile pour les deux autres capteurs mais pour celui-ci, j'en ai bavé.
 
Finalement, je procède en trois temps:
 - L'interruption qui se contente de stocker la valeur de millis()) dans un tableau en incrémentant son indice.
 - en vrac dans loop() pour vider le tableau en traitant ses valeurs
 - dans le bloc de loop() qui s'exécute à un intervalle d'une minute, qui finalise les calculs et balance les résultat au serveur.
 
A cause de ce tableau, la mémoire disponible pour les variables globales est maintenant squattée à 57% et mon code est une usine à gaz.
 
Je n'ai pas encore pu le tester à fond parce que le vent est particulièrement poussif aujourd'hui. Je ne saurais que demain si mon code ne fait pas fondre l'Arduino vu la météo prévue.
 
Le bénéfice des interruptions est déjà flagrant sur la puissance active consommée, dont la courbe n'est plus constellée d'impulsions manquées  :sol:  
Un exemple avec mon chauffe-eau sur programmateur, dont la courbe est jaune pisse, sans interruption puis avec:
 
https://i.ibb.co/pyhL6P2/Sans-interruption.pnghttps://i.ibb.co/1LnNR4j/Avec-interruption.png


Message édité par Lermite le 25-09-2022 à 22:42:19
n°383140
Lermite
Posté le 27-09-2022 à 23:39:31  profilanswer
 

Pas moyen d'arriver à des interruptions qui fonctionnent nickel  :cry:  
 
Sans ATOMIC_BLOCK dans loop(), ce dernier est perturbé par les interruptions.
Avec des ATOMIC_BLOCK, ce sont les interruptions qui sont perturbées, notamment celle utilisée par millis().
 
N'existerait-il pas un Arduino, EPS-32 ou truc du genre mais multicoeurs, capable d'exécuter au moins une thread en parallèle du code principal?


Message édité par Lermite le 27-09-2022 à 23:44:10
n°383141
crazytiti
http://crazytiti.free.fr/
Posté le 27-09-2022 à 23:55:58  profilanswer
 

Ta mis toute ta fonction loop dans un atomic_block ?
il faut mettre uniquement l'accés aux variable partagées le temps de les copier dans d'autres variables.

Message cité 1 fois
Message édité par crazytiti le 27-09-2022 à 23:56:11

---------------
Le PC est une drogue... Téléchargez mes modèles 3D pour que j'ai du filament gratuit :-D https://www.printables.com/fr/@Crazytiti_1456354
n°383142
Lermite
Posté le 28-09-2022 à 00:00:40  profilanswer
 

crazytiti a écrit :

Ta mis toute ta fonction loop dans un atomic_block ?

Je ne suis pas bourrin à ce point  :D  

crazytiti a écrit :

il faut mettre uniquement l'accés aux variable partagées le temps de les copier dans d'autres variables.

C'est ce que j'ai fait et ça suffit apparemment à mettre la pagaille  :sweat:  
J'avais lu je ne sais plus où que milis() ne fonctionne pas dans une interruption, et c'est peut-être vrai finalement  :??:  

n°383144
Lermite
Posté le 28-09-2022 à 00:18:19  profilanswer
 

Le code relatif à mes deux interruptions, sachant que l'intervalle des impulsions du pluviomètre est grand, au moins d'une dizaine de secondes, et celui du Linky est à peine plus court, de 1,4 secondes quand le chauffe-eau s'ajoute  tout ce qui tourne déjà:

Code :
  1. const int intervLinky = 3000;
  2. long puissA;
  3. unsigned long firstmsImpLinky=0;
  4. volatile unsigned long lastmsImpLinky=0;
  5. volatile int linkyNbImps=0;
  6. void gererPluvio()
  7. {
  8.   pluieInc++;
  9. }
  10. void gererLinky()
  11. {
  12.   lastmsImpLinky=millis();
  13.   linkyNbImps++;
  14. }
  15. void setup()
  16. {
  17.   attachInterrupt(digitalPinToInterrupt(PLUVIOPIN),gererPluvio,FALLING);
  18.   attachInterrupt(digitalPinToInterrupt(LINKYPIN),gererLinky,FALLING); 
  19. }
  20. void loop()
  21. {
  22.   // gestion Linky ――――――――――――――――――――――――――――――――――
  23.   if (linkyNbImps!=0)
  24.   {
  25.     if (lastmsImpLinky!=0)
  26.     {
  27.       if (firstmsImpLinky==0)
  28.         firstmsImpLinky=lastmsImpLinky;
  29.       else 
  30.       {
  31.         unsigned long intervmsLinky=lastmsImpLinky-firstmsImpLinky;
  32.         if (intervmsLinky>=intervLinky)
  33.         {
  34.           ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
  35.           {
  36.             puissA = (float)linkyNbImps * 3600000.0 / float(intervmsLinky);
  37.             firstmsImpLinky=lastmsImpLinky;       
  38.             linkyNbImps=0;
  39.           } 
  40.           Serial.print(puissA);
  41.           Serial.println("W" );
  42.           affLCDPuissA();
  43.           setPuissAHTTP();
  44.         }
  45.       } 
  46.     } 
  47.   }
  48.   if ((ms - lastms) >= intervUpdate) // transmission valeurs une fois par minute
  49.   {
  50.     // gestion pluviomètre ――――――――――――――――――――――――――――――――――
  51.     ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
  52.     {
  53.       pluie = incPluie * pluieInc;
  54.       pluieInc=0;
  55.     } 
  56.     cumulPluie += pluie;  }
  57. }


Message édité par Lermite le 28-09-2022 à 00:44:54
n°383146
docmaboul
Posté le 28-09-2022 à 06:53:10  profilanswer
 

tu peux virer l'atomic block et tenter ce genre de chose ?
 

Code :
  1. noInterrupts();
  2. puissA = (float)linkyNbImps * 3600000.0 / float(intervmsLinky);
  3. firstmsImpLinky=lastmsImpLinky;     
  4. linkyNbImps=0;
  5. interrupts();


 
(idem plus bas)
 
sinon il y a bien un delay systématique à la fin de ta boucle ?

n°383155
Lermite
Posté le 28-09-2022 à 10:09:06  profilanswer
 

docmaboul a écrit :

tu peux virer l'atomic block et tenter ce genre de chose ?
 

Code :
  1. noInterrupts();
  2. puissA = (float)linkyNbImps * 3600000.0 / float(intervmsLinky);
  3. firstmsImpLinky=lastmsImpLinky;     
  4. linkyNbImps=0;
  5. interrupts();


 
(idem plus bas)

:jap:  
Le test est lancé. Verdict d'ici quelques heures.
 

docmaboul a écrit :

sinon il y a bien un delay systématique à la fin de ta boucle ?

Non, aucun delay() directement dans loop() notamment parce que les impulsions de l'anémomètre y sont gérées directement sans interruption, parce que c'était la plus problématique à cause de ses impulsions trop rapprochées (24 ms pour 100 km/h). Lui ne passera sur interruption que si les deux interruptions actuelles fonctionnent nickel, ce qui était loin d'être le cas jusqu'ici.
J'ai même désactivé la mesure de la pression parce que lui nécessitait deux delay().
Des delay() se produisent toujours mais beaucoup plus sporadiquement dans des fonctions appelées par loop(): requêtes NTP, si problème de communication avec le LIDAR, si besoin de reconnecter l'ethernet,...
 
Nb: Je ne vois pas d'objection à poster l'intégralité de mon code mais vu qu'il compte 931 lignes et est toujours aussi illisible, ce serait passablement lourdingue.


Message édité par Lermite le 28-09-2022 à 10:11:15
n°383158
crazytiti
http://crazytiti.free.fr/
Posté le 28-09-2022 à 10:36:14  profilanswer
 

Si je peux me permettre, il faudrait justement éviter des calculs (surtout avec des float) dans la partie sans interrupt.
Ex de

Code :
  1. noInterrupts();
  2.     puissA = (float)linkyNbImps * 3600000.0 / float(intervmsLinky);
  3.     firstmsImpLinky=lastmsImpLinky;   
  4.     linkyNbImps=0;
  5. interrupts();
 

passer à

Code :
  1. noInterrupts();
  2.     VarA = linkyNbImps;
  3.     VarB = intervmsLinky;
  4.     VarC = lastmsImpLinky
  5. interrupts();
  6.     puissA = (float)VarA * 3600000.0 / float(VarB);
  7.     firstmsImpLinky=VarC ;   
  8.     linkyNbImps=0;
 

Nb : ici j'ai considéré que les 3 valeurs étaient accédé en écriture dans le traitement de l'interruption, il faut bien entendu se limiter aux variables nécessaires.

Message cité 2 fois
Message édité par crazytiti le 28-09-2022 à 10:37:43

---------------
Le PC est une drogue... Téléchargez mes modèles 3D pour que j'ai du filament gratuit :-D https://www.printables.com/fr/@Crazytiti_1456354
n°383159
Lermite
Posté le 28-09-2022 à 10:50:23  profilanswer
 

crazytiti a écrit :

Si je peux me permettre, il faudrait justement éviter des calculs (surtout avec des float) dans la partie sans interrupt.
Ex de

Code :
  1. noInterrupts();
  2.     puissA = (float)linkyNbImps * 3600000.0 / float(intervmsLinky);
  3.     firstmsImpLinky=lastmsImpLinky;   
  4.     linkyNbImps=0;
  5. interrupts();


 
passer à  

Code :
  1. noInterrupts();
  2.     VarA = linkyNbImps;
  3.     VarB = intervmsLinky;
  4.     VarC = lastmsImpLinky
  5. interrupts();
  6.     puissA = (float)VarA * 3600000.0 / float(VarB);
  7.     firstmsImpLinky=VarC ;   
  8.     linkyNbImps=0;


 
Nb : ici j'ai considéré que les 3 valeurs étaient accédé en écriture dans le traitement de l'interruption, il faut bien entendu se limiter aux variables nécessaires.

Merci encore  :jap:  
Mais le cas de linkyNbImps me turlupine  :heink:  
C'est une variable utilisée et modifiée par l'interruption.
Selon moi, sa remise à zéro devrait être dans le bloc sans interruption pour éviter les changements croisés de sa valeur.
Autrement dit, le code ne devrait-il pas plutôt être celui-ci?

Code :
  1. noInterrupts();
  2. int linkyNbImpsTemp = linkyNbImps;
  3. unsigned long lastmsImpLinkyTemp = lastmsImpLinky;
  4. linkyNbImps=0;
  5. interrupts();
  6. puissA = (float)linkyNbImpsTemp * 3600000.0 / float(intervmsLinkyTemp);
  7. firstmsImpLinky=lastmsImpLinkyTemp;


 
Oups, plutôt ça:
 

Code :
  1. noInterrupts();
  2.   int linkyNbImpsTemp = linkyNbImps;
  3.   unsigned long lastmsImpLinkyTemp = lastmsImpLinky;
  4.   interrupts();
  5.    if (linkyNbImpsTemp!=0)
  6.   {
  7.     if (lastmsImpLinkyTemp!=0)
  8.     {
  9.       if (firstmsImpLinky==0)
  10.         firstmsImpLinky=lastmsImpLinkyTemp;
  11.       else 
  12.       {
  13.         unsigned long intervmsLinky=lastmsImpLinky-firstmsImpLinky;
  14.         if (intervmsLinky>=intervLinky)
  15.         {
  16.           noInterrupts();
  17.           linkyNbImps=0;
  18.           interrupts();
  19.           puissA = (float)linkyNbImpsTemp * 3600000.0 / float(intervmsLinky);
  20.           firstmsImpLinky=lastmsImpLinkyTemp;       
  21.         } 
  22.         if (puissA<6000)
  23.         {
  24.           Serial.print(puissA);
  25.           Serial.println("W" );
  26.           affLCDPuissA();
  27.           //setPuissASQL();
  28.           setPuissAHTTP();
  29.         } 
  30.       } 
  31.     } 
  32.   }


Message édité par Lermite le 28-09-2022 à 10:54:46
n°383161
crazytiti
http://crazytiti.free.fr/
Posté le 28-09-2022 à 10:55:06  profilanswer
 

Oui toutafait :bounce:

 

Edit ligne 13 ya une erreur sur la variable
mettre lastmsImpLinkyTemp au lieu de lastmsImpLinky


Message édité par crazytiti le 28-09-2022 à 10:57:28

---------------
Le PC est une drogue... Téléchargez mes modèles 3D pour que j'ai du filament gratuit :-D https://www.printables.com/fr/@Crazytiti_1456354
n°383165
docmaboul
Posté le 28-09-2022 à 11:07:42  profilanswer
 

crazytiti a écrit :

Si je peux me permettre, il faudrait justement éviter des calculs (surtout avec des float) dans la partie sans interrupt.


 
Il faut éviter quelque chose de long mais deux casts, une multiplication et une division, c'est rien du tout.
 
Après sur le principe tu as raison.

n°383175
Lermite
Posté le 28-09-2022 à 12:41:03  profilanswer
 

C'est pas gagné  :sweat:  
 

11:55:42.945 -> 426W
11:55:51.322 -> 427W
11:55:59.795 -> 424W
11:56:09.152 -> 8854W  <=  navak!!
11:56:28.355 -> 375W
11:56:37.909 -> 376W

n°383177
docmaboul
Posté le 28-09-2022 à 12:53:58  profilanswer
 

tu peux mettre ton code sur un dépôt github qu'on puisse regarder s'il n'y a pas un autre souci ?

 

edit: aussi pour la donnée qui est erronée, affiche à chaque fois linkyNbImpsTemp et intervmsLinky qu'on sache laquelle à un problème

Message cité 1 fois
Message édité par docmaboul le 28-09-2022 à 12:56:28
n°383180
Lermite
Posté le 28-09-2022 à 13:15:39  profilanswer
 

docmaboul a écrit :

tu peux mettre ton code sur un dépôt github qu'on puisse regarder s'il n'y a pas un autre souci ?
 
edit: aussi pour la donnée qui est erronée, affiche à chaque fois linkyNbImpsTemp et intervmsLinky qu'on sache laquelle à un problème


Mon code est sur Github mais je préfère ne vous donner le lien que dans quelques heures.
J'ai en effet un doute sur l'instant où est apparue la valeur fantaisiste. Elle pourrait être antérieure à la dernière version du code, d'où l'intérêt de le laisser pédaler quelques heures pour voir si le bug revient à la charge avec plus de détails dans le log.
 

n°383187
Lermite
Posté le 28-09-2022 à 14:34:21  profilanswer
 

Le bug est toujours présent hélas:
 
13:48:25.249 -> 448W   linkyNbImpsTemp = 1   intervmsLinky = 8027
13:48:33.279 -> 447W   linkyNbImpsTemp = 1   intervmsLinky = 8052
13:48:41.199 -> 454W   linkyNbImpsTemp = 1   intervmsLinky = 7927
13:48:48.239 -> 11283W   linkyNbImpsTemp = 22   intervmsLinky = 7019  <= WTF
13:48:58.129 -> 3630W   linkyNbImpsTemp = 10   intervmsLinky = 9915    <=  
13:49:16.250 -> 397W   linkyNbImpsTemp = 1   intervmsLinky = 9060
13:49:25.369 -> 395W   linkyNbImpsTemp = 1   intervmsLinky = 9106
 
Si vous avez les nerfs assez solide pour affronter mon code hideux:
 
https://github.com/LermiteFR/Weathe [...] gged_Linky
 
C'est la première fois que j'utilise Github pour publier du code donc si ce lien ne fonctionne pas, n'hésitez pas à râler.

mood
Publicité
Posté le   profilanswer
 

 Page :   1  2  3  4  5  ..  240  241  242  ..  278  279  280  281  282  283

Aller à :
Ajouter une réponse
 

Sujets relatifs
* Réparations de vos appareils électroniques & electromenager * 
Plus de sujets relatifs à : [arduino] Topic Unique blabla @ Arduino


Copyright © 1997-2025 Groupe LDLC (Signaler un contenu illicite / Données personnelles)