Olduvaï
Vous souhaitez réagir à ce message ? Créez un compte en quelques clics ou connectez-vous pour continuer.
Le Deal du moment :
TCL C74 Series 55C743 – TV 55” 4K QLED 144 ...
Voir le deal
499 €

Arduino, programmation, résilience et librairie Olduvaï

5 participants

Page 1 sur 2 1, 2  Suivant

Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Arduino, programmation, résilience et librairie Olduvaï

Message par tarsonis Mar 9 Aoû 2022 - 12:38

Salut à tous,
Oui, vous avez bien lu, c'est bien un sujet sur l'Arduino.

Je parcourais les différents posts où le sujet était évoqué et je me disais qu'il fallait actualiser mon propos.

Depuis quelques temps, je cherchais un moyen de proposer des fonctions un peu plus évoluées sur le forum afin de coller à nos éventuels besoins.
Théoriquement, quasiment toutes les fonctions sont réalisables avec des circuits analogiques (transistors, résistances, tec), aucun souci pour les quelques-uns que nous sommes à concevoir des schémas et fabriquer, mais cela devient complexe pour la plupart des lecteurs, et peu polyvalent.

Par exemple, je planchais sur mon proto de déshydrateur/tourailleur solaire (ici [Brassage] Faire sa bière résiliente)
C'est relativement "simple", avec des comparateurs à transistor à ajuster, mais je doute encore de sa faisabilité sans un minimum de compétences en électronique.

J'envisageais depuis quelques temps d'ouvrir une section avec les microcontrôleurs PIC type 16F, mais ils requièrent une sacrée dose de formation, une carte de programmation (qui commence à se faire rare) et un très bon niveau en assembleur. La programmation avec MPLAB étant vraiment rude, surtout si on compare avec le langage C. Pour obtenir ce que je cherchais, il fallait compter plusieurs heures de développement.

Le point entre ces deux univers est l'Arduino, qui est une carte avec microcontrôleur, mais également les garnitures qui permettent de la faire communiquer et la programmer avec un ordinateur. Finalement, avec l'interface sur Ordi, on ne code qu'en C en comprenant les quelques spécificités du module et ça roule en quelques minutes. De la plupart des cartes que j'ai étudiées, le code source est compatible de l'une à l'autre, d'autant plus si on utilise les variables prédéfinies à la compilation.

Là où je pense que l'on a passé un point de transition, c'est sur la démocratisation des différentes cartes Arduino et la possibilité d'avoir des clones, non officiels, mais 100% fonctionnels.
On trouve en effet à présent des modules à quelques euros... c'est à dire beaucoup moins que les PIC, voire certains circuits de la série CDxxxx dont je parle sur les topics électroniques. Un bon indicateur de disponibilité c'est le site d'occasion. Il y a 5 ans, il était assez rare d'en trouver tandis que maintenant cela a quasi pignon sur rue et on a plusieurs centaines d'annonces à moins de 20E.

L'investissement est donc vraiment minime pour un potentiel assez intéressant dans nos thématiques.

Ici, je pense développer autour de l'Arduino Nano, dont voici un clone à 2€ :
Arduino, programmation, résilience et librairie Olduvaï Capt1023


Autre point sans doute d'intérêt : les plus jeunes sont sans doute beaucoup plus familiers avec cette techno qu'un vieux croûton comme moi. Voici donc un topic plus orienté vers les concernés clind'oeil

Ce que je propose :
- tous les intéressés sont invités à partager leurs questions/projets/améliorations ici.
- on crée une bibliothèque "Olduvai" Open Source, orientée résilience sur la plateforme Arduino qui permettra à quiconque d'avoir accès aux fonctions que nous aurions créées. Éventuellement un répertoire spécial sur Oldu.fr où je déposerai les fichiers sources.

Exemple de fonctions : monitoring, détecteur de trop-plein de cuves, de pompage, de mise en contact, d'alarme, de sécheresse du sols, de charge des accus, température, pollution sur capteur, programme de compteur, simple ou évolué comme un Geiger (je suis sur soft Geiger/Radiamètre/Dosimètre avec suivi sur 50 jours), décodeur de morse pour ondes courtes, etc.

Dans un registre un peu différent, il est possible de simuler pas mal de fonctions logiques (ET, OU, OU-Ex, etc), de convertir un signal analogique en numérique et réciproquement (je planche sur un ECG).
Enfin, on n'oublie pas nos chers enfants avec la possibilité de créer des jeux interactifs. Je travaille sur une version de Simon avec plusieurs niveaux de difficultés (vitesse, nombre de couleurs, etc...).



Quelques ressources

Je trouve que la plupart des cours et tutos sont sympathiques pour démarrer. Pour les jeunes, "Programmer en Arduino en s'amusant" d'Olivier Engler sera une bonne intro à la programmation et l'électronique, pour les moins jeunes, "Arduino pour les nuls" ou "Le Grand livre d'Arduino" me semblent de bonnes bases. N'hésitez pas à ajouter vos références.


Premier post, en guise d'introduction pour entrer dans le concret : La frugalité des variables.



Dans le cadre de nos thématiques et dans une optique de résilience, je trouve que les codes sont très rarement optimisés, bien que les Arduino soient très limités en mémoire RAM (2ko sur Nano) et flash (32ko).
Cela convient pour la plupart des projets, mais il serait amha intéressant de prendre de bonnes habitudes dès le départ si l'on souhaite créer et partager des projets dans un cadre de résilience-frugalité de sorte à ce qu'un programme écrit pour une bête de guerre soit facilement adapté à un module plus limité.

Exemple, voici les déclarations de mon programme hyper simple de veilleuse RGB :

Code:
const byte ledBlue = 9; // broche PWM pour led bleue
const byte ledRed = 10; // broche PWM pour led rouge
const byte ledGreen = 11; // broche PWM pour led verte

// Composantes de départ de gradient
byte startBlue=0;  
byte startRed=0;  
byte startGreen=0;

// Composantes d'arrivée de gradient
byte endBlue=0;
byte endRed=0;
byte endGreen=0;

byte gradient=0; // variable qui va réaliser un gradient progressif de 0 à 255

Lors de la compilation, on obtient la taille mémoire occupée par le programme et les variables :
Le croquis utilise 2032 octets (6%) de l'espace de stockage de programmes. Le maximum est de 30720 octets.
Les variables globales utilisent 20 octets (0%) de mémoire dynamique, ce qui laisse 2028 octets pour les variables locales. Le maximum est de 2048 octets.

Si j'avais codé ça à la manière des tutos usuels, j'aurais pris des variables 'int' (codées sur 2 octets, qui manipule des nombres entre -32768 et 32767) à la place de 'byte' (codé sur 1 octet, qui manipule des nombres entre 0 et 255)

Code:
int ledBlue = 9; // broche PWM pour led bleue
int ledRed = 10; // broche PWM pour led rouge
int ledGreen = 11; // broche PWM pour led verte

// Composantes de départ de gradient
int startBlue=0;  
int startRed=0;  
int startGreen=0;

// Composantes d'arrivée de gradient
int endBlue=0;
int endRed=0;
int endGreen=0;

int gradient=0; // variable qui va réaliser un gradient progressif de 0 à 255

La différence se manifeste lors de la compilation :

Le croquis utilise 2074 octets (6%) de l'espace de stockage de programmes. Le maximum est de 30720 octets.
Les variables globales utilisent 27 octets (1%) de mémoire dynamique, ce qui laisse 2021 octets pour les variables locales. Le maximum est de 2048 octets.

On voit que les variables globales prennent 35% de mémoire en plus (7 octets), tandis que les constantes ajoutent 42 octets de place prise par le programme.

Cela semble représenter relativement peu de mémoire globalement, mais il s'agit ici d'un exemple rudimentaire pour laquelle le simple choix du type de variable adaptée à son usage a une influence sur la consommation des ressources disponibles, alors que les deux programmes fonctionnent strictement de la même manière.
Accessoirement, le code est un chouïa plus rapide sur la version optimisée, de l'ordre de 10% sur une fonction hyper simple de test conditionnel. Cela pourra montrer quelques différences de performances dans l'analyse du signal (compteur Geiger par ex avec des impulsions de quelques ms).

Donc pour tout ce qui est de l'ordre du brochage Arduino ou de fonctions qui ne dépassent pas 255, byte est à préférer.

Optimiser le code est toujours une bonne idée, mais cela permet aussi d'avoir plus de largesse concernant un point très particulier dans nos thématiques :

- la possibilité de cumuler plusieurs programmes, qui s'activent uniquement selon des signaux spécifiques. Cela évite d'avoir à reprogrammer la carte sans arrêt et permet d’utiliser chaque fonction dans la brousse selon le besoin du moment; par exemple : remplissage des cuves puis réactivation du système d'irrigation un peu plus loin

- enfin, la capacité de cacher du code et des fonctions dans un programme en apparence anodin.
Ici, mon programme de veilleuse led RGB diffuse une petite lumière d'ambiance quand la luminosité de la pièce est insuffisante. Mais cinq impulsions rapprochées sur un Pin spécifique active un code de monitoring, qui envoie un signal sur une broche annexe qui avertit que la lumière est allumée dans la pièce.

________________________________________________________
L'expérience est une lumière qui n'éclaire que ceux qu'elle a déjà brûlés. Cédric Dassas


甩葱歌 - 古箏 - Distant Pulsar - Un Mauvais Fils - 25 Years of Zelda - Machinarium - Récapitulatif des projets électroniques - [Chroniques du Bunker de L'Apocalypse] - Projet Geiger - Culture ethnobotanique en France
tarsonis
tarsonis
Administrateur

Masculin Nombre de messages : 10680
Age : 37
Localisation : Grand Est
Loisirs : Trek, ethnobotanique, électronique DIY, nucléaire, médecine, post apo.
Date d'inscription : 21/05/2008

KrAvEn, victor81, Le castor bricoleur, pvo12 et Encatimini aiment ce message

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par Encatimini Mar 9 Aoû 2022 - 16:30

Tout à fait d'accord.

J'imagine aussi une liste de composants dans un format unique de tableau qui pourrait permettre de choisir ses projets et commander ses composants avec certitude.
Encatimini
Encatimini
Membre

Masculin Nombre de messages : 138
Date d'inscription : 20/01/2021

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par tarsonis Mar 9 Aoû 2022 - 16:59

Bonne idée, avec les plages de valeurs admissibles dans le cas où l'on n'aurait pas les bons composants sous la main.

Je réfléchis également à une manière de lier un schéma au fichier .ino autre qu'en format texte en commentaire. Sur Oldu.fr c'est facile mais dans une lib ?

________________________________________________________
L'expérience est une lumière qui n'éclaire que ceux qu'elle a déjà brûlés. Cédric Dassas


甩葱歌 - 古箏 - Distant Pulsar - Un Mauvais Fils - 25 Years of Zelda - Machinarium - Récapitulatif des projets électroniques - [Chroniques du Bunker de L'Apocalypse] - Projet Geiger - Culture ethnobotanique en France
tarsonis
tarsonis
Administrateur

Masculin Nombre de messages : 10680
Age : 37
Localisation : Grand Est
Loisirs : Trek, ethnobotanique, électronique DIY, nucléaire, médecine, post apo.
Date d'inscription : 21/05/2008

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par Encatimini Mar 9 Aoû 2022 - 22:52

Il existe aussi les ESP6288 qui sont comme les Arduino mais avec le wifi intégré.
Encatimini
Encatimini
Membre

Masculin Nombre de messages : 138
Date d'inscription : 20/01/2021

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par Canis Lupus Mer 10 Aoû 2022 - 13:25

Intéressant sujet ! Est-ce que selon vous on peut envisager la domotique d'une cabane ayant accès au réseau 4G avec un Raspberry PI ayant des Arduino "esclaves" ?

________________________________________________________
Canis Lupus
Canis Lupus
Membre fondateur

Masculin Nombre de messages : 4477
Age : 38
Date d'inscription : 16/11/2006

http://fullspectrumpreparedness.blogspot.com/

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par tarsonis Mer 10 Aoû 2022 - 15:48

Hello,
perso je vais surtout développer sur le forum avec Arduino nano, amha la plateforme la plus facile à manipuler, notamment l'accès rapide breadboard.
Mais n'hésitez pas à partager/développer vos projets ! clind'oeil

________________________________________________________
L'expérience est une lumière qui n'éclaire que ceux qu'elle a déjà brûlés. Cédric Dassas


甩葱歌 - 古箏 - Distant Pulsar - Un Mauvais Fils - 25 Years of Zelda - Machinarium - Récapitulatif des projets électroniques - [Chroniques du Bunker de L'Apocalypse] - Projet Geiger - Culture ethnobotanique en France
tarsonis
tarsonis
Administrateur

Masculin Nombre de messages : 10680
Age : 37
Localisation : Grand Est
Loisirs : Trek, ethnobotanique, électronique DIY, nucléaire, médecine, post apo.
Date d'inscription : 21/05/2008

Ash et victor81 aiment ce message

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par Encatimini Mer 10 Aoû 2022 - 19:07

Je pense que l'idéal serait de faire un cahier des charges par rapport aux besoins possibles.
Ensuite on voit si c'est possible avec un Atmega328 (nom du processeur d'un Arduino nano) ou Raspberry (micro pc) ou autre.

Une fois le besoin et le matériel définis, chacun peut faire sa partie.
Encatimini
Encatimini
Membre

Masculin Nombre de messages : 138
Date d'inscription : 20/01/2021

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par Encatimini Mer 10 Aoû 2022 - 19:15

Canis Lupus a écrit:Intéressant sujet ! Est-ce que selon vous on peut envisager la domotique d'une cabane ayant accès au réseau 4G avec un Raspberry PI ayant des Arduino "esclaves" ?

Perso je ferais ça avec un Raspberry, des modules relais chacon en 333 ou une carte 16 relais 12V/220v 16A avec octocoupleurs, un arduino nano pour la commande par radio en RF module, un module 4G, le tout piloté par domoticz.

C'est ce qui consomme le moins de courant.
 
C'est ce que j'ai fait chez moi excepté le 4G.

Mais on sort du thème du topic.....
Encatimini
Encatimini
Membre

Masculin Nombre de messages : 138
Date d'inscription : 20/01/2021

Canis Lupus et victor81 aiment ce message

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par victor81 Mer 10 Aoû 2022 - 19:43

HS:en ce qui concerne les pin du raspberry et domoticz, je ne suis pas arrivé (ou plutot pa su comprendre comment, malgré les tutos) a les ouvrir.
si tu a une methode simple....
victor81
victor81
Membre Premium

Masculin Nombre de messages : 1127
Localisation : catharn
Loisirs : detection, culture de plantes medicinales
Date d'inscription : 13/06/2012

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par Encatimini Mer 10 Aoû 2022 - 22:51

HS Il n'y a pas de moyen simple.

Je te conseille de commencer à jouer avec wiringpi pour allumer une lampe en ligne de commande.
A savoir que la numérotation des pin est différente.
gpio

Je te conseille aussi ces deux tutos pour comprendre.

wiring jusqu'a la minute 7
gpio dans domoticz

Ensuite quand tu as compris le concept tu pourras passer sur domoticz sans problèmes.
Il restera un petit problème à régler en cas de reset du courant du raspberry, les gpio seront sur on, mais si tu as compris tu trouveras la parade.
Encatimini
Encatimini
Membre

Masculin Nombre de messages : 138
Date d'inscription : 20/01/2021

victor81 aime ce message

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par Ash Ven 19 Aoû 2022 - 22:50

Faut que je me sorte les d* du c* pour m'en faire un automate de pilotage d'ici quelques mois...

On verra ce qui en sortira Smile

________________________________________________________
...N'est pas mort ce qui à jamais dort et au cours des ères peut mourir même la Mort... Briarée-Erèbe
Ash
Ash
Membre Premium

Masculin Nombre de messages : 5915
Age : 38
Localisation : Stairway to heavens (57)
Date d'inscription : 02/10/2008

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par Encatimini Ven 19 Aoû 2022 - 23:16

Moi j'emploie un Raspberry, avec une carte 16 relais avec optocoupleurs et un mini-routeur pour faire la connexion wifi. 

ça me permet de gérer les pompes et uv de l'étang et l'éclairage de tout.

Le tout avec domoticz et senseurs température, humidité et lumière.

Option, je récolte les données de mon onduleur hybride.

Le tout un peu remixé peut permettre en mode dégradé de gérer les consommateurs selon la production solaire ou le niveau des batteries (j'ai tout mis dans un coffre transportable avec des prises 16A)
Encatimini
Encatimini
Membre

Masculin Nombre de messages : 138
Date d'inscription : 20/01/2021

Canis Lupus aime ce message

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Arduino et Prescaler : modifier la fréquence du CPU

Message par tarsonis Mer 24 Aoû 2022 - 12:14

Salut à tous !

Petit post relativement simple pour aborder l'Arduino, mais directement dans nos thématiques : la consommation du module.
Je ne vais parler que d'un tout petit changement logiciel, bien qu'il soit également possible d'améliorer au niveau matériel (si on alimente le circuit en 3,3V, dessouder la led Power, etc) ou programmation via les différents modes de veille.

La plupart des cartes ont une consommation minimum, que ce soit "au repos" ou quand un programme standard tourne. Pour le nano, elle est d'environ 25mA.
Cela s'explique par le cadençage du microprocesseur (CPU) à 16MHz. Il exécute quasiment autant d’instructions par secondes, mais c'est en réalité bien plus que nécessaire dans la plupart des applications.

Tout comme il est possible d'overclocker (surfréquencer) un CPU pour le faire tourner au dessus de sa fréquence de base, on peut le downclocker (sous-fréquencer), afin de réduire sa consommation. C'est une technique assez fréquente avec les PIC.

C'est ce que l'on va faire ici avec le Prescaler de l'Arduino.

Très sommairement, il s'agit d'un diviseur de fréquence en sortie de l'oscillateur. Plus on la divise, plus on réduit la fréquence de fonctionnement du CPU, donc la consommation.

Le Prescaler peut être appelé à n'importe quel moment dans un programme, via l'instruction CLKPR (Clock Prescale Register) avec l'ATmega328P (Nano, Uno, etc.)

Code:
CLKPR = 0b10000000; // Activation du prescaler

Il faut ensuite rapidement définir son niveau (dans un laps de 4 cycles d'horloges, donc il est préférable de coller la commande tout de suite après : avec les quatre derniers bits :

Code:

//CLKPR = 0b00000000; //Division par 1
//CLKPR = 0b00000001; //Division par 2
//CLKPR = 0b00000010; //Division par 4
//CLKPR = 0b00000011; //Division par 8
//CLKPR = 0b00000100; //Division par 16
//CLKPR = 0b00000101; //Division par 32
//CLKPR = 0b00000110; //Division par 64
//CLKPR = 0b00000111; //Division par 128
//CLKPR = 0b00001000; //Division par 256

Impacts sur le code :

Il faut faire attention, car cette commande modifie la fréquence de fonctionnement en amont. Donc toutes les fonctions qui l'utilisent, telles que delay(), timer() ou encore millis() ainsi que le moniteur série vont être influencés. Il faut donc faire attention si on utilise des durées dans un programme.

Par exemple delay(4096) va marquer une pause de 4096ms. Mais si on divise la fréquence par 2, cette commande va générer une pause doublée (8192ms), si on divise par 256, on va obtenir une pause de 1048 secondes !
Il peut être intéressant de définir un facteur diviseur afin d'adapter le code, par exemple delay(4096/facteurCPU) ou alors tout coder en dur.

J'ai voulu tester dans quelle mesure ce changement modifie la conso.

Voici le programme qui teste chaque mode en laissant environ 4 secondes entre chaque changement. Notez que le dernier delay(16) fonctionne avec un prescaler de 256, donc est équivalent à une delay (16*256) donc on a bien delay(4096) sans prescaler.

Code:
void loop()  
{

delay(4096);

CLKPR = 0b10000000; //Activation du prescaler
CLKPR = 0b00000000; //Division par 1

delay(4096);

CLKPR = 0b10000000; //Activation du prescaler
CLKPR = 0b00000001; //Division par 2

delay(2048);

CLKPR = 0b10000000; //Activation du prescaler
CLKPR = 0b00000010; //Division par 4

delay(1024);

CLKPR = 0b10000000; //Activation du prescaler
CLKPR = 0b00000011; //Division par 8

delay(512);

CLKPR = 0b10000000; //Activation du prescaler
CLKPR = 0b00000100; //Division par 16

delay(256);

CLKPR = 0b10000000; //Activation du prescaler
CLKPR = 0b00000101; //Division par 32

delay(128);

CLKPR = 0b10000000; //Activation du prescaler
CLKPR = 0b00000110; //Division par 64

delay(64);

CLKPR = 0b10000000; //Activation du prescaler
CLKPR = 0b00000111; //Division par 128

delay(32);

CLKPR = 0b10000000; //Activation du prescaler
CLKPR = 0b00001000; //Division par 256

delay(16);

// on fait clignoter la Led afin de signaler la fin de la boucle.
digitalWrite(ledPin, HIGH);
delay(1);
digitalWrite(ledPin, LOW);
delay(1);
digitalWrite(ledPin, HIGH);
delay(1);
digitalWrite(ledPin, LOW);
delay(1);
digitalWrite(ledPin, HIGH);
delay(1);
digitalWrite(ledPin, LOW);
}

On notera que la fréquence peut être modifiée à tout moment si on rappelle le Prescaler. Il est donc possible de faire tourner un bout de code à la fréquence souhaitée selon le besoin.

Résultats :

Arduino, programmation, résilience et librairie Olduvaï Capt1024

On voit qu'aux alentours de 1MHz, on divise presque la consommation par deux pour tomber à 13mA. Au delà, on diminue encore un peu, mais ce n'est pas vraiment probant. Au bout du test, à 62,5kHz la carte consomme 10mA, à cause de la Led Power et des différents modules.

Pour tous les projets qui tournent sur pile (notamment la maigre 9V) ou batterie, cette simple modification du prescaler permet au moins de doubler l'autonomie sur la plupart des programmes

Donc pour le code à ajouter dans setup() :

Code:

CLKPR = 0b10000000; //Activation du prescaler
CLKPR = 0b00000100; //Division de la fréquence d'Horloge par 16

________________________________________________________
L'expérience est une lumière qui n'éclaire que ceux qu'elle a déjà brûlés. Cédric Dassas


甩葱歌 - 古箏 - Distant Pulsar - Un Mauvais Fils - 25 Years of Zelda - Machinarium - Récapitulatif des projets électroniques - [Chroniques du Bunker de L'Apocalypse] - Projet Geiger - Culture ethnobotanique en France
tarsonis
tarsonis
Administrateur

Masculin Nombre de messages : 10680
Age : 37
Localisation : Grand Est
Loisirs : Trek, ethnobotanique, électronique DIY, nucléaire, médecine, post apo.
Date d'inscription : 21/05/2008

Canis Lupus, Ash, Nadia et pvo12 aiment ce message

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par tarsonis Jeu 25 Aoû 2022 - 11:53

Salut à tous,
alors premier projet, de petite envergure afin de prendre en main la bête.

J'ai hésité entre plusieurs développements, qui ne s'excluent pas nécessairement :
- un programme par fonction
- un programme avec sélecteur de fonction sur l'une des entrées analogiques pour choisir quel morceau on utilise, type :

1) Détecteur de circuit fermé (trop plein),
2) détecteur de circuit ouvert (alarme ou cuve vide),
3) capteur de température, etc.

- un programme avec toutes les fonctions, qui s'activent uniquement si on branche le capteur en entrée.

J'ai choisi - pour l'instant - la dernière possibilité afin de ne pas "consommer" une entrée juste pour sélectionner un truc, et pour ne pas à avoir à retransférer le programme entre chaque changement d'utilisation. Je verrai pour scinder tout ça dans une lib Olduvai.cpp et .h à l'occasion.

En gros, voici un programme qui prend en charge - pour l'instant- quatre capteurs :

Sur l'entrée A1 :
Mode Circuit fermé ou capteur avec seuil ascendant, qui peut être utilisé pour la détection d'un trop-plein avec un capteur d'eau (progressif, avec seuil), de luminosité (résistance qui diminue), etc. Ou une alarme quand deux conducteurs sont reliés (fils ou contact à lames souples), donc en mode ON/OFF.

Il y a une résistance pulldown de 15k avec un seuil montant de 100. Cela signifie en gros que le montage va se déclencher quand on aura environ 500mV sur A1, soit une résistance d'environ 150k (modulo toutes les résistances parasites).
On peut modifier le seuil pour le rendre plus ou moins sensible.

Pour les détails concernant le pont diviseur de tension, voir le post Circuits Nomades

Sur l'entrée A0 :
Mode circuit ouvert ou capteur avec seuil descendant.
Fonctionnement inverse : on détecte quand un capteur passe en dessous d'un seuil, par exemple indicateur de sécheresse (résistance qui augmente) ou de bas niveau de cuve, de luminosité, etc. ou alarme quand le circuit est ouvert (contact entre deux conducteurs coupés, plus fréquent).

Il y a une résistance pullup de 15k avec un seuil descendant de 100. Cela signifie en gros que le montage va se déclencher quand on aura environ 500mV sur A0, soit une résistance d'environ 1,5k (modulo toutes les résistances parasites) pour le capteur descendant. Ici il faut une résistance beaucoup plus faible en niveau bas car une jauge résistive peut rester conductrice avec un résidu d'humidité.

On peut modifier le seuil pour le rendre plus ou moins sensible.



Le programme active la sortie outPin (la Led L de la carte, sur 13), permettant de piloter un buzzer et une sorte avec signal sonore généré sur 9 (juste besoin d'un haut parleur) selon l'état de A0 ou A1

Monitoring A0/A1 :
Le signal analogique d'entrée prend une valeur entre 0 et 1023. Chaque entrée est découplée avec sa résistance de pull afin de maintenir le potentiel fixe, même en l'absence de capteur.

Une fois le seuil (descendant sur A0, montant sur A1) franchi, le signal est actif jusqu'à ce que l'on presse sur le bouton stopPin (détecte un signal HIGH sur l'entré stopPin). On peut mettre en commentaire cette ligne pour préférer un reset de l'Arduino.

Il est possible d'économiser quelques résistances externes en utilisant les pullup de la carte, mais cela complique un peu le montage car leur valeur est un peu aléatoire sur les clones de cartes.

Sur l'entrée A2 :
J'y ai collé mon programme pour le séchoir solaire sur une base de thermistance un ventilateur (ou ce qu'on veut, piloté sur Pin 4). Quand la température du séchoir dépasse x°C le ventilateur se met en route. afin de ne pas obtenir un four.
La valeur d'arrêt (inférieure de quelques °C) est amha nécessaire afin de ne pas provoquer des oscillations avec déclenchements intempestifs.
C'est une base pourra être récupérée pour le tourailleur avec double valeurs de seuil et qui peut évoluer avec un fonctionnement sur panneau solaire.


Il y a deux alarmes possibles :
- si vous avez un buzzer, cad un module qui génère lui-même un signal sonore quand il est alimenté, il suffit de le relier à la pin outPin (LED_BUILTIN, donc 13 sur nano) avec une résistance de limitation et 200 Ohms.
- si vous n'avez que des petit haut-parleurs, alors il y a un signal généré sur la pin 9 de quelques centaines de Hz. Idem il suffit d'y relier le HP avec une résistance limitatrice.

Le restart de l'alarme est suivi d'une latence de quelques secondes, afin de remettre les capteurs si besoin (et pour les tests) et éviter les déclenchements à répétition.

Température sur A2 :
Il y a une fonction de calibration de la thermistance qui est prévue par le programme car la plupart des CTN ont des courbes différentes, si bien qu'il est difficile de prédire le comportement.
Je propose une fonction qui renvoie sur le Moniteur Série la valeur entre 0 et 1023 de l'entrée A2, que vous ferez correspondre à la température prise en plaçant un thermomètre juste à côté. Quand vous aurez la correspondance °C / sensorTempValue, vous pourrez modifier le code source pour reporter les valeurs de seuil avec temperatureSeuilVentilation et temperatureSeuilArret, et passer en commentaire la fonction calibrageCTN() qui n'est plus utile.

Le code : J'ai hésité à appeler le programme malabar.ino vu qu'il est destiné à devenir de plus en plus trappu. Mais je vais me contenter de titan.ino afin d'éviter les soucis de marque clind'oeil



Code:
/*  
 *   Programme de monitoring des entrées A0, A1, A2 et A3
 *   ---
 *  A1
 *  Mode Circuit fermé ou capteur avec seuil ascendant
 *  Peut être utilisé pour la détection d'un trop-plein avec un capteur d'eau (progressif, avec seuil), de luminosité, etc
 *  ou une alarme quand deux conducteurs sont reliés (fils ou contact à lames souples), donc en mode ON/OFF
 *  ----
 *  A0
 *  Mode circuit ouvert ou capteur avec seuil descendant.
 *  Fonctionnement inverse : on détecte quand un capteur passe en dessous d'un seuil, par exemple indicateur de sécheresse ou de bas niveau de cuve,
 *  ou alarme quand le circuit est ouvert (contact entre deux conducteurs coupés).
 *  
 *  ---
 *  Extinction
 *  Une fois le seuil franchi (dans le cas d'une sonde humidité, c'est progressif, sinon c'est plutôt ON/OFF, le signal est actif jusqu'à ce que
 *  l'on détecte un signal HIGH sur l'entré stopPin. On peut mettre en commentaire cette ligne pour préférer un reset de l'arduino.
 *  
 *  Il est possible d'économiser les résistances extrnes en utilisant les pullup de la carte, mais cela complique un peu car leur valeur est un peu aléatoire sur les clones de cartes.
 *  
 *  ---
 *  A2 Sonde de température avec seuil de mise en marche de ventilation et seuil de mise à l'arrêt
 *  
 *  ---
 *  
 *  A3
 *  Jauge de batterie
 *  0-1023-> 0-5V
 *  
 *  Entrée sur pont diviseur.
 *  10k pulldown
 *  Sortie série pour l'instant. Monitoring LCD pour la suite
 *  Sera adapté pour mesurer jusqu'à 30V avec entrée protégée contre les surtensions.
 *  
 *  
 *  5/08/2022 - Dernière édition 25/08/2022
 *  Tarsonis
 *  Projet Olduvaï
 *
 */

// Bloc concernant le capteur humidité/sécheresse
const byte sensorPinUp = A1;             // (pin 15 sur nano) Entrée du capteur d'eau analogique pour monitorer avec un seuil.
const byte sensorPinDown = A0;             // (pin 14 sur nano) Entrée du capteur d'eau analogique pour monitorer avec un seuil.
const byte stopPin= 2;                 // bouton permettant de revenir à la normale, en cas de test. Un peu facultatif VS reset mais pratique pour les tests.
const byte outPin = LED_BUILTIN;      // Sortie sur Led circuit (pour y coller un buzzer), 13 sur la plupart des plateformes
const byte outPinSound = 9;           // sortie sonore avec tone()
unsigned int sensorValueUp = 0;                  // variable pour stoker la valeur du capteur monta
unsigned int sensorValueDown = 1023;             // variable pour stoker la valeur du capteur.
const unsigned int seuilUp = 100;  // seuil de notre capteur entre 0 (0V) et 1023 (5V)
const unsigned int seuilDown = 800;  // seuil de notre capteur entre 0 (0V) et 1023 (5V)


// Bloc concenrnant le capteur de température/sécheur
const byte sensorPinTemp = A2;    // pin d'entrée de la sonde de température
const byte secheurSystem = 4;      // Output pour commander le sécheur solaire
unsigned int sensorTempValue = 0;  // température de la CTN
const unsigned int temperatureSeuilVentilation = 600; // valeur Max qui déclenche la ventilation, à définir (0-1023) avec calibrageCTN
const unsigned int temperatureSeuilArret = 400; // valeur Min qui arrête la ventilation, à définir (0-1023) avec calibrageCTN

// Bloc concernant la lecture de tension sur A3
const byte sensorPinVoltage = A3;  
unsigned int sensorVoltage;


void calibrageCTN(){
/* XXXXXXXXX Fonction à supprimer une fois la CTN calibrée afin d'économiser de l'espace prog/var XXXXXXXXXXX
 *  Cette fonction sert à calibrer la CTN utilisée par le module en obtenant une correspondace °C <->valeur sur A0
 * La CTN est en série avec une résistance de valeur proche de la CTN : +5V CTN RES 0V
 * La prise de A0 se fait entre CTN et RES de sorte à avoir un pont diviseur de tension.
 * On aura donc une évolution entre 0 et 5V sur A0, on récupère la valeur de cette borche en l'affichant dans le moniteur.
 * Cela donne des points de référence à injecter dans le code par la suite
 */



Serial.println("Valeur de l'entrée sur A2 : ");
  
while (1==1)
{
    digitalWrite(outPin, LOW); // On éteint la LED L
    delay(500); // Délai entre deux mesures en ms
    digitalWrite(outPin, HIGH); // On allume la LED L
    sensorTempValue = analogRead(sensorPinTemp); // lecture sur CTN
    Serial.println(sensorTempValue); // valeur de SensorPin dans
}


}


void setup() {
  
  delay(1500); // délai d'initialisation
  Serial.begin(9600); // ouverture du moniteur
  pinMode(sensorPinUp, INPUT); // initialisation des entrées/sorties
  pinMode(sensorPinDown, INPUT);
  pinMode(sensorPinTemp, INPUT);
  pinMode(stopPin, INPUT);
  
  pinMode(outPin, OUTPUT);
  pinMode(outPinSound, OUTPUT);
  pinMode(secheurSystem, OUTPUT);
  
  digitalWrite(outPin, LOW);    // sortie numérique outPin sur LOW
  digitalWrite(secheurSystem, LOW);

}
 
void loop() {

  sensorVoltage=analogRead(sensorPinVoltage); //lecture du pont diviseur pour évaluer la tension dessus.
  sensorValueUp = analogRead(sensorPinUp);  // lecteur de la valeur du capteur ascendant
  sensorValueDown = analogRead(sensorPinDown);  // lecteur de la valeur du capteur descendant
  sensorTempValue = analogRead(sensorPinTemp); // lecture sur CTN

    Serial.print("Tension mesurée : ");
    Serial.println(map(sensorVoltage,0,1023,0,500)/100); // map retourne des entiens uniquement, ici on bidouille pour avoir 2 chiffres après la virgule
  if (sensorTempValue >= temperatureSeuilVentilation)// si le statut est déjà high, ne change pas &&(sensorValue >= temperatureSeuilVentilation)
  {
    digitalWrite(secheurSystem, HIGH); // On allume la LED L, qui sert de sortie pour piloter le ventilateur sur transistor.
   // Serial.println("Déclenchement");
  }

  if (sensorTempValue <= temperatureSeuilArret)
 
  {
    digitalWrite(secheurSystem, LOW); // On éteint la LED L, qui sert de sortie pour piloter le ventilateur sur transistor.
  //  Serial.println("Arrêt");
  }


  if ((sensorValueUp > seuilUp) || (sensorValueDown < seuilDown)){        // déclencheur avec seuil, on va émettre un signal HIGH sur outPin et un signal sonore sur outPinSound
      // bon, théoriquement on n'utilise pas le sécheur en même temps que les jauges
      digitalWrite(outPin, HIGH);  
      do {
           tone(outPinSound,300,500); // sur pin outPinSound, envoyer 300Hz pendand 250ms !!! attention, interférence avec pin 3 et 11 PMW
           delay(50);
           tone(outPinSound,2000,50);
          
           if (digitalRead(stopPin)==HIGH) {         // si le bouton stop est pressé, on revient
               sensorValueUp=0;
               sensorValueDown=1023;
               digitalWrite(outPin, LOW);  
               noTone(outPinSound);
               delay(3000); // pause de 3s avant de réenclencher le détecteur afin de laisser le temps de tout débrancher si besoin
          
            }
           delay(50);
    
         }  while (sensorValueUp!=0 && sensorValueDown!=1023);
  }

  
  
}




Le circuit :
Toutes les résistances de pull sont fixées à 15k, mais peuvent être adaptées sans souci d'environ 2k à 100k. Juste, plus la résistance est élevée, plus le montage sera sensible (cela forme un pont diviseur de tension sur chaque broche).

Arduino, programmation, résilience et librairie Olduvaï Capt1025


Prochain post :

Je vais ajouter une Jauge de batterie sur A3 :

D'une part pour monitorer la tension du montage et tester la tension de diverses batteries. Il y a déjà un bout de code à ce sujet, non optimisé, qui va être amélioré grâce au point suivant :


J'ai récupéré un vieil afficheur LCD d'un jeux d'échecs HS, à voir s'il fonctionne encore.
Arduino, programmation, résilience et librairie Olduvaï Capt1026

C'est un contrôleur Hitachi, donc théoriquement cela se pilote très facilement avec de l'Arduino.
Arduino, programmation, résilience et librairie Olduvaï Capt1027

L'afficheur débloquerait énormément de potentiel dans nos thématiques car on pourrait alors se passer du moniteur série et donc de l'ordi branché sur le montage, pour avoir une interaction directe avec l'utilisateur, donc tous les contrôles, calibrations, paramétrages dans des menus dédiés.
Cela permet au passage de travailler sur un seul gros programme modulaire dont chaque partie peut être activée/désactivée au besoin.

Je parlerai également de l'utilisation d'une seule entrée pour plusieurs boutons. Par exemple, la possibilité de détecter 4 états différents (donc des flèches haut/bas/droite/gauche) voire une dizaine sans trop se casser la tête (et sans multiplexeur CD4051, que l'on verra plus tard).... et donc économiser ces entrés au profit des capteurs.

________________________________________________________
L'expérience est une lumière qui n'éclaire que ceux qu'elle a déjà brûlés. Cédric Dassas


甩葱歌 - 古箏 - Distant Pulsar - Un Mauvais Fils - 25 Years of Zelda - Machinarium - Récapitulatif des projets électroniques - [Chroniques du Bunker de L'Apocalypse] - Projet Geiger - Culture ethnobotanique en France
tarsonis
tarsonis
Administrateur

Masculin Nombre de messages : 10680
Age : 37
Localisation : Grand Est
Loisirs : Trek, ethnobotanique, électronique DIY, nucléaire, médecine, post apo.
Date d'inscription : 21/05/2008

Canis Lupus et victor81 aiment ce message

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par victor81 Jeu 25 Aoû 2022 - 14:48

je sens que je vais ressortir mes vieux arduino nano pour essayer !
victor81
victor81
Membre Premium

Masculin Nombre de messages : 1127
Localisation : catharn
Loisirs : detection, culture de plantes medicinales
Date d'inscription : 13/06/2012

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par tarsonis Jeu 25 Aoû 2022 - 15:10

Hello,
n'hésite pas, surtout si tu vois des points à améliorer ou des fonctions à ajouter clind'oeil

________________________________________________________
L'expérience est une lumière qui n'éclaire que ceux qu'elle a déjà brûlés. Cédric Dassas


甩葱歌 - 古箏 - Distant Pulsar - Un Mauvais Fils - 25 Years of Zelda - Machinarium - Récapitulatif des projets électroniques - [Chroniques du Bunker de L'Apocalypse] - Projet Geiger - Culture ethnobotanique en France
tarsonis
tarsonis
Administrateur

Masculin Nombre de messages : 10680
Age : 37
Localisation : Grand Est
Loisirs : Trek, ethnobotanique, électronique DIY, nucléaire, médecine, post apo.
Date d'inscription : 21/05/2008

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par tarsonis Ven 26 Aoû 2022 - 9:54

Salut à tous,
Bon petite déception au début, la moitié de l'afficheur était HS, donc potentiellement l'un des deux contrôleurs derrière. C'est ce qui a sans doute poussé l'appareil vers la benne.

Mais mais mais..... sauras-tu trouver la cause de la panne?
Arduino, programmation, résilience et librairie Olduvaï Capt1029

Spoiler:

C'est un petit défaut de fabrication qui a sans doute fini par court-circuiter avec les années et l'humidité.

Bref, réparé facilement. Premiers tests, histoire de voir si tout est ok....et tenter l'affichage des caractères spéciaux dont on parlait, dont le "ï" et surtout le "µ", que bon nombre de dosimètres modernes ne sont pas capables d'afficher. Ici, c'est un LCD des années 90 avec un Arduino de 2008... aucune excuse pour les appareils développés depuis moins de dix ans !

Arduino, programmation, résilience et librairie Olduvaï Lcd_im10

Comme précisé plus haut, cela va me permettre de développer un bien meilleur programme, avec la possibilité d'interagir avec l'utilisateur, donc de sélectionner différents embranchements de programmes et d'options.

Bons bidouillages à tous !

________________________________________________________
L'expérience est une lumière qui n'éclaire que ceux qu'elle a déjà brûlés. Cédric Dassas


甩葱歌 - 古箏 - Distant Pulsar - Un Mauvais Fils - 25 Years of Zelda - Machinarium - Récapitulatif des projets électroniques - [Chroniques du Bunker de L'Apocalypse] - Projet Geiger - Culture ethnobotanique en France
tarsonis
tarsonis
Administrateur

Masculin Nombre de messages : 10680
Age : 37
Localisation : Grand Est
Loisirs : Trek, ethnobotanique, électronique DIY, nucléaire, médecine, post apo.
Date d'inscription : 21/05/2008

Canis Lupus, Ash, victor81 et Le castor bricoleur aiment ce message

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par tarsonis Mer 31 Aoû 2022 - 14:16

Salut à tous,
Petites fonctions ajoutant un menu interactif à l'appareil, permettant de connaitre l'état d'une fonction et de le modifier.
L'enjeu est évidemment de mettre à profit le LCD afin de proposer un circuit pouvant être utilisé complètement offline.

Accessoirement, je parle ici de la technique très rudimentaire mais efficace où l'on peut greffer plusieurs commandes sur une seule entrée analogique, afin de les économiser pour un usage plus important. Ici, il y aura 5 boutons poussoirs pour le menu sur A5, mais théoriquement on pourrait en utiliser au moins une dizaine en ajustant les composants.

Plusieurs commandes sur une seule entrée analogique.

Ici, sur A5, on vérifie la tension entre 0 et 5V, qui prend une valeur entre 0 et 1023.
Une résistance RA5 de 100k porte l'entrée à la masse, donc par défaut on a toujours 0 dessus.

J'y ajoute les boutons poussoirs via des résistances 22k en série, selon le schéma :
Arduino, programmation, résilience et librairie Olduvaï Capt1031

Chaque bouton pressé va former un pont diviseur de tension. Plus de détails dans le post : Circuits Nomades

En gros, la tension sur A5 :
Arduino, programmation, résilience et librairie Olduvaï Capt1032

Avec les résistances 100k et 22k :

Arduino, programmation, résilience et librairie Olduvaï Capt1033

Donc la valeur numérique sur A5 :
Arduino, programmation, résilience et librairie Olduvaï Capt1034


Avec les résistances 100k et 22k :
Arduino, programmation, résilience et librairie Olduvaï Capt1035


On voit que si on presse :
- Haut, il y +5V sur A5, donc 1023.
- Bas, il y aura un pont diviseur 22k-100k sur A5, donc 4,10V sur A5, soit 839
- Droite, il y aura un pont diviseur 44-100k sur A5, donc 3,47V sur A5, soit 710
- Gauche, il y aura un pont diviseur 66-100k sur A5, donc 3,01V sur A5, soit 616
- Ok, il y aura un pont diviseur 88-100k sur A5, donc 2,66V sur A5, soit 544

Il n'y a plus qu'à vérifier cette valeur qui arrive sur A5 pour savoir quel bouton a été pressé.
Alors évidemment, il faut inclure une marge, car les composants sont soumis à quelques imprécisions.
Avec une fourchette de +/- 5% standard pour la plupart des résistances, on obtient des intervalles de valeurs potentielles pour chaque bouton.

D'où le choix des valeurs que je propose : ces intervalles de se chevauchent pas. Il est tout à fait possible de prendre d'autres valeurs, mais il faut alors recalculer ces intervalles.
Un petit tableur est toujours utile :
Arduino, programmation, résilience et librairie Olduvaï Capt1036


Si on voulait être perfectionniste, on pourrait réindexer les tensions sur la valeur réelle d'alimentation du circuit (sur sa référence 1,1V) et prendre en compte la variation des valeurs des résistances en fonction de la température. Mais vu les intervalles, cela ne me semble pas pour l'instant probant (variation homogène pour toutes). Sinon, on peut soit passer sur des résistances 1%, soit intercaler d'autres résistances et prendre des valeurs plus petites afin d'ajouter des gaps de valeurs entre chaque bouton.



Le fonctionnement du programme.
Au démarrage, on affiche la version du programme et quelques infos puis ça arrive sur le menu.

Arduino, programmation, résilience et librairie Olduvaï Capt1037

On peut faire défiler avec haut/bas, qui boucle si on arrive au dernier slot.
Cela affiche l'option en cours, et si elle est active.

Arduino, programmation, résilience et librairie Olduvaï Capt1038

Gauche-Droite permet d'activer/désactiver.
Arduino, programmation, résilience et librairie Olduvaï Capt1039


Pour l’instant, ok permet de sortir du menu quand on est sur Exit
Arduino, programmation, résilience et librairie Olduvaï Capt1040

En exemple, j'ai voulu tester l'option d'activation du prescaler vue plus haut, qui permet de réduire la fréquence de l'horloge du nano et diviser sa consommation par 2.
Arduino, programmation, résilience et librairie Olduvaï Capt1041


Bons bidouillages à tous clind'oeil

Le bout de code :

Code:

/* 31/08/2022 : V0.1.1 Ajout Du Prescaler /16 -> 1MHz d'horloge pour diviser la conso du nano par 2

*/

#define menuItem 5 // nombre d'entrées dans le menu (attention, incluant le 0)

const byte menuButtonPin = A5; // doit être analogique en attendant un mutiplexeur.
unsigned int menuButtonValue=0; // mettre en private
const byte outPin = LED_BUILTIN;
boolean optionMenu[menuItem] = {0,0,0,0,0}; // on pourrait utiliser des byte, qui utilisent strictement le même espace mémoire. on pourra stocker des trucs intéressants plus tard si nécessaire

byte perscalerTime=1; // facteur diviseur pour toutes les fonctions temporelles.

char *TexteMenu[] = {
"Option A",              //0 les options commencent ici
"Option B",              //1
"Option C",              //2
"Prescaler 1MHz",        //3  le prescaler 1MHz permet de diviser la conso par 2 du Nano //les options finissent ici
"Exit Menu"              //4
};  


char *TexteProg[] = {
"Titan V0.1.1",               //0
"Menu T/B/R/L",          //1

};  



#include <LiquidCrystal.h>

const byte rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);


byte buttonMenu() {
  /* on utilise une configuration avec 5 résistances 22k en série entre +VCC et GND + bouton qui cut sur pinMenu.
  Chaque bouton réaliser un pont diviseur :

Valeur Résistance de pont       22  k
Valeur résistance pulldown      100 k
Vcc     5 V
Interrupteur  Résistance A5/Vcc   UA5 AnalogInput Marge Min -5% Marge Sup+5%

1 0   5,00  1023    
2 22    4,10  839 797 880
3 44    3,47  710 675 746
4 66    3,01  616 585 647
5 88    2,66  544 517 571*/

while (1==1)
{
    menuButtonValue = analogRead(menuButtonPin); // lecture des boutons sur menuButtonPin


/////////// peut être ajouter un beep qqpart
    delay(16/perscalerTime); // Délai entre deux mesures en ms

    if (menuButtonValue>=1009 && menuButtonValue<=1023)  //Haut
    return (0);
  if (menuButtonValue>=797 && menuButtonValue<=880) // Bas
    return (1);
  if (menuButtonValue>=675 && menuButtonValue<=746) // Droite
    return (2);
  if (menuButtonValue>=585 && menuButtonValue<=647) //Gauche
    return (3);
  if (menuButtonValue>=517 && menuButtonValue<=571) // Ok
    return (4);
  }
}


void menu()
{
  byte menuPosition=0;
// Initialisation : display de comment ça fct.
//byte positionMenu=0;
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(TexteProg[0]);
  lcd.setCursor(0, 1);
  lcd.print(TexteProg[1]);

delay(1600/perscalerTime);
  

while(1==1)
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(TexteMenu[menuPosition]);
  lcd.setCursor(0, 1);

if (menuPosition<menuItem-1)
{
  


  if ((optionMenu[menuPosition])) //si actif et hors Exit Menu
  {
        lcd.print("Actif");
  }

  else
  {
      lcd.print("Inactif");
  }
}

switch (buttonMenu()) // on récupère ce que l'utilisateur presse
{
 case 0:
    // Haut
  
    if (menuPosition!=0) // on peut remonter dans le menu ?
    {
      menuPosition--;
    }
    else
    {
      menuPosition=menuItem-1;
    }
    break;
 case 1:
    // Bas
     if (menuPosition<(menuItem-1)) // on peut descendre dans le menu ?
    {
      menuPosition++;
    }
    else
    {
      menuPosition=0;
    }
    break;
 case 2:
    // Droite
    optionMenu[menuPosition]=!optionMenu[menuPosition];
    
    // Si c'est le prescaler
    if (menuPosition==3)
    {
      if (perscalerTime==16)
      {
        
        perscalerTime=1;
      
        CLKPR = 0b10000000; //Activation du prescaler
        CLKPR = 0b00000000; //Division par 1

      }
      else
      {
        perscalerTime=16;
    
        CLKPR = 0b10000000; //Activation du prescaler
        CLKPR = 0b00000100; //Division par 16
  
      
      }
    }
  

    
    break;

    

 case 3:
    // Gauche
    optionMenu[menuPosition]=!optionMenu[menuPosition];
    if (menuPosition==3)
    {
      if (perscalerTime==16)
      {
        
        perscalerTime=1;
              
        CLKPR = 0b10000000; //Activation du prescaler
        CLKPR = 0b00000000; //Division par 1
      }
      else
      {
        perscalerTime=16;
      
        CLKPR = 0b10000000; //Activation du prescaler
        CLKPR = 0b00000100; //Division par 16
  
      }
    }

    
    break;
 case 4: // Bouton OK
  if (menuPosition==menuItem-1)
  {
   return 0;
   }
    
    break;
}




  
delay(512/perscalerTime);
}

  
  
}

void setup() {
  // Mise en place de l'afficheur 16 colonnes - 2 lignes - LM052L
  // Adapter peut être l'affichage dans le cadre d'un afficheur 1 ligne

lcd.begin(16, 2);

lcd.print(TexteProg[0]);
delay(512/perscalerTime);

menu();
}



void loop() {
menu();
 
  delay(512/perscalerTime);
}

________________________________________________________
L'expérience est une lumière qui n'éclaire que ceux qu'elle a déjà brûlés. Cédric Dassas


甩葱歌 - 古箏 - Distant Pulsar - Un Mauvais Fils - 25 Years of Zelda - Machinarium - Récapitulatif des projets électroniques - [Chroniques du Bunker de L'Apocalypse] - Projet Geiger - Culture ethnobotanique en France
tarsonis
tarsonis
Administrateur

Masculin Nombre de messages : 10680
Age : 37
Localisation : Grand Est
Loisirs : Trek, ethnobotanique, électronique DIY, nucléaire, médecine, post apo.
Date d'inscription : 21/05/2008

Canis Lupus, Nadia et victor81 aiment ce message

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par tarsonis Mar 13 Sep 2022 - 14:39

Salut à tous,
petite vidéo plutôt qu'un article, afin de présenter le bout de code du détecteur de radioactivité.

Il y a un monitoring du bruit de fond avec une moyenne glissante sur 60s (les CPM) et un détecteur de hausse de radioactivité avec les CP5.
Les deux variables sont converties en µSv/h avec le facteur de conversion du tube sélectionné.

Ici je bidouille avec la platine type "Cajoe" ou "RadiationD", qui n'est pas optimisée du tout et souffre de quelques défauts de conception (sans compter les erreurs sur Github). Je verrai sans doute dans un second temps pour son amélioration.
Le kit qu'on m'a donné est pourvu du tube J305, qui présente un terrible problème d'utilisation qui mérite une attention particulière à l'usage clind'oeil



Le code source pour bientôt; il mérite encore quelques optimisations clind'oeil

________________________________________________________
L'expérience est une lumière qui n'éclaire que ceux qu'elle a déjà brûlés. Cédric Dassas


甩葱歌 - 古箏 - Distant Pulsar - Un Mauvais Fils - 25 Years of Zelda - Machinarium - Récapitulatif des projets électroniques - [Chroniques du Bunker de L'Apocalypse] - Projet Geiger - Culture ethnobotanique en France
tarsonis
tarsonis
Administrateur

Masculin Nombre de messages : 10680
Age : 37
Localisation : Grand Est
Loisirs : Trek, ethnobotanique, électronique DIY, nucléaire, médecine, post apo.
Date d'inscription : 21/05/2008

victor81 aime ce message

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par tarsonis Ven 4 Nov 2022 - 15:45

Salut à tous,
on aborde enfin le stockage mémoire, qui va représenter une grande avancée dans n'importe quel projet.
En effet, cela débloque plusieurs possibilités, dont la lecture et l'écriture donc le monitoring et le suivi de variables.

Aujourd'hui, on va aborder le niveau le plus simple, avec l'EEPROM interne présente dans tous les modules Arduino. Il s'agit d'une petite mémoire dont la taille varie selon le modèle qu'on a sous la main.
En général pour le Uno et le Nano (sur ATmega328), elle est de 1kilo-octet (1024 octets).
Elle est assez lente (quelques ms par requête) et n'a qu'un nombre limité d'écritures par cellule mémoire, en général 100 000. Il ne faut donc pas trop s'amuser à réécrire chaque case toutes les secondes sinon en deux jours c'est plié. Théoriquement, il semble que la durée de rétention de l'info soit d'environ une dizaine d'années.

On démarre en douceur avec un bout de code qui utilise EEPROM.h et vérifie la taille de l'EEPROM avec length() et affiche la valeur de chaque case mémoire avec read(x) qui retourne la valeur stockée à l'emplacement x.
Tous les détails ici https://docs.arduino.cc/learn/built-in-libraries/eeprom

Code:
#include <EEPROM.h>


void setup() {

  unsigned int tailleEeprom=EEPROM.length();  // donne le nombre de cellules de l'EEPROM interne :  uint16_t length(){ return E2END + 1; }
  unsigned int tmp;
  Serial.begin(9600);
  Serial.println("");
  Serial.println("");
  Serial.println("Initialisation...");

  Serial.print("Taille de l'EEPROM INTERNE : ");
  Serial.print(tailleEeprom);
  Serial.println(" kb");


  for(tmp = 0; tmp < tailleEeprom ; tmp++)
  {
       if ((tmp% 16)==0)
       {
          Serial.println("");
               Serial.print("#");
               Serial.print(tmp);
               Serial.print("->");
               Serial.print(tmp+15);
               Serial.print(" ");
       }

       Serial.print(EEPROM.read(tmp));
       Serial.print("  ");

  }
    Serial.println("Fin de lecture.");

}

void loop()
{
}



Ici sur mon nano, il y a 1024 octets. Chaque cellule vaut 255, donc n'a jamais été écrite.
Arduino, programmation, résilience et librairie Olduvaï Capt1045


On peut utiliser la fonction write(adresse, valeur) qui écrit 'valeur' (un octet) dans la cellule 'adresse'.

Comme le nombre d'écritures est limité, il est en général préférable d'utiliser update(adresse, valeur) qui vérifie d'abord le contenu de la cellule, et la met à jour uniquement si la valeur passée en argument est différente de celle stockée. En gros, on évite de griller une écriture si la valeur est la même.

Enfin, il existe deux fonctions très pratiques get() et put() qui fonctionnent respectivement comme read() et update() à ceci près que l'on peut lire et écrire des structures (donc soit des variables, soit des combinaisons de variables). Si on écrit des trucs les uns à la suite des autres, il faut tout de même vérifier le nombre de cellules occupées avec la fonction sizeof().

Par exemple, dans le cadre du programme Geiger, je peux stocker la dose totale cumulée, qui sera conservée même après extinction des circuits.
En gros, on obtient exactement le radiamètre XR-1 dont je parle ici : Aujourd'hui, où se procurer un Geiger pas cher ?

La fonction d'écriture :
Code:
void enregistreCoupsEeprom (unsigned long valeur)
/* Fonction d'enregistrement du nombre de coups totaux, de sorte à monitorer la dose totale.
 *  UL permet de stocker 4,294,967,295 valeurs, soit en général la durée de vie d'un tube.
 *  Fonction appelée une fois par heure (mais désactivable si on se met en mode mesure de contact),
 *  ce qui permet de monitorer pendant environ 15 ans avant de griller les cases mémoires de l'EEPROM,
 * il faudra décaler de 4 cases ensuite.
 *
 * */

{
  EEPROM.get(99, valeur); // on utilise la 100e case
  delay(15);
}

Pour la suite, on abordera l'utilisation de mémoires externes I2C EEPROM, que l'on trouve pas mal en récup... clind'oeil

________________________________________________________
L'expérience est une lumière qui n'éclaire que ceux qu'elle a déjà brûlés. Cédric Dassas


甩葱歌 - 古箏 - Distant Pulsar - Un Mauvais Fils - 25 Years of Zelda - Machinarium - Récapitulatif des projets électroniques - [Chroniques du Bunker de L'Apocalypse] - Projet Geiger - Culture ethnobotanique en France
tarsonis
tarsonis
Administrateur

Masculin Nombre de messages : 10680
Age : 37
Localisation : Grand Est
Loisirs : Trek, ethnobotanique, électronique DIY, nucléaire, médecine, post apo.
Date d'inscription : 21/05/2008

victor81 aime ce message

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par tarsonis Mer 9 Nov 2022 - 16:52

Salut à tous,
Tout d'abord, petite nouveauté pour le topic, j'ai trouvé un kit Quimat en occas à côté de chez moi, ce qui permettra de tester (et proposer) les circuits à la fois sur Uno et sur Nano. Théoriquement, les deux cartes sont quasi-identiques, mais dans la pratique il y aura quelques subtilités mineures (puissance, fréquence, broches, etc).

Il ne faut pas hésiter à parcourir les annonces car on y trouve régulièrement des kits complets, donc une bonne base de démarrage sans se ruiner.
Ici pour 5E :
Arduino, programmation, résilience et librairie Olduvaï Img_8110

J'envisage de faire une carte Geiger avec le "prototype extension board".

Aujourd'hui, petit approfondissement avec l'utilisation d'une EEPROM externe 8bits, ici un 24LC02B de récup. C'est un circuit I2C série, capable de stocker 2kb, donc 256 octets.
Il y a toutes sortes de variations, avec plus ou moins de mémoire; en général, pour les 24LCxx, le xx représente le nombre de kb de mémoire.

Ici sur Uno et Nano :
Arduino, programmation, résilience et librairie Olduvaï Capt1051

Déporter le stockage sur une EEPROM externe permet pas mal de trucs, dont :
- permuter des modules selon les besoins. Perso je travaille sur un soft Arduino d'apprentissage du code Morse. Les mémoires permettent de jouer avec les séquences. Dans un autre registre, je pensais à différentes routines programmées; par exemple : les séquences d'émissions radio, d'activation de poulailler (le membre se reconnaitra clind'oeil ), etc.
- stocker sur des mémoires plus résilientes : les 24LCxx permettent en général plusieurs millions de réécritures, et sur la durée; les constructeurs garantissant au moins 50 ans. C'est un énorme avantage par rapport à l'EEPROM interne vue plus haut.
- utiliser des systèmes de clef : les valeurs dans l'EEPROM peuvent servir de clef privée pour activer/chiffrer du code.

Cependant, cela ajoute deux contraintes :
- Les broches A4 et A5 de l'Arduino sont bloquées pour l'EEPROM, je n'arrive pas complètement à les réassigner.
- Il y a un peu de codage en plus.


On ne peut pas utiliser la lib EEPROM, qui ne peut écrire que sur la mémoire interne de l'Arduino.
Mais fort heureusement, la lib Wire fait déjà tout à notre place, il ne reste qu'à l'implémenter et comprendre les quelques subtilités.

Il y a un excellent article français sur le net, à consulter/backuper immédiatement : http://electroniqueamateur.blogspot.com/2020/01/utiliser-une-memoire-eeprom-i2c-arduino.html
qui voit de long en large le sujet.
Je me permets de citer les points essentiels :

  • Les broches 1, 2 et 3 du CI ne sont pas branchées. Pour le modèle 24C64A, on peut relier certaines d'entre elles à 5 V pour modifier l'adresse I2C. Pour les deux autres modèles, ces 3 broches ne servent à rien!

  • La broche 4 du CI doit être branchée à la masse (GND).

  • La broche 5 du CI est responsable de l'échange des données (SDA). On la branche à la broche A4 de l'Arduino Uno, ainsi qu'à 5 V par l'entremise d'une résistance de tirage de quelques kiloohms (j'ai utilisé 4,7 kΩ).

  • La broche 6 du CI reçoit le signal d'horloge (SCL). On la branche à la broche A5 de l'Arduino Uno, ainsi qu'à 5 V par l'entremise d'une résistance de tirage de quelques kiloohms (j'ai utilisé 4,7  kΩ).

  • La broche 7 du CI (WP) doit être reliée à la masse (GND) pour qu'il soit possible d'écrire dans l'EEPROM. Si vous désirez ensuite empêcher que l'information de l'EEPROM puisse être modifiée, vous pouvez brancher cette broche à 5 V.

  • La broche 8 du CI doit être reliée à 5 V.


Fonctionnement en lecture :
Le sketch ci-dessous affiche dans le moniteur série la valeur enregistrée à chaque adresse de l'EEPROM. L'essentiel du travail s'effectue dans la routine readbyte():
  • On débute la transmission en indiquant l'adresse I2C du 24LC01B:  Wire.beginTransmission(0x50);
  • On envoie au 24LC01B l'adresse de l'octet dont on désire lire la valeur: Wire.write(5);
  • On clôt la transmission: Wire.endTransmission();
  • On demande au 24LC01B de nous envoyer l'information: Wire.requestFrom(0x50, 1);
  • On récupère l'information reçue: if (Wire.available()) {lecture = Wire.read();}


Fonctionnement de l'écriture :
Le 24LC01B comporte 128 octets numérotés de 0 à 127. Chacun de ces 128 emplacements de mémoire peut contenir une valeur située entre 0 et 255.

Le sketch ci-dessous écrit la valeur "100" à l'adresse "5" de l'EEPROM. Cette écriture ne s'exécute qu'une seule fois, au démarrage du programme. L'essentiel du travail s'effectue dans la routine writebyte():

  • On débute la transmission en indiquant l'adresse I2C du 24LC01B:  Wire.beginTransmission(0x50);
  • On envoie au 24LC01B l'adresse de l'octet dont on désire modifier la valeur: Wire.write(5);
  • On envoie au 24LC01B la valeur qu'on désire enregistrer à cette adresse: Wire.write(100);
  • On clôt la transmission: Wire.endTransmission();


Voici un sketch qui lit et affiche l'intégralité de l'EEPROM au format hexadécimal.
Code:
/*
   Lecture de tout le contenu d'une mémoire EEPROM 24LC01B
*/

#include <Wire.h>  // bibliothèque i2c

#define adresse_EEPROM 0x50    //Addresse i2c de l'EEPROM 24LC02
#define adresseMax 256 // taille de l'EEPROM (nombre d'octets)

unsigned int adresse = 0;

byte lettre=0;
void setup(void)
{
  Serial.begin(9600);
  Wire.begin();
  delay(100);
  Serial.println("");
  Serial.println("Lecture des valeurs enregistrees sur l'EEPROM:");

  for (int i = 0; i < adresseMax; i++) {

      if ((i% 16)==0)
       {
               Serial.println("");
               Serial.print("#");
               Serial.print(i);
               Serial.print("->");
               Serial.print(i+15);
               Serial.print("  ");
               if (i<16)
               {
                 Serial.print(" ");
               }
               if (i==96)
               {
                 Serial.print(" ");
               }
               if (i<96)
               {
                 Serial.print("  ");
               }
       }

  
    lettre=readbyte(adresse_EEPROM, i);
    
    if (lettre<16)
    {
       Serial.print(" "); // espace sur valeur simple
    }
    Serial.print(lettre, HEX);
           Serial.print("  ");
  }
}

void loop() {

}


byte readbyte(int adressei2c, unsigned int adresseMem )
{
  byte lecture = 0;

  Wire.beginTransmission(adressei2c);  // adresse i2c du 24LC02B
  Wire.write(adresseMem); // numéro de l'octet qu'on veut lire
  Wire.endTransmission();
  Wire.requestFrom(adressei2c, 1); // on demande au 24LC02B d'envoyer de l'info

  delay(10);

  if (Wire.available()) {  // réception de l'info
    lecture = Wire.read();
  }

  return lecture;
}

void writebyte(int adressei2c, unsigned int adresseMem, byte data )
{
  Wire.beginTransmission(adressei2c); //adresse I2C de l'EEPROM
  Wire.write(adresseMem); // numéro de l'octet à modifier
  Wire.write(data); // nouvelle valeur que doit prendre l'octet
  Wire.endTransmission(); // fin de la transmission I2C
  delay(10);
}

On voit que l'EEPROM de récup a bien été utilisée et contient pleins de données :

Arduino, programmation, résilience et librairie Olduvaï Capt1046


Si on ajoute
Code:
 writebyte(adresse_EEPROM, i, 0);


Juste au commencement de la boucle for, alors on écrit 0 dans la case qui va être lue. Comme on parcourt toutes les cellules, on efface complètement la mémoire :

Arduino, programmation, résilience et librairie Olduvaï Capt1047

A partir de maintenant, on sait écrire un byte (un octet) dans une case.

Cependant, on est vite limité car la plupart du temps, les variables à enregistrer sont d'un autre type que byte, qui nécessite 8 bits.
Sur Uno et Nano, une variable int est codée sur 16 bits (2 octets), tandis que les float/long sont codés sur 32 bits (4 octets). Comment stocker ça avec un circuit avec qui on ne peut communiquer qu'avec des paquets de 8 bits ?

Soit on bricole une routine qui convertit la variable en question en suite de case de 8bits (dans les deux sens), soit on utilise une possibilité très pratique du langage C, que l'on rencontre quasi-uniquement que dans les codes optimisés : l'Union.

Très sommairement, c'est un agrégat qui permet d'accéder au même espace mémoire selon différents types de données. Un exemple pour clarifier cela : J'ai besoin de stocker pour le circuit Geiger le nombre total d'impulsions, donc dans un long non signé, donc codé sur 4 bytes, et capable de stocker des valeurs jusqu'à environ 4 milliards :

Code:
union {
   byte b[4];
   unsigned long longintnumber;
} TotalPulse;

Bon, comme on essaye de bricoler du code portable, je préfère plutôt :
Code:
union {
   byte b[sizeof(unsigned long int)];
   unsigned long int longintnumber;
} TotalPulse;

Car la taille mémoire des variables peut différer avec certaines cartes Arduino; le INT est sur 16bits avec Uno mais 32bits sur Due, par exemple. Ici, on crée l'Union selon la taille définie par le système, donc on n'a plus à s'en soucier.

On va pouvoir appeler TotalPulse selon deux manière :

1) Comme un long non signé :

Code:
TotalPulse.longintnumber=1020304050;

2) Comme une suite de 4 bytes, stockant chacun une partie du nombre :

Code:
TotalPulse.b[i]=0b00100001;


Ici, avec le code qui affiche d'abord la taille mémoire de la variable (donc le nombre de bytes utilisé dans l'Union), puis la valeur de chaque byte selon le nombre injecté dans longintnumber

Code:

Serial.println("--------------------");
Serial.println(sizeof(unsigned long int));

for (byte i = 0; i < sizeof(TotalPulse.longintnumber); i++)
{
    Serial.print(TotalPulse.b[i], BIN);
    Serial.print(" ");
}
    TotalPulse.longintnumber=255;
    TotalPulse.longintnumber=65000;
    TotalPulse.longintnumber=1000000;
    TotalPulse.longintnumber=50000001;
    TotalPulse.longintnumber=4278320655;

Avec le for -absent du code pour l'alléger- rappelé à chaque fois
Sortie :

Arduino, programmation, résilience et librairie Olduvaï Capt1048

Alors attention, les bytes sont du plus faible au plus fort et les 0 sont pour chaque byte sous-entendus : 1111 signifie 00001111
Bon de toute façon, on n'a pas à s'en soucier, c'est juste pour expliciter le process.


Du côté utilisateur, c'est transparent, seul le stockage se fait par paquet de 8bits : ici je stocke ma variable sur les 4 premiers bytes de l'EEPROM en appelant autant de fois la fonction d'écriture qu'il n'y a de byte dans l'Union.


Code:
  for (byte i = 0; i < sizeof(TotalPulse.longintnumber); i++){
    writebyte(adresse_EEPROM, i,TotalPulse.b[i]);
  }

Et la lecture :

Code:
for (byte i = 0; i < sizeof(TotalPulse.longintnumber); i++){
    TotalPulse.b[i]=readbyte(adresse_EEPROM, i);
    
  }

Code qui va lire et afficher tout le contenu de l'EEPROM l'afficher, lire les 4 premier octets pour recomposer un entier Long non signé (notre variable).

Puis écrire une nouvelle valeur dans l'EEPROM, effacer la variable dans le programme (afin d'être sûr que l'on rapatrie bien une valeur enregistrée), puis afficher le nouveau contenu de l'EEPROM et la variable actualisée.

Code:
void setup(void)
{


  Serial.begin(9600);

  Wire.begin();
  delay(100);


  Serial.println("");
  Serial.println("Lecture des valeurs enregistrees sur l'EEPROM:");

  Serial.println("");
  for (int i = 0; i < adresseMax; i++) {


      if ((i% 16)==0)
       {
          Serial.println("");
               Serial.print("#");
               Serial.print(i);
               Serial.print("->");
               Serial.print(i+15);
               Serial.print("  ");
               if (i<16)
               {
                 Serial.print(" ");//espace première ligne
               }
               if (i==96)
               {
                 Serial.print(" ");//espace première ligne
               }
               if (i<96)
               {
                 Serial.print("  ");//espace première ligne
               }
       }

    
    lettre=readbyte(adresse_EEPROM, i);
    if (lettre<16)
    {
       Serial.print(" "); // espace sur valeur simple
    }
    Serial.print(lettre, HEX);
           Serial.print("  ");
  }


for (byte i = 0; i < sizeof(TotalPulse.longintnumber); i++){
    TotalPulse.b[i]=readbyte(adresse_EEPROM, i);
    

  }
  Serial.println("");
  Serial.println("Valeur EEPROM Actuelle: ");
  Serial.println(TotalPulse.longintnumber);

  
  TotalPulse.longintnumber=1122334455;
   Serial.println("");
    Serial.println("Valeur à définir : ");
    Serial.println(TotalPulse.longintnumber);


  
  for (byte i = 0; i < sizeof(TotalPulse.longintnumber); i++){
    writebyte(adresse_EEPROM, i,TotalPulse.b[i]);

  }
  Serial.println("");
  Serial.println(" Fin De l'écriture sur EEPROM");

  Serial.println("");



  TotalPulse.longintnumber=0;
    Serial.println("Variable programme effacée.");
  Serial.println("Valeur programme : ");
      Serial.println(TotalPulse.longintnumber);
    Serial.println("");
    
    Serial.println("Lecture des valeurs enregistrees sur l'EEPROM:");

  for (int i = 0; i < adresseMax; i++) {


      if ((i% 16)==0)
       {
          Serial.println("");
               Serial.print("#");
               Serial.print(i);
               Serial.print("->");
               Serial.print(i+15);
               Serial.print("  ");
               if (i<16)
               {
                 Serial.print(" ");//espace première ligne
               }
               if (i==96)
               {
                 Serial.print(" ");//espace première ligne
               }
               if (i<96)
               {
                 Serial.print("  ");//espace première ligne
               }
       }


    lettre=readbyte(adresse_EEPROM, i);
    if (lettre<16)
    {
       Serial.print(" "); // espace sur valeur simple
    }
    Serial.print(lettre, HEX);
           Serial.print("  ");
  }


  Serial.println("");
  Serial.println("Lecture de la mémoire en 8b");
  
for (byte i = 0; i < sizeof(TotalPulse.longintnumber); i++){
    TotalPulse.b[i]=readbyte(adresse_EEPROM, i);
    
  }
  Serial.println("Valeur mémoire : ");
  Serial.println(TotalPulse.longintnumber);

}


Le résultat :

Arduino, programmation, résilience et librairie Olduvaï Capt1049

Tout fonctionne clind'oeil

Du coup, test de protection en écriture en reliant la broche 7 de l'EEPROM sur +5V  et nouvelle valeur à enregistrer :

Arduino, programmation, résilience et librairie Olduvaï Capt1050

On voit que la mémoire n'a pas bougé. Voilà pour le stockage sur EEPROM externe. Il y a une subtilité pour les mémoires où on dépasse un adressage sur 8bits, où le tuto en lien explique comment le faire proprement. Cela suit en fait la même logique en envoyant l'adresse en plusieurs paquets.
Bons bidouillages à tous !clind'oeil

________________________________________________________
L'expérience est une lumière qui n'éclaire que ceux qu'elle a déjà brûlés. Cédric Dassas


甩葱歌 - 古箏 - Distant Pulsar - Un Mauvais Fils - 25 Years of Zelda - Machinarium - Récapitulatif des projets électroniques - [Chroniques du Bunker de L'Apocalypse] - Projet Geiger - Culture ethnobotanique en France
tarsonis
tarsonis
Administrateur

Masculin Nombre de messages : 10680
Age : 37
Localisation : Grand Est
Loisirs : Trek, ethnobotanique, électronique DIY, nucléaire, médecine, post apo.
Date d'inscription : 21/05/2008

Canis Lupus aime ce message

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par tarsonis Mar 6 Déc 2022 - 22:37

Hello,
suite et fin de la partie sur la mémorisation afin d'offrir plus de possibilités car on va aborder la lecture et l'enregistrement sur carte SD.

Au niveau du tuto, je ne vais pas réinventer la roue, et vous renvoie vers l'excellent
https://electroniqueamateur.blogspot.com/2012/06/carte-sd-et-arduino.html

Ici, je vais surtout parler des subtilités de fabrications et d'utilisation.

Alors au niveau des avantages, le premier évidement est la quantité de mémoire disponible. On passe des quelques octets des EEPROMS à plusieurs Go.
Ensuite, c'est rudement pratique, on peut lire des fichiers dans des répertoires, stocker des infos et faire des appels répétés dessus avec des fonctions évoluées; plus besoin de trifouiller/convertir les données en paquets de 8bits.

Enfin, les cartes SD (et microSD) étant plus largement répandues, ce sera bien plus facile de bidouiller dessus qu'avec des EEPROMS puis de les permuter, échanger, et lire sur un PC.

Au niveau des inconvénients, j'en vois deux principaux:
- cela demande quatre pins de communication avec l'Arduino... si on a des boutons, un écran, des sondes & co, cela peut vite atteindre les limites du Nano/Uno. Il faut alors soit multiplexer, soit passer à un module avec plus d'E/S (type Mega).
- cela bouffe énormément de mémoire RAM sur le module. Il faut donc surveiller assez rapidement ce point au risque de rendre le circuit complètement instable voire non fonctionnel.
Les fonctions seules de lecture/écriture mangent environ 1ko de RAM, sur 2ko c'est tout de même important.

Bref, c'est assez peu frugal. Donc si on souhaite juste lire et stocker quelques valeurs comme avec le circuit compteur geiger/dosimètre, je recommanderais l'EEPROM. Si on a besoin de logs ou de lire plus que quelques centaines de ko (ça arrive vite), alors il faut passer au SD.

Au niveau de l'électronique.
Le point majeur à avoir en tête, c'est que toute carte SD communique en 3,3V. Avec les sorties Arduino en 5V directement dessus, on la grille quasiment immédiatement.
Il faut alors abaisser la tension pour envoyer des instructions à la bonne tension. Pour la communication retour SD->Arduino, ce n'est pas nécessaire car la carte répond en 3,3V, ce qui correspond à un statut HIGH sur Arduino en 5V. Certains ajoutent un convertisseur sur cette étape, mais il s'agit là d'une protection de découplage, utile surtout lorsque le module SD n'est pas alimenté par l'Arduino.

On voit de nombreuses bidouilles avec les ponts diviseurs pour convertir les impulsions 5V en 3,3V, mais cela fonctionne rarement, car ces résistances, couplées aux capacités parasites des connectiques vont créer des filtres RC, notamment du passe-bas, ce qui va altérer fortement les signaux et donc les communications; n'oublions pas que l'on échange à des fréquences bien supérieures à la centaine de KHz ici, donc quelques pF par ci par là vont tordre le signal et le rendre illisible.

Le schéma malgré tout, si on a vraiment rien sous la main :
Arduino, programmation, résilience et librairie Olduvaï Arduin10

Du coup, à partir d'ici, on peut soit acheter un module tout fait, soit en bricoler un.
Dans le premier cas, attention car il y a tout et n'importe quoi en vente.
Par exemple ce module ci :
Arduino, programmation, résilience et librairie Olduvaï Capt1054

Est pourvu d'un régulateur d'entrée uniquement pour l'alimentation de la carte extension, qui passe de 5V à 3,3V. Les PIN de communication sont juste protégées par des résistances. Du coup, on est vite dans la situation du pont diviseur, les capas parasites &co. Donc cela risque de ne pas fonctionner.

Il faut choisir un module avec convertisseur entrée/sortie, tel que celui-ci, où l'on voit bien la puce qui s'en occupe.
Arduino, programmation, résilience et librairie Olduvaï Capt1055

Je vous propose la version DIY avec le célèbre CD4050, qui est un buffer avec 6 entrées-sorties (bien que l'on n'en ait besoin que de 3, ça laisse d'autres possibilités). En gros, quand on a une entrée au statut HAUT, la sortie l'est aussi, mais à la tension VCC du CD4050. Donc si on l'alimente en 3,3V (tension qui est fournie par l'Arduino Uno/Nano), on a un convertisseur 5/3,3V, peu importe ce qui arrive en entrée (jusqu'à 18V).

A noter que l'on peut utiliser le 74HC4050 voire le 74HC125, mais attention, il sont beaucoup moins tolérants sur l'alim. Au delà de 7V ils claquent, tandis que le bon vieux CD4050 encaisse du 20V, donc peut tolérer des erreurs de manip.


Arduino, programmation, résilience et librairie Olduvaï 4050c10
(image electroniqueamateur.blogspot)

Avec ce brochage SD ou microSD :
Arduino, programmation, résilience et librairie Olduvaï Sd-car10

Au niveau du slot, on peut bricoler un truc rapide avec des broches, mais on arrive vite aux problèmes de mauvais-contact; c'est juste pour essayer.

Arduino, programmation, résilience et librairie Olduvaï Capt1056

Perso j'ai dessoudé un slot pour bidouiller un module dédié :

Arduino, programmation, résilience et librairie Olduvaï Capt1057

Alors attention lors des raccordements, bien utiliser le 3,3V de l'Arduino. Une confusion est si vite arrivée vu qu'elle se trouve juste à côté du 5V dévil

Arduino, programmation, résilience et librairie Olduvaï Capt1058

L'exemple d'utilisation du tuto en lien est assez modulable. J'ai juste modifié quelques lignes pour créer un log du compteur Geiger qui enregistre le nombre de coups comptés à chaque minute.

Code:

#include <SD.h>

const int chipSelect = 10;  //pin de l'Arduino reliee au CS du module SD
Sd2Card card;
SdVolume volume;
SdFile root;
File myFile;

byte SaveToSD(unsigned int PulseGeiger)
{

  pinMode(chipSelect, OUTPUT);     // 10 sur Uno/Nano 53 si ArduinoMega.


  // On vérifie si une carte est présente
  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    return 1; //Pas de carte
  }

  // On trouve le volume
  if (!volume.init(card)) {
    return 2; // La carte n'est pas formatee ou avarie (en général faux-contact)
  }

  // on sort la liste des fichiers déjà présents

  // On se prepare a jouer dans les fichiers
  if (!SD.begin(chipSelect)) {

    return 3; //Echec de l'initialisation
  }

  // ouverture du fichier pour ecriture (il sera créé s'il n'existait pas déjà)
  myFile = SD.open("GEIGER.csv", FILE_WRITE);
  // Si l'ouverture du fichier a fonctionné, on écrit quelque chose à l'intérieur
  if (myFile) {
    //Ecriture dans le fichier

    for (int i=0;i<100;i++){
      
  
    myFile.print(millis());
    myFile.print(";");
    myFile.print(PulseGeiger);
    myFile.println(";");
    // fermeture du fichier
     }
    myFile.close();


  }
  else {
    return 4; //Impossible d'ouvrir le fichier pour l'ecriture
  }
    return 0;
}


byte ReadFromSD(){

  // on ouvre le fichier, et on vérifie son contenu A voir pour parser le nom est qq infos en apramètres.
  myFile = SD.open("GEIGER.csv");
  if (myFile) {
    Serial.println("Contenu du fichier:");  
    // rOn lit jusqu'à épuisement du fichier > moniteur série
    while (myFile.available()) {
      Serial.write(myFile.read());
    }
    // Fermeture du fichier
    myFile.close();
    return 0;
  }
  else {
    // si l'ouverture du fichier a échoué, on l'indique
    Serial.println("impossible d'ouvrir le fichier pour la lecture");
    return 1;
  }

}

J'ai un fichier log CSV sur la carte SD directement lisible dans n'importe quel soft. En A la durée en ms depuis l'allumage du circuit, en B le nombre de CPM.
Arduino, programmation, résilience et librairie Olduvaï Capt1059

C'est juste pour l'intégration rapide. J'envisage une écriture type Date/Tube/CPM et autres infos et de laisser la carte ouverte plutôt que d'invoquer open à chaque fois. Ici mon appel est calé un peu à l'arrache dans le programme, je pense le réaliser lors du saut de minute. afin d'avoir exactement une seconde entre chaque. En effet :

Quelques considérations sur l'écriture SD:
Elle n'est pas immédiate; en fait toutes les fonctions travaillent avec un buffer. Tant qu'il n'est pas plein ou que la connexion avec la carte n'est pas fermée (ce que je fais ici), rien n'est réellement écrit sur la carte SD. C'est l’explication du pourquoi ces routines mangent la moitié de la RAM de l'Arduino.

Lors  de l'intégration plus large dans un code, il faut commencer à faire attention au niveau de l'ajout des fonctions SD car ce genre d'opération prend en général 20ms. A l'échelle d'un programme entier c'est énorme, notamment si on utilise toutes sortes d'interruptions comme dans le montage Geiger et que l'on enregistre les logs à chaque seconde.
Il y a plusieurs écoles sur l’interaction buffer/interruption. Certaines conseillent de mettre en pause les interruptions et les reprendre après la phase d'écriture.
Perso, j'aurais tendance à réduire les cycles d'écriture (une fois par minute comme ici plutôt qu'à chaque seconde).

Pour la suite du topic

J'ai plusieurs trucs dans les tuyaux. Le principal projet étant l'ajout d'un shield réseau pour relier le compteur Geiger à internet et lui faire remonter le débit de dose ambiant sur un serveur (je check avec le serveur Oldu.fr dispo en haut du forum).
En gros, cela mettrait en ligne en temps réel la radioactivité ambiante de mon coin, un peu comme les balises type Teleray.
Mais j'envisage un peu de fonctions, dont proposer deux débits : gamma et alpha, sur filtre à charbon actif clind'oeil

________________________________________________________
L'expérience est une lumière qui n'éclaire que ceux qu'elle a déjà brûlés. Cédric Dassas


甩葱歌 - 古箏 - Distant Pulsar - Un Mauvais Fils - 25 Years of Zelda - Machinarium - Récapitulatif des projets électroniques - [Chroniques du Bunker de L'Apocalypse] - Projet Geiger - Culture ethnobotanique en France
tarsonis
tarsonis
Administrateur

Masculin Nombre de messages : 10680
Age : 37
Localisation : Grand Est
Loisirs : Trek, ethnobotanique, électronique DIY, nucléaire, médecine, post apo.
Date d'inscription : 21/05/2008

Canis Lupus, vigo, Nadia et Le castor bricoleur aiment ce message

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Réparer une Sardine Box

Message par tarsonis Ven 27 Jan 2023 - 11:58

Salut à tous,
petit aparté aujourd'hui avec un projet Arduino HS qu'on m'a donné au dernier Repair Café.

Il y a plusieurs points intéressants à développer, notamment le processus de dépannage, et analyse erreurs classiques de design.

A priori la personne n'était pas la même que celle qui a tenté de l’assembler mais l'a récup quelques euros sur LBC, finalement faute de doc accessible elle a abandonné et me l'a offert.

Donc le projet s'appelle la "Sardine Box", réalisé il y a quelques années par des makers. Bon pas de chance, le site web qui en parle est complètement HS (je ne le cite pas si jamais l'auteur a voulu le supprimer, mais il est facile à remonter). On va se débrouiller avec ce qu'il reste de Web Archive clind'oeil

Arduino, programmation, résilience et librairie Olduvaï Sardin10

Tout d'abord, au niveau du circuit, on repère un clone d'Arduino Nano, deux potentiomètres, un interrupteur à glissière, un haut parleur, un bouton poussoir, un circuit survolteur 5V, et un rack de 2 piles AA.

Arduino, programmation, résilience et librairie Olduvaï Sarda10

Mais tout de suite les soucis sautent aux yeux :
- les soudures débordent un peu de partout : Vin (5V) touche presque la masse, les entrées A0 et A1 se touchent, les pattes des potentiomètres touchent la carcasse du haut parleur.
Arduino, programmation, résilience et librairie Olduvaï Sarda110

La patte de la résistance reliée au bouton poussoir touche deux entrées (pas critique mais pas terrible), vue de Vin/GND et A0 qui touche aussi la piste Ref....

Arduino, programmation, résilience et librairie Olduvaï Sardb110

J'ai oublié de prendre la photo, mais en dessous il y a également les soudures de l'interrupteur et boutons qui touchent un peu la plaque.

Bon en l'état si on finit le montage, il y a de fortes chances -au mieux- qu'il ne fonctionne pas ou -au pire- de cramer l'Arduino.

Première étape : on dessoude tout pour isoler le Nano. Je le branche à vide sur l'IDE pour tenter de communiquer avec.

Pas de chance, j'ai la fameuse erreur avrdude: stk500_recv(). C'est pas hyper spécifique, mais rend le pronostic plutôt négatif. On commence par checker la Zener D1 du Nano (qui brûle en premier en cas de court-circuit), elle est ok.
Des différents diagnostics, j'ai l'impression que le problème tourne autour de l'interface USB avec le FT232 (ici à droite) :
Arduino, programmation, résilience et librairie Olduvaï Capt1072
Sur ce coup, j'ai eu un peu de chance car en projetant de la dessouder, j'ai remarqué une très petite goutte de soudure qui faisait faux-contact entre deux broches.

En grattant un peu, tout fonctionne, ouf.

Remontage en isolant les interrupteurs

Arduino, programmation, résilience et librairie Olduvaï Capt1073

Ainsi que la résistance, les broches des potentiomètres et soudures propres.

Arduino, programmation, résilience et librairie Olduvaï Capt1074

Au niveau de la schématique, on comprend que le bouton poussoir sert à envoyer une impulsion en entrée et A0 et A1 sont les entrées des potentiomètres.
Pour les intéressés, j'ai pu faire ressortir une miniature du cache internet; même pixelisée, elle reste compréhensible pour le câblage :
Arduino, programmation, résilience et librairie Olduvaï Capt1075

Le projet d'origine contient un condensateur chimique en série avec un haut parleur piezo. Il n'est pas nécessaire avec un HP 8Ω.
J'ai changé le design en plaçant l'interrupteur avant le circuit survolteur car même montage éteint le circuit continue d’être alimenté et j'ai collé le poussoir sur D8 vu que le câble était trop court.

J'ai aussi trouvé la page en cache concernant le code (j'ai modif la PIN 8 pour le bouton)

Code:
int gamme[] = {
  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
};
int lastBouton = LOW;
boolean maintien = false;

void setup() {
  
  pinMode(8, INPUT);
 // pinMode(3, OUTPUT); (pour VCA)
 //Serial.begin(9600);
 tone(7, 880);
 delay(100);
 tone(7, 1760);
 delay(700);
 noTone(7);

    
}

void loop() {
  // read the sensor:
  int sensorReading = analogRead(A0);
  int sensorReading2 = analogRead(A1);
  int bouton = digitalRead(8);
    
  int range = map(sensorReading, 0, 1023, 0, 3);
  int thisPitch = map(sensorReading2, 0, 1023, 55, 800);
  int i = map(sensorReading2, 0, 1023, 0, 11);
  int tune = map(sensorReading, 767, 1023, 0, 255);
  int del =  10;
  
  //digitalWrite(3, HIGH); (pour VCA)
   if ((bouton == HIGH) && (lastBouton == LOW)) {
       maintien = !maintien;
   }
  
    

 //  Serial.println(range); (pour debug)
  switch (range) {
    case 0:    
    del = map(sensorReading, 0, 255, 0, 200);
     if (maintien == HIGH) {
      tone(7, random(0, thisPitch));
      break;
      }
      else {
        noTone(7);
      }  
    
        
      
    case 1:  
    if (maintien == HIGH) {
      tone(7, thisPitch);
      
      break;
      }
      else {
        noTone(7);
    
    }
    
      
      case 2:    
      if (maintien == HIGH) {
      
      
      tone(7, (110*gamme[i]+tune));
      break;
    
      }
      else {
        noTone(7);
      }  
      
      
  }
  delay(del);        //delay fixe 10ms sauf pour mode random
  lastBouton = bouton;
}


Le code reste relativement simple, le poussoir sert à mettre le montage en pause en coupant le son en conservant l'état actuel. Le potentiomètre de gauche ajuste la hauteur du son émis et celui de droite la fréquence de transition. Le tout avec un peu d'aléatoire dedans. En gros un thérémine amélioré.

Alors l'ensemble est prévu pour être dans une boite à sardines. Franchement c'est possible uniquement si on isole tout le circuit au vu des masses qui se baladent partout :
Arduino, programmation, résilience et librairie Olduvaï Capt1076


Projet fini
Arduino, programmation, résilience et librairie Olduvaï Sardin11

Le petiot s'amuse maintenant comme un fou avec.

Bon au final, à mon avis quelques points à retenir :
- le design n'est pas à 100% terminé, notamment côté survolteur
- les soudures sur Nano peuvent présenter quelques soucis aux débutants. Amha soit plier les pattes vers l'extérieur, soit orienter les apprenants sur Uno ou alors utiliser des fils femelle/mâle que l'on trouve dans tous les coffrets.
- énormément de risques de faux-contact : résistance, interrupteurs, masses, potentiomètres. Lors de la mise en place dans la boite, je ne vois pas comment ne pas en avoir sans tout scotcher dans de l'isolant.
- les infos disparaissent assez vite d'internet. Avec de la chance on récupère avec WebArchive sinon il faut faire un peu de reverse clind'oeil

________________________________________________________
L'expérience est une lumière qui n'éclaire que ceux qu'elle a déjà brûlés. Cédric Dassas


甩葱歌 - 古箏 - Distant Pulsar - Un Mauvais Fils - 25 Years of Zelda - Machinarium - Récapitulatif des projets électroniques - [Chroniques du Bunker de L'Apocalypse] - Projet Geiger - Culture ethnobotanique en France
tarsonis
tarsonis
Administrateur

Masculin Nombre de messages : 10680
Age : 37
Localisation : Grand Est
Loisirs : Trek, ethnobotanique, électronique DIY, nucléaire, médecine, post apo.
Date d'inscription : 21/05/2008

Canis Lupus, vigo et logan aiment ce message

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par tarsonis Mer 12 Avr 2023 - 12:25

Salut à tous,
Aujourd'hui, petite bidouille toute simple en attendant la suite (2 posts sur le feu avec Arduino...).

Il vous faudra une carte Arduino, une prise jack 2,5mm et une 3,5mm de récup.
Ça va parler reprogrammation Baofeng.... mais sans une seule ligne de code avec Arduino; donc un montage à la portée du débutant.

Par mégarde, on m'a flashé ma Baofeng en triturant les boutons... un petit reset qui m'a viré toute la configuration et les fréquences... dévil
On peut la reprogrammer via le câble adaptateur USB/série-jack spécifique et CHIRP sur PC quelconque... mais si on n'a pas le câble avec soi ? Ah ah, les bricoleurs nous diront qu'il suffit d'utiliser un simple convertisseur USB/Série avec une petite commande sur le net et quelques jours/semaines de livraison.

Mais il est possible de faire un peu plus "simple", faute de mieux clind'oeil

En effet, la plupart des cartes USB Arduino sont pourvues d'un convertisseur USB/Série pour communiquer avec le microcontrôleur. Aujourd'hui, on va utiliser cette fonction pour reprogrammer une Baofeng (le principe fonctionnera sans doute avec la plupart des appareils de la même catégorie).

L'article précédent mentionnait ce convertisseur, car je pensais qu'il était cramé sur la carte Nano de récup. Ici, avec mon Uno, le convertisseur est près du port USB, c'est un ATmega16U2. En fait, il s'agit même d'un microcontrôleur à part entière. Un peu overkill pour cette fonction, mais sans doute utilisé à la place du FT232 pour une question de coût.

Arduino, programmation, résilience et librairie Olduvaï Capt1101

Le microcontrôleur Arduino ATmega328P est ici désactivé en reliant RESET à la masse, on ne va utiliser que le convertisseur, d'où l'absence de programmation purement Arduino clind'oeil

Au niveau câblage, la Baofeng communique via la prise Jack 3,5mm pour Rx (de l'Arduino) et la Jack 2,5mm pour Tx et la masse (idem), selon le schéma :
Arduino, programmation, résilience et librairie Olduvaï Capt1095

Je conseille évidemment de vérifier toutes la connectique à l'ohmmètre.

On relie l'ensemble et on allume la Baofeng à volume Max : Reset à la masse et les 3 broches vers les prises jack.

Et on teste avec CHIRP que tout fonctionne via Radio > Download From Radio.

Arduino, programmation, résilience et librairie Olduvaï Capt1098

On voit au passage sur la carte que Tx et Rx clignotent :

Arduino, programmation, résilience et librairie Olduvaï Capt1097

Bon évidemment ma liste est quasiment vide:

Arduino, programmation, résilience et librairie Olduvaï Capt1099

Et on teste un Upload avec le premier fichier image qui nous tombe sous la main clind'oeil

Arduino, programmation, résilience et librairie Olduvaï Capt1100

Voilà, rien de bien sorcier fumeur

________________________________________________________
L'expérience est une lumière qui n'éclaire que ceux qu'elle a déjà brûlés. Cédric Dassas


甩葱歌 - 古箏 - Distant Pulsar - Un Mauvais Fils - 25 Years of Zelda - Machinarium - Récapitulatif des projets électroniques - [Chroniques du Bunker de L'Apocalypse] - Projet Geiger - Culture ethnobotanique en France
tarsonis
tarsonis
Administrateur

Masculin Nombre de messages : 10680
Age : 37
Localisation : Grand Est
Loisirs : Trek, ethnobotanique, électronique DIY, nucléaire, médecine, post apo.
Date d'inscription : 21/05/2008

Canis Lupus, Da, victor81, Kyraly et Encatimini aiment ce message

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par tarsonis Jeu 13 Avr 2023 - 12:42

Post temporaire : je viens de voir plusieurs Uno et Nano à 7E sur leboncoin. Ca fait 10E tout compris avec les frais d'envoi clind'oeil

________________________________________________________
L'expérience est une lumière qui n'éclaire que ceux qu'elle a déjà brûlés. Cédric Dassas


甩葱歌 - 古箏 - Distant Pulsar - Un Mauvais Fils - 25 Years of Zelda - Machinarium - Récapitulatif des projets électroniques - [Chroniques du Bunker de L'Apocalypse] - Projet Geiger - Culture ethnobotanique en France
tarsonis
tarsonis
Administrateur

Masculin Nombre de messages : 10680
Age : 37
Localisation : Grand Est
Loisirs : Trek, ethnobotanique, électronique DIY, nucléaire, médecine, post apo.
Date d'inscription : 21/05/2008

Revenir en haut Aller en bas

Arduino, programmation, résilience et librairie Olduvaï Empty Re: Arduino, programmation, résilience et librairie Olduvaï

Message par Contenu sponsorisé


Contenu sponsorisé


Revenir en haut Aller en bas

Page 1 sur 2 1, 2  Suivant

Revenir en haut

- Sujets similaires

 
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum