Articles Tagués ‘Tutorial’

[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 😉

Publicités

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,

Alors en ce moment je joue pas mal avec mon Stellaris Launchpad et je vous propose aujourd’hui une méthode pour se passer du programmateur. L’intérêt ? Et bien on peut imaginer des montages avec un ARM en standalone sans avoir besoin d’y intégrer un programmateur. Au passage, Texas Instrument propose directement des bootloaders pour flasher via USB, Série, SPI et même i2c. Sur les Tiva C série 129 il y en a même équipés de l’ethernet et on peut flasher par ce biais. La doc de TI sur le sujet 

Ce billet va traiter d’une autre méthode, même si elle utilise l’USB. Au hasard du net j’ai trouvé le boulot d’un type  et j’ai décidé de tester et d’adapter la méthode pour Energia.

Par ailleurs, n’ayant qu’un Stellaris Launchpad sous la main, mon tuto a été réalisé sur cette carte mais normalement ça marche aussi pour les Tiva C Launchpad, moyennant peut-être juste quelques adaptations. Enfin il se destine pour les mêmes raisons aux Windows-iens 😉

1ère étape

Dans le github de l’auteur, dossier prebuilt, récupérer boot_msc_usb.bin

Si vous ne l’avez pas, récupérez LMFlashProgrammer ici. C’est un outil de programmation très simple mais très efficace fourni par TI pour ses ARM. Au passage si vous jouez avec les différents types de bootloader, ce programme permet d’uploader un programme par n’importe quelle voie, même l’ethernet !

On va maintenant flasher le Launchpad avec le booloader. Branchez votre Launchpad par l’USB Debug et lancer  LMFlashProgrammer :

Dans « quick set », selectionnez « LM4F120 Launchpad » si vous avez un Stellaris LaunchPad et « TM4C123G Launchpad » si vous avez un Tiva C launchpad, puis dans l’onglet « Program » allez chercher le fichier boot_msc_usb.bin préalablement téléchargé. Si vous n’avez touché à rien d’autre alors tout est bien configuré.

Cliquer sur Program, et voila 😉

2ème étape

Vérification : brancher votre launchpad via USB Device cette fois et n’oubliez pas de basculer l’interrupteur de sélection d’alim sur Device. Presser le bouton SW2 et tout en le maintenant enfoncé appuyez puis relâchez le bouton reset. Normalement la led rouge se met à clignoter, signe que le bootloader s’est lancé et votre launchpad apparaît sur votre PC comme une clé USB.

3ème étape

« Ah bin t’es marrant toi je mets quoi dessus maintenant ? »

J’y viens j’y viens …

Il faut copier votre program au format .bin. En réalité, quelque soit votre environnement de développement (Energia, CCS, IAR …) votre programme est toujours transformé en fichier binaire, compréhensible par le µC (peut-être que vous avez déjà croisé des histoires de .bin et des .hex). C’est fruit d’une série d’étapes dont on a pas toujours connaissance. Exemple sur Arduino, on clique sur upload et hop « comme par magie » il se retrouve sur la carte. Vous vous doutez bien que c’est pas aussi simple que ça derrière le rideau …

Bref, après une modification mineure, on va pouvoir récupérer le .bin de votre programme codé sous Energia, pour le copier sur le Launchpad comme si on copiait une musique sur son lecteur mp3.

Donc aller dans votre dossier Energia\hardware\lm4f\cores\lm4f et ouvrer dans notepad ou notepad++ le fichier lm4fcpp.ld

Il faut modifier la partie concernée du fichier comme suit :

MEMORY
{
// flash (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 // ligne d’origine
flash (rx) : ORIGIN = 0x00004000, LENGTH = 0x0003c000 // ligne pour upload via USB Storage mass
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}

Le bootloader étant installé sur la flash il faut « décaler » la plage de programmation allouée au programme, sans ça il ne démarrera jamais. Attention : si vous essayer de repasser par le port debug pour uploader votre programme via Energia, ça ne marchera plus, il faut remettre la ligne d’origine, c’est pour ça que je commente/décommente les lignes concernées dans ce fichier, au moins pour passer d’une méthode à l’autre j’ai juste à faire ça. Par ailleurs, écrire un programme avec la configuration d’origine va effacer le bootloader et il faudra recommencer depuis l’étape précédente.

Maintenant sur Energia, ouvrez votre programme, cliquer sur Vérifier pour lancer la programmation. Dans l’espace en bas apparaît une série de lignes. Regardez à la fin, il apparaît un certain fichier …

energia bin

Et oui c’est notre .bin ! Récupérer le et copier le sur votre Launchpad. Appuyer sur Reset et normalement il se lancera 😉

Par ailleurs je ne l’ai pas précisé mais ce .bin est tout à fait uploadable via LM Flash Programmer avec le Launchpad branché sur la prise USB Debug (ou par les autres voies citées en intro si vous avez mis un autre bootloader), à condition cette fois d’utiliser la config d’origine du fichier lm4fcpp.ld

Optimisations

Alors j’avoue que pour l’instant mes connaissances sur tout ce qui touche à la compilation, au linker, au makefile … est très limitée. Il y aurait surement une méthode plus simple pour spécifier à la compilation qu’on veut le .bin, donc modifier le fichier .ld automatiquement et mettre le .bin sur le bureau par exemple.

Sur CCS

Sur CCS la méthode est quasiment la même, il suffit de modifier le fichier nom_de_votre_projet.cmd  comme ceci :

//#define APP_BASE 0x00000000 // originale
#define APP_BASE 0x00004000
#define RAM_BASE 0x20000000

/* System memory map */

MEMORY
{
/* Application stored in and executes from internal flash */
//FLASH (RX) : origin = APP_BASE, length = 0x00040000  // originale
FLASH (RX) : origin = APP_BASE, length = 0x0003c000
/* Application uses internal RAM for data */
SRAM (RWX) : origin = 0x20000000, length = 0x00008000
}

/* Section allocation in memory */

SECTIONS
{
.intvecs: > APP_BASE
.text : > FLASH
.const : > FLASH
.cinit : > FLASH
.pinit : > FLASH
.init_array : > FLASH

.vtable : > RAM_BASE
.data : > SRAM
.bss : > SRAM
.sysmem : > SRAM
.stack : > SRAM
}

__STACK_TOP = __stack + 1024;

Faites ensuite clique droit sur votre projet > properties puis dans  la colonne de gauche « Build » puis onglet « Steps » et enfin au champs « Command » dans Post-Build steps  ajoutez ces lignes :

« ${CCS_INSTALL_ROOT}/utils/tiobj2bin/tiobj2bin.bat » « ${BuildArtifactFileName} » « ${BuildArtifactFileBaseName}.bin » « ${CG_TOOL_ROOT}/bin/armofd.exe » « ${CG_TOOL_ROOT}/bin/armhex.exe » « ${CCS_INSTALL_ROOT}/utils/tiobj2bin/mkhex4bin.exe »

Lancez le build et dans votre dossier de projet se trouvera le .bin 😉

Si vous avez des questions n’hésitez pas les commentaires sont la pour ça 😉

Bonjour à tous,

Aujourd’hui je vous propose un petit test/tutorial sur la soudure CMS à l’air chaud.

CMS, késako ? Pourquoi faire ?

CMS = Composant Monté en Surface (SMD dans la langue de Shakespeare)

Le CMS vous savez ce sont tout ces petits composants montés sans trou sur les circuits imprimés. C’est un format très utilisé dans les produits commerciaux pour plusieurs raisons :

– moins cher : regarder par cous même sur des crèmerie comme farnell, y’a pas photo …

– plus compact. Démonstration :

WP_20130924_002 (2)

A gauche des MSP430G2553 et à droite des Atmega 328P. Au bas mot 4x plus petit et 4 x moins épais.

– pas de trou à faire : moins de main d’oeuvre, encore des économies.

– montage à la chaîne robotisé possible, très difficile en traversant.

– On soude tout d’un coup.

– possibilité de faire du double face : doublement plus compact ! On peux poser des composants des deux côtés d’un PCB.

Maintenant qu’en est-il pour nous DIYers : et bien si vous relisez cette liste, vous trouverez plusieurs arguments intéressants, surtout si vous avez déjà monté des PCB un poil complexes. En plus, pas mal de composants n’existent tout simplement pas en traversant, obligation d’utiliser un adaptateur.

Alors pourquoi on en voit pas souvent ? Je pense qu’il y a surtout deux gros points qui font barrage :

– d’une part les gens en on peur : c’est tout petit, on en voit pas souvent, il doit falloir un matos hyper complexe et cher …

– c’est beaucoup plus difficile de bidouiller après coup. On va plutôt réserver ce type de placement pour des prototypes dont on est quasiment sûr de la fiabilité.

Et pourtant vous allez voir souder du CMS c’est pas si compliqué, et une fois qu’on y a gouté c’est comme beaucoup de choses, c’est dur de s’en passer xD

Le matos nécessaire et le principe

– Une source de chaleur (je développerai ensuite).

– Un PCB + les composants (sans déconner ??!).

– De la pâte à souder.

– Deux mains, un cerveau.

Le principe est très simple : on place un peu de pâte à souder sur les pads, on pose ses composants dessus, on chauffe et la pâte se transforme en étain. Au refroidissement tout est prêt, il ne reste plus qu’à faire les éventuels composants traversants.

Alors cette source de chaleur peut prendre plusieurs formes : four principalement, ou avec une buse à air chaud comme je vais vous le montrer. Les fours permettent du travail de gros alors que la buse à air chaud convient bien pour du « à la main ».

La station

WP_20130809_008

Alors c’est une station achetée sur ebay pour 80€ environ. Elle fait buse à air chaud et fer à souder. Il y a deux boutons pour allumer ou éteindre la buse ou le fer et il y a 3 potard de réglage : un pour la température du fer à souder, un pour celle de l’air chaud et le troisième pour le débit d’air. Il y a deux afficheurs 7-segments qui affiche les températures de consigne du fer et de l’air. Deux led indiquent si on est à la bonne température ou pas. Donc on ne peut pas savoir quelle est la température, mais si la led s’éteint c’est que la consigne est atteinte.

Au niveau de l’usage rien à redire : le fer comme la buse chauffe très vite, on peut facilement changer la pane (je n’ai pas cherché les disponibilité pour une de rechange mais ça doit se trouver), et la buse se coupe quand on la repose sur son support. Le ventilateur tourne un certain temps sans chauffage pour éviter une surchauffe à cause de l’élan thermique, donc pensez à ne pas débrancher tant que le ventilo tourne 😉

Alors vous pouvez trouver sur ebay plusieurs modèles, il se ressemblent beaucoup au niveau de la buse à air chaud donc je pense qu’elles ont à peu prêt toute le même fournisseur. Ce qui n’est pas plus mal si un jour elle tombe en panne 😉

Au niveau des accessoires sont fournies plusieurs buses, pour l’instant j’ai pas exploré plus que ça, j’ai mis la plus fine et ça fonctionne très bien donc bon …

Bref je ne regrette absolument pas mon achat, rien à redire pour le moment.

Choix de la pâte

Et oui on a pas parler de ça ! Alors grosso modo on trouve 3 famille de pâte : avec plomb (Sn/Pb) , sans plomb, bismuth/étain. Comme pour la soudure en fil, avec plomb c’est beaucoup mieux que sans … Surtout qu’ici la sans plomb fond bien plus haut que  celle avec. Et la Bi/Sn elle a ma préférence car fond à 140°C (230°C pour la Sn/Pb). En effet à 230°C l’epoxy et le vernis apprécient moyen …

Ou en trouver ?

En effet j’ai lu à plusieurs endroit qu’il était difficile de s’en procurer. Y’en a qui ne doivent pas connaitre Farnell … Attention les pâtes à souder n’ont pas une durée vie très longue (quelques moi). Pour ma part j’opte pour celle la : Sn/Bi, pas cher, fourni avec les embouts de seringue, petit volume donc évite le gâchis.

Souder le CMS

Allez on y va, vous allez voir, mis à part la mise en place des composants, ça va très vite ! A ce propos : vous n’avez même pas à mettre parfaitement les composants, comme toute les pattes de votre composant baigne dans de l’étain liquide, la capillarité place le composant tout seul (sisi !). Alors ça marche pas tout le temps à 100%, vous pouvez avoir à faire une petite reprise.

Le PCB :

pcb

On met un peu de pâte de partout :

pate

A noter que si vous disposer d’une découpeuse laser, vous pouvez faire des masques en vinyl, il n’y a alors qu’à étaler la pâte. Exemple :

On place les composants à la pince brucelles :

Et on chauffe !

et voila le résultat !

finie

Alors pas mal hein 😉

Petite astuce en passant fournie par BossOfScandalz  du forum Arduino pour les réparations : utiliser des blindages CEM pour protéger ce qu’on ne veut pas dessouder. Les blindage ressemble à ça.

A bientôt !

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 😉

Bonjour à tous !

Alors aujourd’hui je vous propose de faire communiquer un MSP430 et une Arduino par une liaison sans-fil à base de NRF24l01+.

Nrf24L01, késako ?

Ces modules de communication sont très intéressants pour plusieurs raisons :

* Le prix : à moins de 3€ sur ebay par module, on peut imaginer créer tout un réseau pour presque rien.
* Ce sont des transceivers : à la fois émetteur et récepteur.
* 2,4 ghz : ça élimine beaucoup d’interférences.
* 128 canaux et plusieurs canaux de réception par module : ça permet d’avoir plusieurs émetteurs pour un seul récepteur sans risquer de collision.
* Plusieurs fonctions directement implémentées : ré-émission automatique, CRC (checksum) …
* Portée : 100m en champs libre, 20 m en intérieur (après ça dépend des murs et du débit). Pour 12€ il existe des modules avec amplificateur de puissance, pas testé mais la portée est annoncée à 1000 mètres.
* La consommation (le point qui m’intéresse, vous après verrez pourquoi 😉 ) : à fond ils bouffent 12mA et à la plus faible puissance on tombe à 8 mA. Mais ce n’est pas tout, il utilise la technologie Shockburst qui consiste lors d’une émission à émettre toutes les trames d’un coup. Autrement dit, si on communique à 10 kbits par seconde avec le module alors il va « accumuler » les données, et une fois qu’on lui demande de transmettre il envoi tout d’un coup, ce qui réduit au maximum la consommation. Enfin on peut les mettre en veille, la consommation tombe alors à moins de 1µA (mais le SPI est toujours actif !). Le réveil est assez rapide (<130µs).

Bref ils ont de quoi convaincre ! Datasheet : http://www.nordicsemi.com/kor/Products/2.4GHz-RF/nRF24L01P

Un doc en anglais, une sorte de synthèse commentée de la datasheet qui m’a pas mal aidé (attention cependant elle traite des modules pas « + ») : http://www.diyembedded.com/tutorials/nrf24l01_0/nrf24l01_tutorial_0.pdf

Comparé à la version « + » il n’y a surtout que quelque registres qui changent.

Si vous voulez plus d’infos et/ou vous limiter au cas de l’arduino, je vous recommande les articles de M. Skywodd : http://skyduino.wordpress.com/2012/01/20/tutoriel-arduino-mirf-v2-nrf24l01/ http://skyduino.wordpress.com/2012/02/01/arduino-transmission-valeur-analogique-par-nrf24l01/

Alors pourquoi interfacer un MSP430 et un Nrf ?

Et bien comme vous l’avez vu, la consommation est particulièrement optimisée, et c’est également la spécialité des MSP430 (et en plus les deux utilisent du 3,3V). Prenons un exemple simple : une sonde de température ambiante. On n’a pas besoin de prendre la température toutes les secondes, seulement une mesure toute les 10 secondes, voire une toute les minutes. Et voilà le principe de fonctionnement :

1) Réveil du MSP430 et du NRF24L01+.

2) Acquisition de la température.

3) Emission radio vers la base.

4) On rendort tout le monde pendant 10 sec.

Les étapes 1) 2) et 3) prennent environ 200 µs. Donc pendant la très grande majorité du temps, la consommation est inférieure à 2µA, et pendant 200µs elle reste très modérée : 400µA du NRF + 400µA pour un MSP430 à 1mhz. L’émission consomme 12 mA mais pendant 10-20 µs.

J’ai fait un essai avec une émission toutes les 2 secondes, alimenté par un condensateur goldcap 5F. Ca a tenu 2 jours, ce qui me donnait une consommation de ~10µA. Avec un pile bouton 200 mAh, ce montage pourrait tenir : 200 000 / 10 / 24 / 365 = 2,3 an ! Et à 0,5 hz de fréquence ! Imaginez si vous greffez un panneau solaire ou si on passe à une émission par minute … Les applications sont quasi infinies !

Allez, assez de théorie place à la pratique !

Alors sachez que je me suis pas mal débattu avec ce trio … Car il y a quelques paramètres qui diffèrent entre les deux librairies, et le problème c’est qu’on bosse en aveugle : tant que tous les paramètres ne sont pas bons, il n’y a pas de communication et le debug est pour ainsi dire quasi-impossible … Bref voici le code côté MSP430 (lib = https://github.com/spirilis/msprf24) :

#include <msp430.h>
#include "msprf24.h"
#include "nrf_userconfig.h"

char addrTX[]={'t','e','s','t','2'};

char buf[]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; // trame exemple

int main(void) {

WDTCTL = WDTPW + WDTHOLD;
BCSCTL2 = SELM_0 + DIVM_0 + DIVS_0;

if (CALBC1_1MHZ != 0xFF) {
DCOCTL = 0x00;
BCSCTL1 = CALBC1_1MHZ; /* Set DCO to 1MHz */
DCOCTL = CALDCO_1MHZ;
}

BCSCTL1 |= XT2OFF + DIVA_3;
BCSCTL3 = XT2S_0 + LFXT1S_0 + XCAP_0;
TA0CCTL0 = CM_0 + CCIS_0 + OUTMOD_0 + CCIE; // configuration du timer à 1 s
TA0CCR0 = 4095;
TA0CTL = TASSEL_1 + ID_0 + MC_1;

UCB0CTL1 |= UCSWRST; // configuration du SPI
UCB0CTL0 = UCMSB + UCMST + UCMODE_0 + UCSYNC;
UCB0CTL1 = UCSSEL_2 + UCSWRST;
UCB0BR0 = 64;
UCB0BR1 = 6;
UCB0CTL1 = ~UCSWRST;

P1DIR|=BIT0;

rf_crc=RF24_EN_CRC|RF24_CRCO; // CRC active, 16-bit
rf_addr_width=5; // On utilise une adresse de 5 bytes
rf_speed_power=RF24_SPEED_2MBPS|RF24_POWER_0DBM; // vitesse 1MBPS et puissance max
rf_channel=1;

msprf24_init();

msprf24_set_pipe_packetsize(0,16); // payload de 16 byte sur le pipe 0
msprf24_open_pipe(0,1); // ouverture du pipe avec Auto-Acknowledgement

w_tx_addr(addrTX); // configuration adresse émission
w_rx_addr(0,addrTX); // configuration adresse réception idem à celle de transmission
                      // pour permettre la réception de l'ACK

msprf24_standby(); // module en veille (pas endormi)

while(1){

if(msprf24_is_alive()) { // fait clignoter la LED rouge sur launchpad si
	P1OUT^=BIT0; // le nrf est bien connecté
}else{
	P1OUT&=!BIT0;
}

LPM3; // on endort

w_tx_payload(16,buf); // on charge le FIFO avec le tableau buf
msprf24_activate_tx(); // émission
msprf24_get_irq_reason(); // récupère les alertes du NRF
while(!(rf_irq && RF24_IRQ_TX)) msprf24_get_irq_reason(); // tant que la transmission n’est pas finie, on boucle
msprf24_irq_clear(RF24_IRQ_TX); // on efface les flags d’alerte

}

}

#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR_HOOK(void) {
LPM3_EXIT;
}

+

Modification du nrf_userconfig.h : en haut il y des constantes suivant la fréquence de fonctionnement, il suffit de décommenter la partie qui vous correspond et de commenter les autres et en bas la partie hardware pour définir où sont brancher les pins CE, CSN et IRQ si vous l’utilisez. J’avoue j’ai pas approfondi le code plus que ça, et il n’est pas optimisé. Il y a surement des lignes que je pourrai virer, mais ils m’avaient tellement fait galérer ces modules que j’en avez marre xD

Comme je vais reprendre ce principe bientôt, je publierai une mise à jour 😉

Côté Arduino :

#include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>

void setup(){
  Serial.begin(9600);
  ConfigMirf();

  Serial.println("Listening...");
}

void loop(){

  if( Mirf.dataReady()){

    byte data[Mirf.payload];
    Mirf.getData(data);

    for (int i=0;i<16;i++){
      Serial.print(data[i]);
      Serial.print(" ");
    }
Serial.println(" ");

  }

}

void ConfigMirf(){

  Mirf.spi = &MirfHardwareSpi;
  Mirf.cePin=8;
  Mirf.csnPin=7;

  Mirf.init();

  Mirf.setRADDR((byte *)"2tset");
  Mirf.setTADDR((byte *)"1tset");
  Mirf.payload = 16;
  Mirf.config();

}

+

Modification du fichier Mirf.h : en effet chose étonnante les créateur de cette lib n’ont pas créé de fonction directe pour modifier la gestion de la CRC … Il faut modifier cette ligne en haut :


#define mirf_CONFIG ((1<<EN_CRC) | (1<<CRCO) ) // CRC active 2 bytes, correspond ici avec le code du MSP 430

#define mirf_CONFIG ((1<<EN_CRC) | (0<<CRCO) ) // CRC active 1 byte

#define mirf_CONFIG ((0<<EN_CRC) | (0<<CRCO) ) // CRC désactivée

Alors vous aurez peut-être noter les petites différences :

* Les adresses ne sont pas dans le même ordre.

* Les canaux sont décalé de 1 (MSP = de 1 à 128, Arduino = de 0 à 127)

Alors après bien sur vous pouvez remplir buf avec ce que vous voulez. A noter également qu’ici je n’ai pas géré la mise en sommeil du Nrf, seulement celle du MSP, mais c’est très facile, il suffit de faire :


msprf24_powerdown(); // endort

msprf24_standby(); // réveil, nécessite 130µs d’après la datasheet

Pour recevoir côté MSP430, en gardant les paramètres du précédent code :


msprf24_get_irq_reason();

if(rf_irq && RF24_IRQ_RX) {

msprf24_irq_clear(RF24_IRQ_RX);

r_rx_payload(16,buf);

}

Bon la du coup ça reste assez simpliste au niveau des fonctionnalités, mais débroussaillé tout ça m’a pris un temps fou vu ces quelques différences foireuses dures à débusquer … Mais ça fait déjà le principal : envoyer et recevoir des données. Je n’ai pas été très explicite dans le code, si vous comprenez pas n’hésitez pas je compléterais 😉

Enjoy !

EDIT 12/06/13 : suite à des problèmes d’un lecteur j’ai repris mon code et trouvé quelques erreurs. En fait il y a quelque chose qui m’échappe avec le registre EN_AA qui permet l’activation de l’auto-acknowledgment. Il s’agit d’une fonction qui permet à l’émetteur de confirmer que son message a bien été reçu. Je ferai un peu plus de test demain mais je pense avoir trouvé. En tout cas j’ai édité les codes de l’articles qui fonctionnent avec un launchpad équipé d’un G2553 et une Arduino nano (ou Uno et compagnie c’est pareil, testé sur Mega également, il suffit d’adapter les n° de pins).

Une remarque également : la librairie Arduino utilise le pipe 1 pour recevoir car apparemment c’est le pipe 0 qui reçoit les ACK, ce qui permet de le garder libre. C’est pourquoi sur le MSP430 il faut configurer le pipe 0 avec la même adresse que celle utilisée pour l’envoi, une façon de reconnaître la provenance de l’ACK et d’éviter tout conflit.

 

EDIT n°2 13/06/13 : deux points : j’ai approfondi le coup de l’auto-acknowledgment. Il faut également que ce paramètre soit synchronisé sur les deux parties ! Par défaut le nrf l’a d’activé, donc si on ne précise pas côté Arduino, il faut utiliser sur le MSP430 :

msprf24_open_pipe(0,1);

+

Il faut mettre d’adresse du destinataire en réception sur le pipe 0.

Si on ne veut pas d’ACK, dans ce cas on désactive côté arduino avec :

Mirf.configRegister(EN_AA,0); // ACK disabled

+

Côté MSP :

msprf24_open_pipe(0,0);

Second point le câblage. Bon côté Arduino y’a pas de mystère je pense. Côté MSP :

MISO P1.6
MOSI P1.7
SCK P1.5
CE P2.4
CSN P2.3

Attention, CE et CSN sont dépendants de ce que vous avez mis dans nrf_userconfig.h. Pour avoir cette config j’ai :


/* CSN SPI chip-select */
#define nrfCSNport 2
#define nrfCSNportout P2OUT
#define nrfCSNpin BIT3

/* CE Chip-Enable (used to put RF transceiver on-air for RX or TX) */
#define nrfCEport 2
#define nrfCEportout P2OUT
#define nrfCEpin BIT4