Articles Tagués ‘Arduino’

Bonjour à tous,

Aujourd’hui je vous propose un projet que j’ai réalisé en à peine quelques heures sur une plateforme qui m’était inconnue ! Bon pas totalement vous allez le voir car intégrée à l’IDE Arduino 😉

Contexte et problématique

Le point de départ de tout ça c’est mon meilleur ami, enfin son portail d’entrée de sa copropriété pour être précis. En effet, sa copropriété ne lui a refilé qu’une seule télécommande, ce qui n’était pas forcément très dérangeant au départ mais maintenant il a un colocataire … Ca devenait compliqué …

Donc au départ quand il me présente le problème, je me dit basiquement « oh y’a 99% de chance pour que ça soit du 315 MHz, du 433 MHz ou du 968 MHz et j’aurais donc le loisir de me servir d’une copie chinoise » sauf que … j’amène mon matos d’analyse radio (si le sujet vous intéresse, chercher « RTL SDR » sur google 😉 ) eeeeeetttt … Niet, j’arrive à rien analyser … Ok tu le prends comme ça ? J’ouvre l’engin, regarde la puce, en galérant un peu je tombe finalement sur la fiche de donnée et outch : c’est du 3 kHz ! Première fois que je croise ça perso … Bref j’ai écumé le net pas moyen de trouver une télécommande dans cette fréquence. Bref on l’avais plutôt dans l’os pour le coup.

Et puis quelques jours plus tard je me dis que je pourrais tout simplement attaquer le problème par un autre bord : et si je connectais la télécommande par le wifi et un relais ? Et oui, je peux simuler l’appui sur le bouton avec un relais piloté par un serveur connecté à internet. Alors c’est possible car je ne l’avais pas précisé, sa télécommande marche depuis son appartement. Et aujourd’hui, avec l’ESP8266 les prix pour se faire ce genre de montage ont drastiquement chutés !

ESP8266 et NodeMCU

Let’s talk about the ESP8266 🙂

Alors pour ceux qui n’ont pas ou peu entendu parlé, l’ESP8266 est un microcontroleur ARM avec tout ce qu’il faut pour faire du wifi pour un prix dérisoire (on trouve des modules à 3$). Au départ c’était pas mal de bricolage, mais à 3$ ça a motivé beaucoup de bidouilleurs, et c’est aujourd’hui beaucoup plus facile et fiable, notamment grace à une petite carte de développement et un firmware portant tout deux le même nom de NodeMCU. Vous pouvez la trouver ici pour 7,45$.

A quoi elle ressemble :

Pin mapping :

Une petite note sur le sujet, malgré la sérigraphie D0 D1 etc … ressemblant furieusement à celle des Arduino, la numérotation est celle marquée sous la forme « GPIOx » et il faut utiliser le x dans l’IDE Arduino comme numéro de pin (donc par exemple, digitalWrite(5,HIGH) pour le GPIO5 sérigraphié « D1 »).

L’avantage c’est que c’est une « vraie » board de développement : il y a tout ce qu’il faut pour la programmer, et brancher des choses dessus (chose plus complexe avec les modules seuls).

Pour l’installer sur votre IDE Arduino (version 1.6.4 minimum) je vous invite à suivre cette procédure très simple.

Après c’est comme une Arduino : même langage et il y a de nombreux exemples pour vous montrer ce que la bête apporte.

Fonctionnement d’internet et du projet

Il me parait important avant d’expliquer certains principes fondamentaux et indispensables ici sur le fonctionnement d’internet. Tout d’abord la notion d’adresse IP et de DNS. Alors l’adresse IP vous en avez sans doute entendu parler c’est ce chiffre étrange qui ressemble à 186.14.26.54 par exemple. En fait,  4 valeurs allant de 0 à 255 (un octet quoi) séparé par des points. Ce numéro correspond à une adresse dans un réseau donné. Chez vous si vous n’avez pas de réseau bidouillé (auquel cas de toute façon vous n’avez même pas pris la peine d’attaquer la lecture de ce paragraphe) vous avez donc : une adresse IP sur internet (votre box) et une adresse par périphérique réseau (votre PC, votre tablette en wifi, votre smartphone en wifi …). Toutefois les adresses réseaux « internet » et « locale » n’ont rien à voir. C’est un petit peu comme « avenue du Général de Gaulle » : y’en a une à Paris, une à Marseille etc … Pourtant ce n’est pas la même avenue 🙂 Et sinon comme toute adresse elle permet de transmettre des messages à un destinataire précis.

Concrètement prenons un exemple : vous allez sur un site internet. En tapant l’adresse IP du site dans votre navigateur internet, vous envoyez une requête de type GET vers cette adresse pour récupérer le site internet et l’afficher (qui est en fait un simple fichier texte codé). Cette requête fait parti du protocole HTTP. En fait internet c’est des messages qui transitent. Mais il faut un peu mettre tout le monde d’accord organiser sécuriser tout ça. La intervient le protocole TCP/IP qui permet d’ouvrir un « canal » de discussion. Après il faut savoir ce qu’on demande : arrive le protocole HTTP. C’est exactement comme deux personnes qui discutent : on a des cordes vocales pour produire différents sons, ensuite on forme des mots, puis des phrases et on rajoute la langue et la politesse par dessus « coucou moi c’est Bob » « coucou moi c’est Peter ». Internet c’est un peu pareil, et même en élargissant c’est le cas de toute les communications numériques.

Bref revenons en à notre site internet : vous aller me dire « mais moi je tape pas une adresse IP dans ma barre de navigation ??! » Et oui vous tapez http://www.google.fr ou http://www.arduino.cc. C’est la que le serveur DNS fait son apparition : quand vous taper une adresse, un appel vers un serveur DNS (vous pouvez configurer ça dans votre panneau de configuration) est réalisé pour lui demander quel est l’IP correspondant à ce site. Et hop magique vous récupérez l’adresse IP du site et entamer la discussion avec 🙂

« Ok et mon réseau local à moi ? » Donc maintenant vous avez compris que vous pouvez taillé le bout de gras avec tout internet juste avec votre navigateur. Donc maintenant imaginons vous êtes au boulot, vous connaissez l’adresse IP de votre maison (au  passage, aujourd’hui tous le monde est en IP fixe, c’est à dire qu’elle ne change normalement jamais, il y a quelques années ce n’était pas le cas) et que vous la tapez dans votre navigateur. Sauf que qui va répondre à l’autre bout ? Personne car vous n’avez pas de serveur. Votre message va arriver à votre box qui fait office de routeur, c’est à dire que c’est la standardiste : « bonjour vous voulez vous adressez à qui ? ». Car si vous faites le test chez vous à partir de différents PC ou autre objet connecté à votre réseau, vous verrez que vous avez la même IP sur internet. C’est normal, c’est le routeur votre point d’entrée au réseau internet. Après il y a votre réseau local ou vous avez une autre adresse IP, cette fois différente pour chaque objet connecté à votre réseau. Et la vous allez me dire « mais comment je fais alors pour m’adresser à un périphérique de mon réseau local depuis l’extérieur ? » c’est la que la notion de « port » intervient. En effet, votre routeur (« la standardiste ») reçoit une communication sur son adresse IP internet, mais reçoit en plus un numéro de port. C’est ce numéro qui va dire ensuite sur le réseau local avec qui vous voulez communiquer. Typiquement en http c’est le port 80 qui est utilisé. C’est la aussi transparent pour l’utilisateur, quand vous visitez un site internet, en fait l’adresse IP complète envoyée est de la forme : xxx.xxx.xxx.xxx:80

Mais les navigateurs prennent en charge des numéros de port différents, il suffit de le spécifier en tapant http://xxx.xxx.xxx.xxx:yy yy étant votre numéro de port. Mais la vous allez me dire « mais comment il sait que ce port est pour ce périphérique précis de mon réseau  ? » Et bien c’est la où il faut aller configurer sa box pour lui dire que les messages arrivant sur ce port la doivent être adressés à cette IP la du réseau local.

Sur la Freebox révolution voici la démarche .

IP de destination = IP de l’ESP8266

Protocole = TCP

IP Source = toute

Port de début = Port de fin = port avec lequel vous lancerez l’appel

Port de destination = port que l’on va paramétrer pour le serveur ESP8266.

En lisant ces deux dernières lignes vous avez peut-être compris que le numéro de port que vous allez taper dans votre navigateur n’est pas obligatoirement celui que l’on va spécifier sur notre serveur. On pourra donc se connecter en tapant par exemple xxx.xxx.xxx.xxx:260 alors que le serveur sera sur le port 504 pourvu que le routeur soit configuré avec un port de début 260 et un port de destination 504 pour l’IP local de l’ESP8266.

Sur les autres box ce sera guère différent dans l’esprit, attention certaines font la différence entre le firewall et le routeur, ce qui fait qu’il faut prévoir la configuration dans les deux et ne pas se retrouvé avec une redirection bloquée par le pare-feu 😉

Bon j’espère vous avoir appris plus de trucs que de vous avoir embrouillé mais il me semblait indispensable de préciser ces points afin de comprendre le code (très court en plus) qui va suivre.

Montage

Le montage est très simple : la carte, un relais, et on tire les deux fils du bouton. J’ai ajouté également un bouton manuel pour pouvoir piloter la télécommande même si tout est planté et sans avoir forcément à passer par un PC ou un smartphone pour ouvrir le portail. Pour la petite histoire, je monte le projet et pouf marche pas … Hum je regarde mon relais : arf 12V !! Donc il ne se fermait pas à 5V. J’avais pas de matos sous la main donc j’ai viré le relais et j’ai utilisé le mosfet qui pilotait le relais pour faire le contact. Voici les deux schémas en un, au crayon gris celui que j’avais imaginé, en rouge les raccordements une fois le relais dessoudé :

SCAN2

La node MCU est simplement alimenté par un chargeur USB de téléphone.

Programmation

On va donc construire un mini serveur, qui quand il recevra une requête exécutera différentes actions. On va faire en sorte de lui donner les fonctions suivantes :

  • répondre par une page un bouton « ouvrir »
  • procéder à l’ouverture en elle même
  • quand l’ordre d’ouverture est exécuté envoyer une page de confirmation

On va donc lancer son IDE Arduino et commencer par inclure les librairies qu’il faut :

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

 

Ensuite on va créer notre serveur sur un port normalement libre (grosso modo éviter les ports « classiques » des différents protocoles internet, une recherche google vous les donnera).

long port = 504;
ESP8266WebServer server(port); // serveur HTTP

 

On va ajouter une petite fonctionnalité gadget qui est le mDNS : vous vous souvenez du serveur DNS ? Ca marche sur internet, mais chez vous ? Et oui y’en a pas … Donc si vous voulez accéder à votre module sans connaitre son IP par coeur, il faut utiliser du mDNS. L’idée c’est d’envoyer un message à tout le monde le réseau et répond qui se sent concerné. On lance donc un « serveur » mDNS qui permettra de répondre à un domaine précis. Ici on va rentrer ça :

MDNSResponder mdns; // serveur mDNS

...

if (mdns.begin("esp8266", WiFi.localIP())) {
Serial.println("MDNS responder started");
}

 

Et on pourra appeler notre module dans le navigateur, connecté sur son réseau local (ça ne marchera pas depuis l’extérieur) en tapant « esp8266.local ».

Ensuite on va définir les réponses de notre serveur :

server.on("/", handle_root);
server.on("/open", handle_open);

 

Avec ces commandes, si je tape monip:monport/open j’exécute directement la routine d’ouverture, et il me répondra avec « opening ». Si je tape monip:monport il me répondra avec une page internet que vous visualisez ici en HTML. Lorsque j’appuierais sur le bouton « Ouvrir » de la page, ça appellera la page /open et donc l’ouverture.

Evidemment il faut se raccorder au wifi, on spécifie donc ces paramètres de connexion au départ :

char* ssid = "xxxxx"; // votre SSID
char* password = "yyyyyyy"; // votre mot de passe wifi

 

Le reste du code est au final assez logique : on pilote le relais, on lance la connexion, on lance les serveurs et on debug sur le port série. Ce qui donne au final :

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

char* ssid = "xxxxx"; // votre SSID
char* password = "yyyyyyy"; // votre mot de passe wifi
MDNSResponder mdns; // serveur mDNS
long port = 504;
ESP8266WebServer server(port); // serveur HTTP

const int led = 16; // led integree au NodeMCU, attention logique inverse
const int relay = 5; // relais connecte au GPIO5

void setup(void) {

/* Configuration des entree/sortie */
pinMode(relay, OUTPUT);
pinMode(led, OUTPUT);

digitalWrite(led, 1);
digitalWrite(relay, 0);

Serial.begin(115200); // initialisation du port serie

connect(ssid, password); // connexion au reseau Wifi

Serial.println("");

/* demarrage du serveur mDNS sur esp8266.local */
if (mdns.begin("esp8266", WiFi.localIP())) {
Serial.println("MDNS responder started");
}

/* ajout des actions du serveur */
server.on("/", handle_root);
server.on("/open", handle_open);

server.begin(); // demarrage du serveur

Serial.println("HTTP server started");
}

void loop(void) {

server.handleClient(); // gestion du serveur

/* Si connecté au wifi alors la LED s'allume */
if (WiFi.status() == WL_CONNECTED) digitalWrite(led, 0);
else digitalWrite(led, 1);

}

/* Routine pour se connecter à un reseau wifi */
void connect(char *_SSID, char* _PWD) {

Serial.println("");
Serial.print("Connecting ");
Serial.print(_SSID);
Serial.print(" password = ");
Serial.print( _PWD);

WiFi.begin(_SSID, _PWD);
Serial.println("");

int h = 0;

// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");

if (h++ > 40) { // si trop long on abandonne
Serial.println();
Serial.println("Failed to connect");
return;
}

}

Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());

}

/* Action serveur sur /open */
void handle_open() {
server.send(200, "text/plain", "opening"); // repond "opening"
open(); // actionne le relais
}

void handle_root() {

/* page[] contient notre page web et renvois vers le domaine /open si on appuie sur le bouton */
char page[] = "<h1>Ouverture portail</h1><p><a href=\"open\"><button>Ouvrir</button></a></p>";

server.send(200, "text/html", page); // repond avec la page web codee en HTML

}

void open() {

digitalWrite(relay, 1);
Serial.println("Opening");
delay(1000);
digitalWrite(relay, 0);

}

 

Sur Github

Boitier

J’ai fait une jolie boîte en medium découpée à la découpeuse laser 🙂 pour sa fabrication au total ça m’a pris …. 10 min. Comment ? Makercase.com est un site qui vous permet de générer des plans de boitier simple. J’ai rentré mes dimensions, l’épaisseur de mon matériau et le type d’assemblage et hop un fichier svg. Alors la je trouve ça assez con vu que c’est quand même le DXF qui est le fichier de base dans le domaine. On doit donc l’ouvrir sous Inkscape, tout sélectionner, faire « convertir objet en chemin » et enregistrer sous au format DXF pour avoir un fichier exploitable par la découpeuse. Mais avant un petit tour sous DraftSight pour ajouter les trous pour la fixation de la carte, le relais et le bouton, et un passage pour le câble d’alimentation. On découpe, et voila le résultat (désolé photo avec téléphone de secours) :

photo (1)

photo (2)

photo (5)

photo (4)

photo (7)

Classe hein ?

Au passage vous voyez :

  • ma « correction » pour virer le relais et utiliser le mosfet.
  • les fils sortant de la télécommande (désolé j’ai oublié de prendre une photo des deux fil soudés au bouton) elle même collé au fond du boitier avec du double-face.
  • la nodeMCU est à l’envers, pour que je puisse accéder au pins par au-dessus.
  • le bouton poussoir en façade.

Fichier DXF (faites clic droit « enregistrer sous »)

Utilisation

Il me suffit maintenant soit de taper « esp8266.local » en local, ou « votreip:port » depuis l’extérieur pour accéder à ça :

(bien évidemment sur les captures j’ai pas laissé l’IP et le port de mon ami 😉 )

cc

On clique et normalement si tout va bien votre relais se ferme et il s’affiche :

cc2

Mais poussons le vice un poil plus loin …

App Android

Et ouais 🙂 alors y’a un super outil pour les gros noob d’Android comme moi, c’est appinventor. il vous suffit de créer un compte, et vous pouvez développer des applis toute simples, avec un codage graphique à la codeblock. C’est très intuitif. En plus le débuging est simple : soit par connexion USB avec votre tel, soit par wifi en installant une application dédiée. A la fin quand votre projet est fini, vous pouvez : soit générer un QR code qui vous renverra un lien de téléchargement temporaire, soit télécharger le fichier .apk à installer en manuel (la aussi je vous renvois vers google c’est tout simple).

Voici l’appli : http://ai2.appinventor.mit.edu/#5889257248391168

Bon l’écran de base c’est un gros troll pour mon pote avec un magnifique montage que vous pouvez faire péter évidemment 😉

Il suffit d’aller dans « Paramètres », de rentrer votre IP et votre port et voila ça devrait fonctionner. Quand on appuie sur le bouton « ouvrir » ça envoi une bête requête, tant que l’app ne reçoit pas « opening » le bouton reste verrouillé ou bien il se déverrouille au bout de 5 secondes.

Une petite base donnée (« tinyDB ») permet à la fois de garder en mémoire les données pour ne pas avoir à les retaper à chaque lancement, et de passer les infos d’un screen à l’autre. En effet sur AppInventor on ne peut pas créer de variables globales, donc le seul moyen de se faire passer des infos d’un screen à l’autre c’est de passer par une base de donnée …

Au passage dans paramètre certains champs sont prévus mais inactifs : en fait à l’origine je pensais passer par du MQTT plutôt que du HTTP mais ça nécessitait trop de moyens …

Limites et conclusion

Un projet bouclé en à peine quelques heures, grâce à une série d’outils puissantz de simplicité (bon j’imagine que si vous débutez complètement ça vous prendra plutôt quelques jours, surtout si tout ne marche pas du premier coup …). Ca démontre bien toutes les mutations en cours dans le domaine et qu’on est loin du temps ou il aurait fallut 4 ingénieurs pendant un mois pour faire ça …

Alors la principale limite ici c’est que ce n’est pas du tout sécurisé, n’importe qui qui a votre adresse IP et le bon port peut piloter votre système. Ici c’est un portail collectif d’une grande résidence donc bon … Et faut arriver à dégoter la bonne IP et le bon port ! Mais bon dans l’absolu c’est assez facilement crackable pour quelqu’un qui veut vous nuire, donc n’utilisez pas ce système pour votre porte d’entrée ou de garage.

Une autre limite est que si internent est capricieux chez vous, bin vous ouvrirez plus rien …

En terme de coût on est tout simplement sous la barre des 10€ sans pousser le vice outre mesure. Avec un circuit dédié on pourrait même tomber sous les 5€ sans problème 🙂

A bientôt et n’hésitez pas à poster vos questions en commentaire de cet article 😉

Publicités

[Tutorial] Arduino, Serial et ASCII

Publié: 18 septembre 2014 dans Tutoriaux
Tags:,

Bonjour à tous,

Aujourd’hui un petit article sur un sujet assez redondant sur le forum Arduino, à savoir l’ASCII et la différence en Serial.write() et Serial.print().

Rappels

Si vous lisez cet article c’est surement que vous débutez et il me semble indispensable pour bien comprendre la suite d’avoir de bonnes bases.

La liaison série, comme toute transmission de données, et toutes les données informatique en général, sont toujours en binaire. Quelque soit la façon dont vous remplissiez une variable, au fond du fond, dans la mémoire du microcontrôleur, ça sera toujours des 0 et des 1. Toutes les autres représentations (décimal, hexa, chaines de caractères …) ne sont que des représentation « de confort » uniquement la pour nous humains.

Pour en revenir à nos moutons, quand on transmet des informations par liaison série, on ne transmet que des 0 et des 1, soit un nombre. Dans le cas de ce type de liaison, on transmet les informations par paquet de byte ou d’octet (c’est la même chose), soit 8 bits, donc un nombre compris entre 0 et 255. Mais maintenant vous allez me dire « pourtant je peux bien faire des Serial.print(« Hello world ») ! Il sont où tes nombres ??! » J’y viens 😉

L’ASCII

Un terme que l’on maudit presque au début alors que c’est enfantin : l’ASCII c’est tout simplement une table qui pour un nombre donné, renvoi un caractère donné. Il s’agit simplement en fait de mettre d’accord des systèmes pour dire : tel nombre c’est un « A », tel nombre c’est un « z » etc … Voici la table ASCII :

Colonne CHR on retrouve les caractères disponibles, les autres colonne représente leur code ASCII sous différentes formes mathématique. Supposons que deux systèmes veuille communiquer, et que le système A veuille envoyer « Arduino » au système B. A va donc devoir envoyer 7 octets, chaque octet correspondant à une lettre, soit :

65,114,100,117,105,110,111

Quelques remarques :

– « Mais y’a que 128 nombre dans ta table ! » en effet, la table ASCII de base ne contient que 128 caractères. Il existe une table dite étendue qui en contient 255 mais qui n’est pas prise en charge par Arduino. C’est pour celà que si vous faites Serial.print(« Mesuré ») vous allez recevoir dans le moniteur série « Mesu » + un caractère bizarre car l’Arduino n’a pas la correspondance pour le « é »

– Vous noterez des choses bizarres au début de la table (jusqu’à 31). Ce sont des caractères spéciaux : il ne représente pas un caractère littéraire mais des sortes de signaux. Beaucoup ne sont quasiment plus utilisés, les 3 qui présentent une vraie utilité en Arduino sont le 0 (NULL), le 10 (Line Feed) et le 13 (Carriage Return). Les deux derniers sont automatiquement ajoutés en fin de chaîne lorsque vous faites un Serial.println(). Concrètement, lorsque que je vais faire Serial.println(« Arduino »), il sera envoyé :

65,114,100,117,105,110,111,10,13

Le LF+CR est utilisé un peu partout en programmation, il est un petit peu l’analogie du « Roger » en communication radio, signifiant la fin d’un message.

– Vous remarquerez que le chiffre 1 n’a pas le code 1 et ainsi de suite … Il y a donc une distinction entre les chiffres et les caractères de ces chiffres. C’est pour celà que dans certains codes que vous trouverez, il y aura des instructions du genre :

byte chiffre = Serial.read() – 48

Par exemple si j’ai envoyé le chiffre 8 en ASCII, soit 56, ça donne 56 – 48 = 8 => je récupère bien mon chiffre.

Vous devez donc maintenant comprendre que quelque soit la solution adoptée, il ne s’agit que d’une question d’interprétation et de représentation. Voyons maintenant comment on peut jouer avec tout ça sur Arduino.

Serial.write() Serial.print() Serial.read()

Serial.write() va envoyer ce qui est passé en argument brut de fonderie. Donc si j’écris Serial.write(48), il va effectivement envoyé 48 et de l’autre côté je recevrais donc 48. Libre à mon autre système d’interpréter cette donnée comme il l’entend, soit en regardant la correspondance dans la table ASCII et donc de comprendre que ce qu’il a reçu est le caractère « 0 », soit en prenant ce nombre comme il est, soit 48.

A l’opposé, si je fait Serial.print(48), le système va envoyé le code ASCII pour le « 4 » puis celui pour le « 8 ». Donc ici, contrairement au write() je vais d’une part envoyer deux octets au lieu d’un seul, et d’autre part je vais encoder ces caractères. Il sera donc transmis 52,56.

Je n’ai pas encore parler de la réception, car il n’y qu’une seule commande sur Arduino, c’est Serial.read(). Bizarre non ? Il devrait pourtant y avoir deux types de réception possibles puisque je peux recevoir les informations sous deux formats différents ? Alala décidément vous ne suivez rien 😀

Serial.read() lit chaque octet reçu. Mais vous voyez bien que, que ce soit avec le write() ou le print() j’ai transmis des octets. Donc pourquoi devrais-je avoir deux modes de réception ? Il s’agit tout simplement à moi programmeur de mettre en forme les données reçus comme elles me conviennent. Reprenons mes exemples :

A => Serial.write(48) => un octet valant 48 est envoyé

B option 1 => byte nombre=Serial.read() => nombre vaudra 48

B option 2 => char caractère = Serial.read() => caractère vaudra … 48 ! Oui mais étant de type char il sera reconnu en tant que caractère dans le système. Si maintenant je veux afficher ce que j’ai reçu sur un écran dont la librairie hérite de print() :

monEcran.print(nombre) => affichera « 48 »

monEcran.print(caractère) => affichera « 0 »

Autre cas, je fais Serial.write(‘8’). Les apostrophes signifient au compilateur que je veux le caractère correspondant en ASCII. Il sera donc transmis un octet valant 56.

La vérité c’est qu’on pourrait très bien se passer de print() mais qu’il rend bien service 😉 d’ailleurs je vais vous avouer un secret : print() utilise write() 😉

Et mes variables dans tout ça ?

Et bien du coup, maintenant que vous avez un peu assimilé tout ça vous devez avoir compris que du côté des variables on peut également un peu faire ce qu’on veut et qu’au final c’est toujours des 0 et des 1 et que tout n’est question que de représentation/interprétation. Concrètement, je peux déclarer la chaîne « Arduino » comme ceci :

char chaine[]= »Arduino »;

ou bien

char chaine[]={‘A’,’r’,’d’,’u’,’i’,’n’,’o’};

ou bien

char chaine[]={65,114,100,117,105,110,111};

puis faire

Serial.print(chaine);

Maintenant si je suis un peux maso :

byte chaine[]={65,114,100,117,105,110,111};

puis

for(int i=0;i<7;i++) Serial.write(chaine[i]);

Dans tous les cas, l’information transmise sera 65,114,100,117,105,110,111

Autre fonctions utiles

Quelques fonction que je ne vais pas détailler ici (une recherche google et vous saurez tout;) ) mais dont il est bon de connaitre l’existence :

atoi() => transforme une chaine en entier, donc à faire une conversion genre « 48 » en nombre 48

itoa() => transforme un entier en chaine de caractère, donc 48 en « 48 »

sprintf() => permet de construire des chaines de caractère et d’y insérer des variables (attention sur Arduino pas de prise en charge des float)

Conclusion

J’imagine qu’arriver ici vous avez peut-être un peu la tête qui tourne … Si vous ne savez pas quoi faire, posez vous deux minute et reprenez votre programme point par point : que vaut ma variable/chaine ? Comment va-t-elle être interprété ? Va elle être encodé en ASCII ? A la réception : comment je veux utiliser mes données ? Sous quelle forme ont-elles étaient envoyés ?

Vous verrez qu’en étant méthodique au début ça devient vite plus limpide 😉

Bonjour à tous,

C’est une question très courante quand veut débuter en Arduino (et donc en générale quand on veut aborder le monde des microcontrôleurs) : quelle carte choir ? UNO, MEGA, DUE, Nano ??!

Comprendre

Très souvent le débutant fait les mêmes erreurs qui le guide vers un mauvais choix de première carte :

– il a déjà un projet en tête : et oui mais l’Arduino, même si ça se veut être la plateforme de développement la plus simple à mon sens, ça reste de la programmation et de l’électronique. Et avant de vouloir courir il faut savoir marcher ! Très souvent sur le forum Arduino on croise des choses du genre « je voudrais faire un quadricoptère, mais je comprends pas ce que c’est que le PWM ». Bah oui mais ça peut peut-être sembler barbant mais commencer à jouer avec des led, des boutons, des photorésistance … Permet d’apprendre les bases indispensables et ça prend pas forcement plus de temps au final parce que ça va peut-être prendre du temps au départ mais qui sera vite rattrapé. Ne pensez pas que vous serez plus malin que les autres.

– « Je vais prendre celle qui en a le plus dans le slip au cas où » : perso, j’ai une MEGA, et elle ne m’a jamais servi … A moins d’avoir des projets bien particuliers, on peut faire énormément de choses avec une Nano ou une Micro, il existe des tas d’extensions possibles pour parer à toutes les situations. On croit bien souvent que le système est lent : croyez moi, le jour où vous amènerez votre UNO à ces limites, c’est soit que vous aurez atteint un certain niveau, soit que vous avez un code foireux 😉

Les fonctions de l’Arduino

Je pense qu’il est bien important de comprendre les fonctions de l’Arduino pour comprendre ce que l’on achète.

Tout d’abord il faut comprendre ce qu’est exactement Arduino : ce n’est pas juste un ensemble de carte, c’est un environnement : des cartes ET une interface de programmation. Ces cartes (puisque que c’est le sujet qui nous interesse ici), il y en a plusieurs mais le principe est toujours le même : on trouve un microcontrôleur (= le cerveau) et une série de composants nécessaires à son fonctionnement, le tout monté sur un circuit imprimé qui facilite le développement : bornier, possibilité d’empiler des « shields » pour ajouter des fonctions, entrées pour différentes alimentations … Donc une carte, c’est un ensemble de choses qui vont lui donner ces caractéristiques finales, mais le principal dans l’histoire reste évidemment le microcontrôleur : c’est lui qu’on va programmer et qui définit le plus les possibilités données à la carte.

Voyons maintenant ce que peut faire un microcontrôleur …

Les entrées/sorties digitales

C’est LA fonction première d’un microcontrôleur : avec une simple ligne de code, on peut passer une sortie du µC (microcontrôleur) à 5V ou à zéro volt. Quelle intérêt ? Alimenter une led au travers d’une résistance, faire sonner un buzzer, commander une électrovanne  un moteur … En gros c’est une sorte « d’interrupteur » : lumière allumée ou éteinte.

Maintenant on peut faire l’inverse : lire une entrée de l’Atmega. Est-elle l’état haut (=5V) ? Ou à l’état bas (=0V) ? Quelle utilité ? Détecter l’appuie sur un bouton, un son, un signal d’un détecteur infrarouge … Bref tout ce qui prend fourni des signaux tout ou rien (= « ma lumière est allumée ou bien éteinte ? »)

Les entrées analogiques

Une fonction également très importante d’un µC (s’il en est capable, ce qui est le cas de toutes les arduinos) est la mesure analogique : c’est très simple à expliquer, c’est comme si vous aviez un voltmètre. Une ligne de code et hop vous connaissez la tension sur tel ou tel pin analogique. Quelle utilité ? Lire tout un tas de capteurs : mesurer la luminosité, la température, l’humidité, la tension d’une batterie …

Les sortie PWM

La on va pouvoir générer une tension « pseudo variable » : en gros il s’agit de faire passer un pin de 0V à 5V puis de 5V à 0V très rapidement(tellement que c’est imperceptible pour l’être humain), et ce, avec une répartition du temps passé à 5V et à 0V variable mais bien évidemment commandée dans le code :

C’est comme un variateur de lumière : la luminosité varie simplement pour nous, mais si on dilatait le temps, on verrait des variations dans la luminosité car en réalité le courant circule un temps puis s’arrête. L’oeil humain n’étant pas assez rapide pour distinguer ces variations, l’illusion fonctionne. Le PWM c’est un peut pareil : un voltmètre lira effectivement une tension variable car la plupart sont équipés de filtre en entrée qui lissent les créneaux de tension. Mais il faut garder à l’esprit que ce n’est pas une réelle tension fixe : si le système sur lequelle on le branche est assez rapide, il ne verra que du 0V ou du 5V. Par exemple si je branche une sortie PWM sur une entrée analogique de l’Arduino, et bien vous aurez un coup une mesure à 0V et un autre à 5V.

Les ports de communication

Il existe trois principaux mode de communication : la liaison série, le SPI et l’i2c. Elles servent principalement à communiquer avec l’ordi (ça c’est pour la liaison série) et à communiquer avec d’autres composants (SPI et i2c). En fait derrière ces noms un peu barbares c’est toujours le même but : échanger des données (et qui sont toujours des 0 et des 1), il n’y a que la manière qui change. Je ne vais pas trop développer ce sujet, mais ce qu’il faut retenir :

– SPI ou i2c : ces deux modes permettent de communiquer avec presque autant de « clients » que vous voulez avec un seul port. Quelque part, deux i2c c’est inutiles, c’est comme avoir deux bouteilles de whisky qui ne se vide jamais.

– Série : deux points à retenir. Le premier, c’est que la plupart des Arduino n’ont qu’un seul port série et qu’il sert à la liaison avec le PC. A ce moment la, un composant (un Atmega32u4 pour les carte récentes, un FT-232 sur les anciennes) fait l’intermédiaire pour que le branchement se fasse en USB (mais sur le PC la carte apparaît bien comme un port série). C’est par ce biais que s’effectue la programmation, et éventuellement le dialogue avec la carte. On peut alors lui transmettre des commandes et elle peut nous envoyer des infos. On peut cependant exploiter ce port série pour communiquer avec d’autres clients, mais en liaison série il n’y a que deux dialogueurs (enfin en réalité on peut faire des dialogues à plusieurs, mais c’est assez complexe). Donc utiliser le port série pour communiquer avec une autre carte par exemple, c’est perdre la liaison avec le PC. Le second point c’est qu’il s’agit de série TTL à différencier du série RS-232 qu’on trouve sur les anciens PC maintenant (le fameux port COM). C’est presque la même chose mais les tensions n’ont rien à voir (0-5V pour le TTL et -12/+12V pour le RS-232) donc brancher du RS-232 sur une Arduino ça va la griller, et les polarités ne sont pas les mêmes (un 0 en TTL est un 1 en RS-232 et vice-versa). C’est pas forcement hyper important comme remarque mais c’est un point qui n’est pas forcement clair et le terme « série » est en générale utilisé à tord et à travers sans distinction.

A noter : dans toutes les fonctions que je viens d’évoquer, chacune n’est pas forcement disponible sur tous les pins du µC. Si je prends la UNO par exemple, j’ai 6 pins analogiques (qui sont aussi digitaux) : sur les autres pins de la carte je ne pourrais pas faire de mesures analogiques.

« Ouais mais tu nous emmerdes on sait toujours pas quoi choisir ! »

Tout ce blabla pour qu’on arrive à mon conseil : prenez une UNO (et pas une UNO cms). Pourquoi :

– elle a toutes les fonctions nécessaires et largement assez dans le slip pour faire tous ce que vous voulez.

– vous pouvez changer l’atmega : si un truc doit griller (et bien évidemment un débutant est le meilleur candidat à ce que ça arrive) c’est l’Atmega. Si vous prenez une Léonardo et que vous flinguez l’Atmega32u4, vous avez intérêt à avoir un pote bien équippé pour qu’il vous dessoude ça et en remonte un neuf … Donc si ça vous arrive toute la carte est bonne pour la poubelle. Alors qu’une UNO classique l’Atmega328P est monté sur un support et qu’ont peut l’enlever à la main. Donc en cas de mauvaise manip, il n’y a que ça à changer.

– ça vous servira toujours : il vaut mieux racheter plus tard une MEGA ou autre, une UNO on s’en sert toujours pour faire des test, programmer des Atmega pour les monter sur ses propres montages en standalone (comprenez qu’on peut juste prendre l’Atmega et le monter sur ses propres circuit intégré, ce que j’ai fait ici par exemple mais avec un Atmega328 en version cms = monté en surface)

Fortement déconseillée : la DUE. Ce n’est pas la même architecture au niveau du µC (c’est un ARM), pour faire simple : si sur la programmation ça ressemble à la même chose que sur une Arduino « normale », derrière ça n’a rien à voir. Donc bon nombre de librairies sont incompatibles, et pas grand monde (même la team Arduino) ne bosse dessus donc pas grand espoir que ça change. En plus elle est en 3,3V : envoyer 5V sur une entrée et bye bye le ARM … Même si le 3,3v est voué à se démocratiser (on voit même apparaître de plus en plus de 1,8V !) ça le rend plus vulnérables aux erreurs de débutants. En plus elle est chère (+ de 35€) … Si vous tenez à faire du ARM tout en gardant la simplicité de la programmation Arduino, prenez la Stellaris Lauchpad de Texas instrument : 9,9$ et compatible avec Energia, un logiciel de programmation basé sur Arduino.

Arduino UNO (Atmega328P au format DIP) => c’est elle qu’il vous faut !

Arduino UNO CMS ==> Pas bbbiiieeennnn

Où acheter ?

Alors je suis un grand acheteur sur ebay et dx.com. J’ai acheté énormément de matériel en provenance de Chine sur ces deux plateformes, jamais déçu. Alors oui je sais c’est pas cool pour les petits français. Mais bon regardez sous tous les appareils électroniques chez vous et ça sera marqué made in China …

Je vous recommande plutôt DX car sur ebay, on trouve un peu plus de choses « exotiques ». Car ce que vous achèterez si vous commandez en Chine, ce sont bien évidemment des clones (pas des copies puisque Arduino est OpenSource, comprenez que rien n’es breveté donc chacun peut dupliquer des cartes Arduino et les vendre) et les fabricants sont multiples et peuvent essayer de grappiller sur les composants : un régulateur moins costaud, un convertisseur USB-Serie moins performant … Et sur Ebay, on peut trouver plein de vendeurs différents avec pas forcement un bon suivi. Sur DX, il y a des commentaires sur tous les articles et ils n’ont pas 10 000 ref différentes pour la UNO. Ils ont bien plusieurs modèles de UNO, mais elle seront surement toutes fiables car ils ne s’amuseraient pas à en mettre des mauvaises car la note du produit serait fortement entachée. Après évidemment il faudra se montrer patient (2-3 semaines en moyenne).

Si vous êtes pressé ou que la Chine vous fait peur, bien sûr il y a des bonnes crèmerie en France : Semageek, Farnell, Snootlab … Et la vous aurait la vrai board officiel. Mais pour au moins 2 fois plus cher. A vous de voir !

Bonjour à tous,

Bon je suis pas encore sûr du nom (du tout même) mais je vais vous présenter un projet qui m’a vraiment pas mal occupé, même si on dirait pas forcement !

Principe

La philosophie de ce projet est très simple : je me suis rendu compte dans mon travail qu’on en revenait très souvent aux mêmes fondamentaux, et que même si idéalement il faudrait créer une ou plusieurs boards par projet, au final 90% du temps on fait toujours appel aux mêmes « briques » électroniques : un microcontrôleur en liaison avec des capteurs et des actionneurs.

J’ai donc entrepris de créer un ensemble de développement, capable de satisfaire un maximum de besoin et ayant une apparence professionnelle. Et c’est ce dernier point que j’ai particulièrement recherché car bien souvent dans le DIY on voit des projets avec des fils partout, des empilements de shield  … Bref pas propre !!

Pour ce faire, le cahier des charges s’est établi comme suit :

– l’ensemble doit pouvoir s’intégrer dans un boitier type DIN (j’en parle plus tard),

– une carte mère rassemblant µC + bouton + écran + buzzer + connecteur pour les autres board + protection/filtrage d’entrées analogiques + autre si la place,

– un prix abordable : et oui si c’est pour sortir l’ensemble à 150€ ça vaudra moins le coup …

– possibilité de brancher des shields pour étendre les fonctionnalités,

– de la place en façade et à l’arrière pour arranger les connecteurs et/ou les potars et/ou autre (led, boutons « cachés », photo résistance, récepteur IR …) comme on veux,

– open source et facile d’utilisation : je veux rester dans un environnement type Arduino.

Le choix du boitier

Je voulais un boitier de ce type :

C’est couramment sous cette forme qu’on trouve les contrôleurs du marché (temperature, vitesse moteur, humidité …). C’est facile à mettre en place et ça fait propre.

Alors j’en ai testé une palanquée … Car si ça peut paraître mineur, et bien ça ne l’est pas … Pourquoi ? Et bien essayez de prendre un boitier vide commercial et d’assembler différente carte dedans, tout en prenant en compte le fait que justement la configuration de vos carte à l’intérieur va changer, et qu’il faut également que vous preniez en compte le fait qu’il y a des connecteurs à installer …

Et puis surtout, trouver des boitiers de ce type, c’est pas une synécure …

Bref c’est un beau mic-mac et j’ai fini par en trouver un, et pas cher en plus (je ne l’avais pas mentionné mais évidemment le tarif est entré en ligne de compte) :

http://www.tme.eu/fr/details/op48x96l057/boitiers-de-panneaux/#

Vous pouvez y aller, c’est en Pologne mais je n’ai eu aucun problème et le matos est de qualité.

La carte mère

WP_20140128_002

Après moulte questionnement, j’en suis arriver à travailler avec un écran de Nokia5110 (PCD8544). Ce choix s’est fait par ses dimensions, sa résolution et son prix. Je ne voulais pas de 7-segment car trop gros, trop gourmand … Pas de caracterères LCD, pour quasiment les mêmes raisons. De plus le PCD8544 est bien documenté et plusieurs librairies existent.

Le micro est évidemment un Atmega328p 🙂

Pour l’instant on peut y souder 4 boutons. J’y ai ajouté une mémoire FM24C04B, pilotée en i2c. Pour résumer c’est une mémoire non volatile (comme l’EEPROM ou la flash) de 4kb qui peut supporter 10 puissance 12 écritures. Grosso-modo, même si vous écrivez sur le même segment toutes les ms, elle durera plus de 30 ans … Le rétroéclairage est piloté en PWM via un mosfet. Je n’ai pas intégrer de FT232RL surtout parce la place me manquait, et aussi parce qu’on en a pas forcement besoin en dehors de la programmation (qui peut se faire via le port ISP présent en plus).

Les entrées analogiques sont protégées et filtrées via un simple circuit RC + zener 5,1V.  Au passage il est possible de faire un diviseur de tension (pour interfacer avec une entrée 0-10V par exemple) en changeant la résistance de pull-down de 100k.

WP_20140128_003

WP_20140128_001

WP_20140307_001 WP_20140307_003 WP_20140307_004

 

WP_20140307_00'

Voici les fichiers eagle (pas forcement complet au niveau noms et valeurs des composants).

A noter également que je n’ai pas terminé les façades avant et arrière ce qui explique l’aspect

Carte alimentation

WP_20140128_004

Alors je vais être honnête, pour cette première version je visais un certain projet et je n’ai pas pu atteindre le degrés de « modularité pour tous » suffisant. Mais j’ai quand même créer une carte d’alimentation capable de prendre en charge suivant les composants soudés sur le PCB : 230VAC, 12VDC ou 36-15VAC/VDC. Elle comporte le FT232RL et un connecteur sur l’arrière pour envoyer i2c, 5V et 12V. Enfin il y a une entrée analogique vers A0.

L’avenir

Alors je compte pas m’arrêter la : je travaille déjà sur d’autres shields pour cette version 1.0 mais j’ai déjà la 2.0 dans la tête. Où j’en suis dans mon raisonnement :

– Microcontrôleur ARM M4 Tiva C TM4C123 le même que celui du launchpad Tiva C :

http://www.ti.com/ww/en/launchpad/launchpads-tivac.html

Pourquoi ? La puissance (je vous laisse regarder la fiche technique mais c’est une tuerie (80 mhz, 256k de flash 32 kb de RAM, 4x SPI, 4x i2c, port USB Host/Device/OTG …) et surtout, le point qui me fait faire vraiment ce choix, compatible avec l’IDE Energia, le Arduino-like pour les launchpad. Bon il ne prend pas tout en charge encore (notamment l’USB sous exploité), mais j’ai trouvé quelques « subterfuges » pour passer outre, j’en parlerai bientôt dans un autre article. Et TI est particulièrement actif dans le monde du DIY et collabore notamment beaucoup avec les developpeurs : les projets Energia par exemple vont pouvoir être importer dans Code Composer Studio v6. Avec les Stellaris et les Tiva C ils fournissent quantités de librairie, notamment en USB ce qui simplifie énormément le travail des codeurs. Le prix des launchpad est ridicule. Bref Texas Instrument semble une « bonne voie » dans laquelle s’engager 🙂

– ce choix me permet d’intégrer une horloge en temps réel puisque intégrée dans le Tiva C 😉

– possibilité d’utiliser d’autres écrans, d’autres configuration de clavier : besoin de plus de bouton ? un joystick ? d’un écran plus petit ? bref un petit coup de fer à souder et hop 😉

– ajout d’un ADC 24-bits, de la prise en charge Ethernet via ENC28j60 et d’un DAC : la nouvelle organisation que je prévois devrait me laisser plus d’espace, donc je vais pouvoir « gaver » l’ensemble pour accumuler un max de fonctionnalités, en tout cas il y aura la place sur le PCB.

Pour le reste comment je vois les choses : fourniture de cartes personnalisées : j’aimerais pouvoir proposer le concept à la vente, avec à la commande pouvoir décider de ce dont vous avez besoin. Pas besoin de l’ethernet ? Bin jle soude pas et le prix est déduit … Et vous recevez un « kit » qu’il ne reste plus qu’à programmer et qui fait pro. Et bien sûr le tout à un prix raisonnable évidemment 😉

Pour les intéressés il me reste pas mal de cartes (seeedstudio oblige) que je peux revendre 😉

Bonjour à tous,

Pour commencer : non je ne suis pas mort mais très occupé 🙂

Je bosse sur pas mal de sujet, y’en a un qui devrait vous intéresser et que je vous présenterai à la fin du mois si tout va bien (en attente des PCB de Chine). Pour l’instant suspens :p

Alors qu’est-ce qui nous amène aujourd’hui : n’avait vous jamais rêvé d’une lumière qui s’allume et s’éteint en tapant dans vos mains ? Et bien ce doux rêve est à portée de bras 🙂

Matériel

– Une arduino (ici j’ai pris une pro mini) + 1 bouton

WP_20140114_001

– Au besoin comme moi, un convertisseur USB <-> Serie :

WP_20140114_005

– Un module chinois de détection sonore :

WP_20140114_004

– Un module  relais chinois :

WP_20140114_003

– Des bras et un cerveau.

Bon vous l’aurez noter peut-être, mis à part les bras et le cerveau tout est en provenance direct de Hongkong, histoire de tester ces modules au passage 😉

Montage

Rien de complexe du tout. Pour le module sonore : deux pins pour l’alimentation, et un pin OUT à brancher sur une entrée digitale de l’Arduino. Ce pin est HIGH lorsqu’il n’y a aucun son et passe à LOW lorsqu’il en détecte un, le seuil se réglant avec le petit potentiomètre dessus. Une LED permet de visualiser la détection.

Pour le module relais rien de fantastique non plus : deux fils pour l’alim et un pour la commande. Ici attention, suivant les modules, le relais ne s’active pas sur le même état. Sur le mien justement HIGH = relais ouvert et LOW = relais fermé

Le bouton la c’est du classico-clasique : une borne au GND, l’autre à un pin digital configuré en INPUT_PULLUP.

Enfin si comme moi vous avez une pro mini, il vous faut raccorder le convertisseur USB<->Série : RX à TX, TX à RX, DTR à DTR, GND à GND et au besoin 5V à VCC.

Programmation

La ça se corse … En fait le codage ne fait pas appel à des notions complexes, mais ça demande une certaine gymnastique mentale pour transcrire le problème réel en code. Le principe de base et le suivant :

Quand je tape dans mes mains, un signal est détecté par l’Arduino. millis() est alors mis en mémoire (si vous êtes déjà perdu cet article devrait vous aider), c’est le point de départ.  Lorsque je retape, l’Arduino détecte le signal et fait la différence entre millis() et le point de départ précédemment enregistré. Cet écart est mis en mémoire dans un tableau. On remet à zéro le point de départ et on recommence. On se retrouve ainsi avec un tableau rempli d’écart entre deux frappes : ça y est, on a sauvegarder notre rythme !

Comme un schéma vaut parfois mieux qu’un long discours :

WP_20140114_010

Alors ça c’est pour le principe de base. Maintenant on veut également ne pas avoir a enregistrer la rythmique à chaque démarrage, donc on va faire appel à l’EEPROM. Pour ceux qui l’ignore, l’EEPROM est une mémoire morte. On en retrouve dans la quasi totalité des microcontrôleurs. Alors qu’est-ce qu’elle a de spécial cette mémoire ? Et bien c’est assez simple : on va pouvoir y stocker des variables et pour toujours (en tout cas, tant qu’on ne réécrit pas dessus) et ce, en passant par un programme ! Typiquement, cette mémoire sert à stocker des variables de configuration amenées à être modifiées durant la vie du système, par exemple le contraste d’un écran : on va pas s’amuser à chaque démarrage à aller dans les menus pour remettre un contraste qui nous semble correct. On stocke en mémoire ce contraste et au redémarrage on recharge cette variable. Dans le montage qui nous intéresse ici, on va donc se servir de cette mémoire pour enregistrer notre rythmique. Attention cependant, le point faible de cette mémoire est qu’elle a un nombre d’écriture limité : 100 000 écritures d’après la datasheet. En réalité c’est une durée de vie minimum, mais si ça se trouve elle peut durer 10 fois plus. En tout cas ce qu’il faut retenir c’est que ce n’est pas une mémoire où il faut écrire régulièrement, sinon on la flingue assez vite. A noter qu’en revanche il n’y a aucune limite en lecture.

Il y aura donc deux modes de fonctionnement : un mode écoute (le fonctionnement « normal » quoi) et un mode enregistrement, qui sera déclenché par l’appui sur le bouton.

Alors on va commencer par l’enregistrement car ça me semble plus facile pour comprendre l’écoute ensuite.

Brute de fonderie, le code :

void Enregistrement(){

Blink(); // fonction qui fait clignoter la LED signifiant le passage en mode enregistrement
 Depart=millis(); // la sortie de Blink() se fait sur la détection du premier clap, donc on prend le point de départ

Stab();

int j=0;

while(millis()-Depart<TIMEOUT && i<50){ // on boucle tant que le timeout n'est pas dépassé on qu'on enregistre pas plus que ce qu'on peut

if(digitalRead(INMIC)==LOW){ // son détecté

Sequence[j++]=millis()-Depart; // on enregistre le temps écoulé
 Depart=millis(); // remise à zéro du point de départ

Stab();

}

}

NombreDeClap=j+1;

SauvegardeEEPROM();

Play();

Mode=ECOUTE;

}

Alors avant toute chose, vous noterez les appels à certaines fonctions. Ne vous inquiétez pas on va les voir. Donc on commence par la fonction Blink() :

void Blink() {

Depart=millis();

byte State_LED=HIGH;

while(digitalRead(INMIC)==HIGH) {

digitalWrite(LED,State_LED);

if(millis()>=(Depart+500)) {
 Depart=millis();
 State_LED = !State_LED;
 }

}

digitalWrite(LED,LOW);

}

Son principe est simple : faire clignoter la LED mais de manière non bloquante : dès qu’il y a un signal sonore, hop on sort. Si vous êtes perdu je vous renvoi vers le même article.

Ensuite on tombe sur Stab(). Vous allez me dire que faire une fonction pour 2 lignes c’est pas forcement utile. Oui mais on y fait appel plusieurs fois dans le programme, donc bon …

void Stab(){

while(digitalRead(INMIC)==LOW); // tant que le détecteur n'est pas revenu à l'état normal on boucle
 delay(REBOND); // anti-rebond

}

Sa fonction est simple : un signal sonore n’est jamais un pic parfait ce qui fait que le signal dure plusieurs millisecondes, donc si on ne veut pas avoir de problème, il faut attendre que le signal « retombe ». Pour ce faire on se mets dans une boucle while() tant que le signal est LOW (=son détecté) et en plus derrière on place en plus un delay() par sécurité (on attend que les choses « se tassent » 😉 ). REBOND est défini en en-tête, on le verra plus tard.

Donc la ça y est le top départ est donné : Depart = millis() ==> mis en mémoire du « Top depart » du chrono.

On rentre alors dans une boucle while() dont on ne sortira qu’à deux conditions : si on dépasse un certain temps (timeout) ou si on arrive à la limite de notre tableau Sequence[] qui permet de sauvegarder notre rythmique.

Alors dès qu’un signal est détecté, on mesure le temps écoulé par rapport au premier « clap », on remet à zéro Depart, on attend le retour à la normale du capteur (Stab()), et on repart pour un tour. Dès qu’on sort de la boucle (trop de clap ou bien on a arrêté de taper et on a dépassé le timeout) on lance la sauvegarde en EEPROM :

void SauvegardeEEPROM(){

EEPROM.write(0,NombreDeClap); // adresse zéro on stocke le nombre de clap

int y=1;

for(i=0;i<NombreDeClap-1;i++) {

EEPROM.writeLong(y+=4,Sequence[i]); // long = 4 bytes

}

}

Alors ici si vous n’avez jamais jouer avec l’EEPROM forcément ça risque de vous parlez un peu chinois (en même temps vu d’où viennent les modules xD)

L’EEPROM est diviser en byte, soit 8 bits. Chaque byte porte une adresse. Pour un atmega 328 qui a 1024byte de mémoire, les adresses vont donc de 0 à 1023. Mais comme ce sont des bytes, on ne peut stocker de base que des nombre entre 0 et 255. Donc pour stocker un « long » qui fait 4 bytes, il faudra donc utiliser les adresses en 4 par 4. Alors écrire une routine pour le faire n’est pas compliqué, mais il y a une librairie qui le fait directement, elle s’appelle EEPROMex.h

Donc je m’en sers ici mais il faut quand même tenir compte du fait qu’elle ne prend pas en compte le type de variable écrit par rapport à l’adresse (je sais c’est pas clair). Par exemple : si j’utilise EEPROM.writeLong(0,MaVariable1) puis  EEPROM.writeLong(1,MaVariable2), je vais écraser 3 blocs sur 4 de MaVariable1 ! Il faut écrire   EEPROM.writeLong(4,MaVariable2). Ainsi aux byte d’adresse 0, 1,2 et 3 j’aurai stocké  MaVariable1 et à ceux dont l’adresse est 4,5,6 et 7 MaVariable2.

Pour en revenir à nos moutons, il me suffit donc de faire une simple boucle for pour recopier les différents index de Sequence[] dans l’EEPROM. Sequence[0] à l’adresse 1, Sequence[1] à l’adresse 5, Sequence[2] à l’adresse 9 etc …

Au chargement du programme on fera donc simplement la manip inverse :

void ChargementEEPROM(){

if(EEPROM.read(0)<=50){

NombreDeClap=EEPROM.read(0);

int w=1;

for(int e=0;e<NombreDeClap-1;e++) {
 Sequence[e]=EEPROM.readLong(w+=4);
 }

}
 else {
 Mode=ENREGISTREMENT; // si nombre de clap invalide on passe en mode enregistrement
 }
 }

Une fois la sauvegarde effectuée on passe à Play() qui va jouer l’enregistrement qu’on vient de record, et ce, sur la LED 13 de la carte :

void Play() {

Pulse();

for(int u=0;u<NombreDeClap-1;u++){

delay(Sequence[u]);

Pulse();

}

Serial.println("");

}

void Pulse(){

digitalWrite(LED,HIGH);
 delay(50);
 digitalWrite(LED,LOW);

}

Donc la je pense que si vous avez compris le principe de base, vous comprendrez ce passage de vous même.

Maintenant passons à la partie un peu plus velue (et oui ça c’était la partie facile, en tout cas pour moi je trouve ça bien plus facile à appréhender que l’écoute) :

void Ecoute(){

if(digitalRead(INMIC)==LOW){ // son détecté ?

Time = millis()-Depart; // Temps écoulé depuis le précédent clap
 Ecart = float(Sequence[i])-float(Time); // Ecart entre le temps "attendu" et celui réalisé

if(abs(Ecart) <=TIME_ERROR){ // si l'écart constaté est dans l'erreur tolérée

i++; // le compteur de "bonne réponse" est incrémenté

Depart=millis(); // RAZ du chrono

if(i>=NombreDeClap-1){ // si le nombre de bonne réponse est atteint

State= !State; // si le relais était allumé on l'éteint et vice-versa
 digitalWrite(RELAY,State);
 New(); // on repart à zéro

}

} else { // si mauvaise réponse

New(); // on repart à zéro

}

Stab();

}
 }

void New(){

Depart=millis();
 i=0;

}

La je pense avoir commenté au maximum le code, si jamais vous ne pigez pas y’a les commentaires 😉

Bon si maintenant on rassemble tout, qu’on rajoute la prise en charge de la liaison série, le setup() et tout, ça nous donne :

#include <EEPROMex.h>
 #include <EEPROMVar.h>

//configuration des pins
 #define INMIC 2 // entrée détecteur de son
 #define RELAY 5
 #define BOUTON 10
 #define LED 13

// constantes pour rendre le code plus lisible
 #define ECOUTE 4
 #define ENREGISTREMENT 5

//constantes de réglage
 #define TIMEOUT 3000
 #define TIME_ERROR 200
 #define REBOND 100

unsigned long Sequence[50]={0}; // sers à stocker l'air
 unsigned long Depart,Time;
 float Ecart;
 int NombreDeClap,i;
 byte Mode,State; // Mode permet de définir le comportement et State est la variable de commande du relais
 char buffer [100]; // Tampon pour les sprintf
 void setup(){

Serial.begin(9600);

// Configuration des variables

Mode=ECOUTE; // par défaut on écoute
 State=HIGH; // sur mon module relais, à LOW le relais est fermé et inversement
 i=0;

// Configuration des pins

pinMode(BOUTON,INPUT_PULLUP);
 pinMode(INMIC,INPUT);
 pinMode(RELAY,OUTPUT);

digitalWrite(RELAY,State);

ChargementEEPROM(); // Chargement de Sequence[]

Play(); // la séquence est jouée sur la LED 13
 }

void loop() {

// si appui bouton, on passe en mode enregistrement
 if(digitalRead(BOUTON)==LOW) {
 Mode=ENREGISTREMENT;
 while(digitalRead(BOUTON)==LOW); // tant que le bouton est appuyé on boucle
 delay(50); //anti-rebond
 }

switch(Mode) {

case ECOUTE:

Ecoute();

break;

case ENREGISTREMENT :

Enregistrement();

break;

}

}

void Ecoute(){

if(digitalRead(INMIC)==LOW){

Time = millis()-Depart; // Temps écoulé depuis le précédent clap
 Ecart = float(Sequence[i])-float(Time); // Ecart entre le temps "attendu" et celui réalisé

if(abs(Ecart) <=TIME_ERROR){ // si l'écart constaté est dans l'erreur tolérée

Serial.println("OK");

i++; // le compteur de "bonne réponse" est incrémenté

Depart=millis(); // RAZ du chrono
 Serial.println(i);

if(i>=NombreDeClap-1){ // si le nombre de bonne réponse est atteint

Serial.println("Sequence validee");
 State= !State; // si le relais était allumé on l'éteint et vice-versa
 digitalWrite(RELAY,State);
 New(); // on repart à zéro

}

} else { // si mauvaise réponse

sprintf (buffer, "Realise = %d ms Attendu = %d ms Ecart = %d ms ", Time, Sequence[i], Ecart);
 Serial.println(buffer);
 Serial.println(Ecart<0?"Pas OK Trop lent":"Pas OK Trop rapide"); // <=> if(Ecart<O) Serial.println("Trop lent"); else Serial.println("Trop rapide");

New(); // on repart à zéro

}

Stab();

}
 }

void Enregistrement(){

Serial.println("Enregistrement");

Blink(); // fonction qui fait clignoter la LED signifiant le passage en mode enregistrement
 Depart=millis(); // la sortie de Blink() se fait sur la détection du premier clap, donc on prend le point de départ

Serial.println("Debut enregistrement");

Stab();
 int j=0;

while(millis()-Depart<TIMEOUT && i<50){ // on boucle tant que le timeout n'est pas dépassé on qu'on enregistre pas plus que ce qu'on peut

if(digitalRead(INMIC)==LOW){ // son détecté

Sequence[j++]=millis()-Depart; // on enregistre le temps écoulé
 Depart=millis(); // remise à zéro du point de départ

Stab();

}

}

Serial.println("Fin enregistrement");

NombreDeClap=j+1;

SauvegardeEEPROM();
 Play();

Mode=ECOUTE;

}

void New(){

Serial.println("New");
 Depart=millis();
 i=0;

}

void ChargementEEPROM(){

if(EEPROM.read(0)<=50){

NombreDeClap=EEPROM.read(0);

Serial.print(NombreDeClap);
 Serial.println(" claps ");

int w=1;

for(int e=0;e<NombreDeClap-1;e++) {
 Sequence[e]=EEPROM.readLong(w+=4);
 sprintf(buffer,"Adresse %d Sequence[%d] = %d",w-4,e,Sequence[e]);
 Serial.println(buffer);
 }

}
 else {
 Serial.println("Le chargement a echoue");
 Mode=ENREGISTREMENT;
 }
 }

void SauvegardeEEPROM(){

Serial.println("Sauvegarde EEPROM");

EEPROM.write(0,NombreDeClap);

Serial.print(NombreDeClap);
 Serial.println(" claps ");

int y=1;

for(i=0;i<NombreDeClap-1;i++) {

EEPROM.writeLong(y+=4,Sequence[i]);
 sprintf(buffer,"Adresse %d Sequence[%d] = %d",y-4,i,Sequence[i]);
 Serial.println(buffer);

}

}

void Stab(){

while(digitalRead(INMIC)==LOW); // tant que le détecteur n'est pas revenu à l'état normal on boucle
 delay(REBOND); // anti-rebond

}

void Play() {

Pulse();

for(int u=0;u<NombreDeClap-1;u++){

delay(Sequence[u]);

Pulse();

Serial.print(Sequence[u]);
 Serial.print(" ");
 }

Serial.println("");

}

void Pulse(){

digitalWrite(LED,HIGH);
 delay(50);
 digitalWrite(LED,LOW);

}

void Blink() {

Depart=millis();

byte State_LED=HIGH;

while(digitalRead(INMIC)==HIGH) {

digitalWrite(LED,State_LED);

if(millis()>=(Depart+500)) {
 Depart=millis();
 State_LED = !State_LED;
 }

}

digitalWrite(LED,LOW);

}

Une fois écrit c’est sûr que ça parait facile (pour ceux qui trouve ça facile). Mais faîtes comme si vous n’aviez rien vu et partez d’une page blanche 😉

En vidéo :

Application sorti du labo

Si maintenant on installait ça pour commander la lumière du salon 🙂

Bilan : on se rend compte que le module micro est très limite. Ça marche très bien à 50 cm et au-delà ça devient assez bof. Mais bon en même temps pour 2€ fallait pas s’attendre à grand chose. Mais je n’ai pas encore dit mon dernier mot 😉

Amelioration

La clairement je ne vois qu’une seule amélioration : la partie détection sonore dont les faiblesses deviennent assez gênantes une fois qu’on applique le montage en situation réelle. Concrètement ça consisterait en quoi ? D’une part mise en place d’un filtre (passe bande surement) pour affiner la détection et limiter les perturbations, ainsi il n’y a que le « type » de son qui nous intéresse qui déclencherait un signal. Je pense que déjà la on y gagnerait beaucoup car derrière on peut mettre en place une amplification plus importante et plus fine.

Autre piste qui ne changerai pas grand chose : utiliser un capteur piezzo pour par exemple taper sur n’importe quelle partie du sol ou du mur pour allumer la lumière. La aussi un petit circuit filtre+amplificateur et ça pourrait donner quelque chose du tonnerre 😉

Bonjour à tous,

Vu que le sujet à l’air de passionner les foules, je me bouge un peu 🙂

Pour commencer les diverses découvertes/constatations/tests :

Dans un précédent billet je vous parlais d’un adaptateur pour des fraises de petits diamètres :

!BtnSdjQEWk~$(KGrHqUH-DkEvsNzohCPBL8tjNKPtQ~~_35

Celles la ne marche pas bien du tout ! Impossible de tenir une  fraise droite … En revanche ce type la marche bien :

collet_1

Ensuite je vous parlais de GRBL controller, oubliez !! Je pensais que le firmware GRBL était lent, mais en fait c’est le streaming par ce soft qui était naze …

Conclusion : prenez le soft officiel GRBL Universal code sender il marche du feu de dieu !!

Allez on passe aux choses sérieuses 🙂

L’électronique de pilotage des CNC

 

 
Un article pour décrire basiquement le fonctionnement de l’électronique qui anime les fraiseuses numériques et imprimantes 3D.

Les moteurs pas-à-pas

 

Il est d’abord primordial de saisir le principe de fonctionnement (très simple) des moteurs PAP. Bon je vais pas ré-inventer l’eau chaude, l’article wikipedia sur le sujet est assez simple et bien foutu : http://fr.wikipedia.org/wiki/Moteur_pas_%C3%A0_pas

Ce qu’il faut retenir : en gros, un moteur pas à pas c’est une série d’électroaimants qu’on alimente tour à tour pour générer des rotations complètes. Il existe alors deux types de moteur : les unipolaires et les bipolaires. Dans le premier, les bobines ne sont alimentées que dans un seul « sens », alors que dans les bipolaires les bobines sont alimentées dans un sens puis dans l’autre, inversant la polarité du champs magnétique. Les bipolaires sont les plus courants, et encore plus dans le monde des fraiseuses et autres imprimantes 3D. Ce type de moteur nécessite l’emploi de montage type pont en H :

pontH

Sur un moteur à courant continu, si on ferme C1 et C4 on tourne dans un sens, et dans l’autre si on ferme C2 et C3. Maintenant si on mets une bobine de moteur PAP à la place, et qu’on multiplie par deux ce montage, on peut piloter les deux bobines d’un moteur PAP bipolaire.

Les circuits intégrés les plus courant dans le domaine sont le L293 et le L298. Ils ont principalement deux faiblesses :

– les courants qu’ils peuvent commander sont faibles pour une CNC : le L298 peut d’après la datasheet commander 2A en continu. Expérience personnelle : déjà à 1A ça chauffe sacrément …

– il faut une électronique de commande : en effet vous remarquer que si on fait des pas avec un stepper, on est obligé de mettre une interface « intelligente » pour faire les 4 étapes de base :

 

Tableau récapitulatif de l’ordre des phases
Impulsion Bobine A Bobine A Bobine B Bobine B
T1 +    
T2     +
T3 +    
T4     +

 

A noter que le L298 a la possibilité de réguler en courant : en effet on peut placer une résistance en sortie sur moteur pour obtenir une image en tension du courant, le L298 ajuste alors la tension pour maintenir le courant et donc le couple. J’en parle ici car c’est une fonction très importante sur les driverx de stepper pour CNC. Les effets inductifs étant de plus en plus grand au fur et à mesure qu’on augmente la vitesse de rotation du moteur, les bobines s’opposent au courant et il faut alors une plus grande tension pour le maintenir et ne pas perdre de couple. C’est pour celà que les driver CNC demandent souvent plus de 24V alors que sur les steppers vous verrez souvent des spécifications aux alentours de 5V.

On fait alors appelle à d’autres circuits intégrés, plus puissant et plus complets. Un modèle très courant est le TB6560 (en cours de remplacement par le TB6660). Il est capable de gérer 3,5A par phase (=bobine) et est bien plus complet : gère le microstepping (1/2, 1/8, et 1/16 de pas), le decay (décalage de courant, inutile de se tracasser la tête avec ça pour le moment) et intègre une interface intelligente. Ici on ne commande plus directement le pont. En effet, un TB6560 peut gérer un moteur, et il n’a besoin que de deux signaux : une horloge (créneaux alternatif 0-5V) pour les pas, et un pour la direction (5V=un sens 0V=autre sens). A chaque transition 0->5V, le moteur fait un pas dans la direction spécifiée par le pin de direction.

Prenons maintenant le connecteur DB25 de mon driver (en version 5 axes ici, j’ai pas trouvé la 3 axes mais les branchements sont les mêmes).

stepdb

DB25(PIN)

The role of the pin on driver board

Notes

1 EN Enable all axis
2 STEPX X pulse signal
3 DIRX X direction signal
4 STEPY Y pulse signal
5 DIRY Y direction signal
6 STEPZ Z pulse signal
7 DIRZ Z direction signal
8 STEPA (absent sur la 3 axes) A pulse signal
9 DIRA (absent sur la 3 axes) A direction signal
10 LIMIT-1 Limit input1
11 LIMIT-2 Limit input2
12 LIMIT-3 Limit input3
13 LIMIT-4 Limit input4
14 Relay control  
15 blank  
16 STEPB- (absent sur la 3 axes) B pulse signal
17 DIRB-(absent sur la 3 axes) B direction signal
18-25 GND  

(A noter que les flèches indiquant le sens des signaux sont inversées …)

Il y a 3 x TB6560 sur cette carte pour 3 moteurs donc, et on retrouve logiquement 3 couples STEP/DIR. Si maintenant on prend le pinout de GRBL :

Grbl_Pin_Diagram

Et la il devient très facile de savoir qui va où 😉 Step Pulse X-Axis à STEPX, Step Pulse Y-Axis à STEPY, Spindle Enable à Relay control …

Les pins indispensables à brancher sont le 12, et ceux de 8 à 2. Pour les butées (=Limit) je ne sais pas si on peux les brancher à ceux de la carte via DB25. Dans tous les cas, deux options 100% sûres s’offrent à vous si vous avez la même carte que moi : brancher vos butées au driver, mais au cas où vous enclenchez une butée, GRBL continuera de tourner, alors que si vous choisissez la seconde option qui consiste à brancher les butées sur l’Arduino, les mouvements stopperont et GRBL s’arrêtera ce qui peut permettre de rattraper les choses éventuellement …

Notez que sur le schéma, certains pins dont les butées que je viens d’évoquer sont en pull-up, c’est à dire que sur chaque pin la résistance interne (de 20 kOhm de mémoire) de pull-up est active, donc il suffit pour déclencher la fonction qui va avec de relier ce pin au GND. Exemple concret : si je veux pouvoir démarrer/mettre en pause le travaille, il me suffit de mettre un bouton poussoir entre le pin A2 et le GND.

Mais GRBL ça sert à quoi exactement ??

Il me semble quand même important de remettre les choses à plat concernant les différents maillons de la chaîne. Pour celà je vais vous décrire la création d’une pièce comme je le fais aujourd’hui et en décrivant le rôle de chaque acteur.

1ère étape : dessin de la pièce

Je dessine ma pièce sur LibreCad, j’obtiens alors un fichier DXF. C’est un format de fichier dédié au pièces en 2D ou 3D : http://fr.wikipedia.org/wiki/Drawing_eXchange_Format

2ème étape : génération du G-Code

Il faut maintenant traduire cette « image » en chemin pour ma CNC. Pour celà j’utilise HeekCAD. Très simplement on choisit une esquisse et on lui attribut une fonction, par exemple une découpe par l’extérieur (c’est à dire que pour réaliser la découpe, le logiciel va tenir compte de la taille de la fraise pour respecter les cotations de l’esquisse).

Le logiciel traduit alors l’esquisse en mouvement de fraise, en gros elle va écrire des ordres en G-Code qui voudront dire « va aux coordonnées X=10 mm et Y=20 mm à telle vitesse puis fait plonger la fraise de 3 mm, puis déplace toi aux coordonnées X=0 et Y=5 » … On obtient alors un fichier texte (ils peuvent prendre divers extensions, mais au final on peut toujours l’ouvrir avec le bloc note 😉 ) rempli de lignes de G-Code.

3ème étape : préparation de la CNC

Je fixe ma plaque de bois ou autre et place ma fraise au point de départ en utilisant GRBL universal code sender et ses outils de déplacement.

4ème étape : je lance la gravure !

Dans GRBL universal code sender je charge mon fichier G-Code et je lance le travail. Le soft va alors streamer le G-Code, c’est à dire qu’il va envoyer ligne par ligne, par liaison série, les ordres en GCODE. GRBL embarqué sur l’Arduino va alors traduire ces ordres en signal d’horloge et de direction comme expliqué au début de ce billet. La carte drivers reçoit les signaux d’horloge de pas et de direction et fait tourner les moteurs en conséquence.

Branchement des moteurs au drivers et configuration du driver

Comme évoqué auparavant, il faut configurer principalement deux paramètres sur le driver : le microstepping et le courant. Le microstepping permet d’avoir des mouvements beaucoup plus fluides et d’avoir une meilleure précision en régulant le courant dans deux bobines consécutives. Par exemple si au lieu de passer brusquement de la bobine A à la bobine B (cf. tableau du début), j’insère une étape où j’alimente A et B en même temps, le rotor prend alors une position intermédiaire. Et hop voilà le demi-pas 😉 Si maintenant j’injecte moitié moins de courant dans A et toujours autant dans B, je fais un quart de pas et ainsi de suite … Le revers de la médaille c’est qu’il faut une horloge rapide en entrée du drivers. Et oui maintenant pour lui, une transition 0->5V signifie maintenant 1/16 ème de pas si vous l’avez configuré ainsi, donc comparé à du plein pas, il faudra une horloge 16 fois plus rapide pour une même vitesse. Pour ma part je travaille en 1/8 de pas.

Pour le courant il faut faire très attention car c’est ici qu’on peut faire du dégât : ces drivers peuvent débiter des ampères donc on grille très vite le moteur et/ou le driver … Mon conseil : commencer au plus bas, si jamais vous faîtes une erreur ça sera sans dommage. Dans un deuxième temps quand vous avez tout bien configuré et que vous maîtrisez les choses, passez au courant nominal du moteur mais sans jamais le dépasser !

Pour brancher les moteurs, je vous invite à consulter (oui je sais, encore une fois !) la doc de mon driver . Alors on trouve des moteurs à 4, 5,6 ou 8 fils, suivant les connexions internes du moteurs. Si vous avez la datasheet du moteur tant mieux, sinon (ce qui est très souvent le cas !) il va falloir jouer de l’ohmmètre dans un premier temps et savoir qui est quoi (à peu près). Si vous avez un quatre fils, il sera facile de retrouver lesquels sont pour la bobine A et lesquels sont pour la B vu qu’ils sont reliés deux à deux et que les bobines ne sont pas reliées entre elles. Pour un 6 fils, le point milieu sera celui qui aura la résistance la plus basse comparés aux extrémités de la bobine concernées. Après tout est une question de bon sens 😉

Ensuite dans la doc, suivant votre moteur, vous trouverez différents modes de branchement suivant que vous souhaitiez privilégier la vitesse ou le couple. Tout dépendra du type de matériaux visé, du couple nominal des moteurs, du pas de la vis (ou de la courroie) … A vous de voir mais vous verrez qu’il existe au final pas mal de levier pour perfectionner votre machine. Bon quand vous en serez la je pense que cet article vous paraîtra bien basique 😉

Voila j’espère avoir éclaircit certains esprits, si vous avez besoin de précision et d’autres infos n’hésitez pas à le demander en commentaire 😉

Prochain article : création d’une carte Arduino dédiée au branchement à un driver via DB25

Bonjour à tous !

Aujourd’hui un petit billet pour vous parler des interruptions temporelles sous Arduino. C’est un sujet qui revient très souvent sur le forum donc je pense que faire un petit article évitera les multiples répétitions …

Pourquoi faire donc ?

Tout simplement pour exécuter une routine de code à intervalle régulier, sans avoir recours à delay() et donc sans bloquer votre code (enfin il faudra nuancer mais dans l’absolu c’est imperceptible).

Comment qu’on fait ?

Le principe est très simple : on a recours à la fonction millis() (ou micros() si vous avez besoin de plus de précision) qui renvoi un unsigned long correspond au nombre de millisecondes écoulées depuis le début du programme. A un moment donné, on va enregistrer cette valeur, puis régulièrement on va faire la différence entre millis() et cette valeur ce qui nous donnera le temps écoulé. Si le temps écoulé correspond à notre intervalle, alors on exécute le code correspondant, sinon, on exécute autre chose.

Exemple

Prenons un simple blink :



const byte led = 13;


void setup(){

    pinMode(led,OUTPUT);

}


void loop() {


    digitalWrite(led,HIGH);

    delay(1000);

    digitalWrite(led,LOW);

    delay(1000);


}


Donc la vous comprenez bien que pendant les deux delay(1000), votre Atmega s’emme**e et ne peux rien faire. Maintenant, soyons plus astucieux 😉 :



unsigned long Depart;

boolean Flag;

const Led 13;

const MonDelai=1000;


void setup() {


    pinMode(Led,OUTPUT);

    Depart = millis(); // Enregistrement de mon point de départ


}


void loop() {


    if((millis()-Depart)>=MonDelai){     // si 1000 ms se sont écoulées

         Flag=!Flag;    // j'inverse l'état de mon booléen

         digitalWrite(Led,Flag);   //  je change l'état de ma sortie

         Depart=millis();  // nouvelle enregistrement du point de départ

        }

// code qui s'exécutera le temps que 1000 ms se soient écoulées

}


Cette exemple montre bien combien un Atmega peut-être « sous-utilisé ». J’entends par la que bien souvent, on trouve sur le forum des personnes qui trouve leur Arduino lente alors qu’en fait c’est juste leur code qui n’est pas du tout optimisé. Ici la partie conditionnelle va prendre quelques dizaines de µs chaque seconde, ainsi on ne sollicite réellement que moins de 0.01% des ressources de l’Atmega … Cependant il faut aussi avoir conscience que si le reste de votre code est bloquant, la précision de votre intervalle va en pâtir.  L’Arduino est mono-tâche, mais si on optimise bien son code, ça peut tout à fait être transparent pour l’utilisateur 😉