mardi 4 décembre 2012

EasyAVR AVRStudio et quelques exemples sur les I/O led et button

Introduction:

L'objet de ce post est de montrer (avec mes mots) comment réaliser l’interaction du MCU avec un bouton.
L'idée est de créer un code qui balaye des LED et inverse le sens dès que l'appui sur un bouton est détecté.

On utilisera pour cela une Macro.
Je profite aussi de ce post pour découvrir : la configuration des registres d'entrées/sorties (I/O); la création d'une fonction simple (juste pour structurer un peu le programme) et enfin, l'utilisation des macro.
Nota : la détection de l'appui sur le bouton ne se fera pas par le mécanisme des interruptions (on verra cela une autre fois pour les interruptions externes et logicielles).

Encore une fois, ce post se déroule dans le cadre d'un MCU ATMega16 avec un IDE AVRStudio et une plateforme matériel EasyAVR 6.

Configuration des registres d'entrées/sortie PORT:

Chez Atmel, sur les ATMega 16, il existe 3 registres en charge de la configuration des entrées/sorties TOR -Tout Ou Rien.
  • Un gros : le registre DDRx (avec x = A, B, C ou D) permet de configurer si l'entrée physique est de type entrée (0) ou sortie (1).
Par Exemple :

DDRA = 0b 01011100;
Dans ce cas là, alors les broches 2, 3 4 et 6 sont de types Sortie (Output). Tandis que les autres broches sont des entrées.
  • Le registre PORTy (avec y = A, B, C ou D) permet: 
    • de forcer un état logique haut = 1 ou bas =0 (si et seulement si la borne DDRx correspondante a été configurée en mode output)
    • OU
    • de forcer la mise en place d'une résistance de Pull-Up (tirage à +VDD du MCU) si 1 et aucune résistance si 0 (si et seulement si la borne DDRx correspondante a été configurée en mode input).
Par exemple si l'on a le code suivant : 
DDRB = 0b 01011000;
PORTB = 0b 01101100;
Signifie que la broche 0 est de type entrée sans résistance de Pull-Up.
Signifie que la broche 2 est de type entrée avec une résistance de Pull-Up.
Signifie que la broche 6 est de type sortie et que l'état est forcée à 1 (haut logique).
Signifie que la broche 4 est de type sortie et que son état est forcée à 0 (bac logique).

==>Bien entendu, de nombreux cas sont possibles. J'ai pris le partie d'utiliser une notation binaire (0b) pour bien "montrer" l'incidence sur les bit. 

  • Le registre PINz (avec z = A, B, C ou D) permet de lire / récupérer l'état de la broche si et seulement si la borne DDRx correspondante a été configurée en mode input et cela quelque soit la présence de la résistance de Pull-Up.
Nota : l'activation de la résistance de Pull-Up ou pas, n'a pas grand chose à voir avec l'aspect "programmation" du MCU. Cela tient plutôt de considération électronique (que j'essaierai d'expliquer une autre fois).

Création d'une fonction pour commencer à structurer le code : 

Loin de moi l'idée de vouloir rentrer dans les explications sur les fonctions en C pour AVR (je comprends pas tout pour le moment :) ).  L'idée est plutôt de montrer l'intérêt des fonctions en C ne serait-ce que pour la structuration du code (là, les fanatiques de C doivent bondir et fabriquer un IED à mettre sous ma voiture....).
Je fais donc créer une fonction très simple qui aura la charge de réaliser le chenillard à LED. La fonction ne renverra aucune valeur--> syntaxe void ; pas plus qu'elle n'utilisera de paramètre en entrée -->paramètre void . Voici ce que l'on obtient donc pour la définition de la fonction.




void led_chaser(void)
{
int i=0;
for (i=256;i>0;i=i/2)
{
PORTA = i;
_delay_ms(500);
}
PORTA=0; }



Rien à dire en particulier sur ce code, qui a déjà été abordé lors d'un précédent post ici.

En ce qui concerne l'appel de la fonction, il suffit d'utiliser la syntaxe suivante : led_chaser(); .
C'est entre les parenthèses que l'on aurait passé les arguments de la fonction. 

Présentation de la Macro pour lire l'état de l'entrée à scruter :

Pour lire un état PINB7 par exemple, il suffit d'utiliser la syntaxe suivante :
PIN
Explication : (merci l'algèbre de Boole)
Si l'on part de la table de vérité d'un ET et d'un OU alors cela devient clair.
En effet, si l'on part du mot 0011, qu'elle est l'opération qui laisse les bit inchangé ?
--> Un "ET" avec un 1 bien sûr !
Donc, si l'on désire "lire" l'état sur le bit 7, PB7 de notre entrée, il suffit de réaliser l'opération suivante:
               01010110
       ET   01000000
               -----------
               01000000   --> là on ne récupère donc que la valeur du bit 7 ! !
C'est ce que l'on appel la technique du Masque. Google est votre ami et vous trouverez tous pleins d'explication plus efficace que les miennes avec des mots clefs tel que Bitwise, AVR, bit manipulation, etc...

Du point de vue code AVR GCC, cela se traduit de la manière suivante :
byte result = PINB & 0x40;
En utilisation avec une structure de "IF", cela donne quelque chose du genre :
if(PINB & (1<<PINB7))
Ici, on utilise la syntaxe 1<<PINB7 en équivalent de 0x40 = 0b01000000
Nota : pour une lecture en mode "normalement ouvert" de l'interrupteur, on utilisera la syntaxe :
if~(PINB & (1<<PINB7))

Voilà sur le principe.
Et la macro alors dans tous cela ?
Et bien les inventeurs de tous cela, ont pensé qu'il serait pertinent de définir des macro pour réaliser tous ces types d'opération de base.
Par exemple, la lecture de la valeur d'une I/O est "macrotisée" en :
#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT)) // Macro to check bit
Et à l'utilisation, cela donne :
if (CHECKBIT(PINB,7))

Exemple de code "complet" en C:


/*
 * LedAndButton.c
 *
 * Created: 04/12/2012 21:45:31
 *  Author: Florent Tainturier
 *  Test of tutorial for changing the direction of led chaser with input button
 */
#define F_CPU 1000000UL
#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT)) // Macro to check bit
#include <avr/io.h>
#include <util/delay.h>


int main(void)
{
//Configuration of PORT
DDRB= 0x7f; // 1 as output; 0 as input
DDRA= 0xFF; //all as output
PORTB = 0x00;
    while(1)
    {
//if (CHECKBIT(PINB,7))
if(~PINB & (1<<PINB7))
{
led_chaser();
} else
{
led_chaserPortB(); }
    }
}
void led_chaser(void)
{
int i=0;
for (i=256;i>0;i=i/2)
{
PORTA = i;
_delay_ms(500);
}
PORTA=0; }
void led_chaserPortB(void)
{
int i=0;
for (i=1;i<=256;i=i*2)
{
PORTB = i;
_delay_ms(500);
}
}

dimanche 2 décembre 2012

Prise en main de EasyAVR 6


               1-Introduction et Installation:


Et bien voilà, c'est la grand jour et le papa Noël est passé avec un peu d'avance (normal il venait de Budapest).
Par soucis d'économie, je suis directement partie sur le kit EasyAVR avec un code de réduction qui allait bien.
Bref, le plus dure à été de déballer la carte de son corset anti-statique ! En effet, l'emballage est vraiment très protecteur....à tel point qu'il devait presque délicat de sortir la carte de son emballage. Ci-dessous une illustration du contenu du kit (LCD et TFT non visible).

Le kit est bien fournis, avec une version papier du manuel utilisateur. Après, on regrettera le fait que tout le manuel utilisateur de MikroC ne soit pas fournis en version papier.
Les DVD d'installation sont également présent.

Pour l'installation, il suffit d'insérer le DVD fourni et de réaliser l'installation de MikroC Pro (ou pas) puis des différent Driver.
Si comme pour moi, le DVD semble avoir une faiblesse....alors contourner cela depuis le site de MikroE par téléchargement des logiciels et driver.
Veillez à bien respecter l'ordre d'installation : logiciel, puis driver et ENFIN raccorder la carte au PC avec le câble USB !
Sinon, vous aurez gagné le droit à un fonctionnement erratique...
Une fois l'installation terminée, vous aurez le droit à un redémarrage du PC en règle !


               2-Premier Code--Hello World

On va démarrer avec un premier code simple. Il s'agira de réaliser un petit chenillard sur les LED (2 rangées)   raccordées sur les ports A et B du ATmega16.


Bien que l'IDE MikroC Pro soit sympa, celui de Atmel AVRStudio reste une référence. C'est pourquoi le code sera "montré" pour les 2 IDE et les différences expliquées.

Configuration :

La configuration choisie repose sur une utilisation directe des ports du MCU (MicroControllerUnit, terme utilisé par la suite pour définir le microcontroller).
Donc, on utilise directement les ports en Output. Cette configuration s'effectue dans le registre : DDRx, où x = A, B , C etc...
Dans notre exemple on obtient donc la syntaxe suivante (en hexa 0x):
DDRA = 0xFF;
Désormais toute les "Pin" du port A sont de type "Output". Elles vont donc pouvoir driver un courant de 20mA , max 200mA (données issues de la Datasheet de l'ATmega16). Concrètement, on obtient le schéma électrique suivant :
Illustration du schéma électronique de la sortie LED ATMega16 EasyAVR (schéma réalisé sous KiCad).

Forcer une sortie à un état logique:

Pour forcer une sortie à un état logique (1 ou 0), il existe plusieurs syntaxe en C. Nous évoquerons ici que les syntaxes testées (et comprises :) ). On verra par la suite les autres possibilités.
PORTA = 0;
Permet de forcer toutes les sorties à 0 du port A
PORTB = 0xff;
Permet de forcer toutes les sorties à 1 du port B (notation en hexa).

Pour forcer un bit particulier du registre PORTx, on peut aussi employer la syntaxe suivante :
PORTA.B4= 1;
Attention : cette syntaxe est valable sous l'environnement MikroC.
Il existe un équivalent générique sous AVRStudio (non présenté ici).
Dans le cas présent, cela signifie que le bit 4 du portA est mis ) l'état logique 1.

Contrainte du chenillard:

C'est l'architecture électronique qui impose le programme à rédiger. Dans le cas présent, chaque sortie étant directement reliées à une LED, alors il va falloir "balayer" le port A.
Une des méthodes possibles est d'utiliser la boucle FOR.
A chaque itération de la boucle, on viendra inscrire une valeur différente dans le registre PORTA.

==> i=i*2  st l'incrément à mettre en place pour avoir un changement de bit et compter de "2 en 2" et obtenir l'effet chenillard souhaité.

Exemple de code sous MikroC:


int i=0;
const unsigned long delay = 100;
void main() {
     DDRA = 0xFF;
     PORTA = 0;
     while(1){
              for (i=1;i<256;i=i*2) {
                   PORTA= i;
                   Delay_ms(delay);
              }
              PORTA = 0;
              Delay_ms(delay);
              PORTA = 0xff;
              Delay_ms(500);
              PORTA = 0;
              Delay_ms(500);
              PORTA = 0xff;
              Delay_ms(500);
              PORTA = 0;
     }
   
}



Exemple de code sous AVRStudio:



/*
 * Blinkg_HelloWorld_AVRStudio.c
 *
 * Created: 02/12/2012 16:46:15
 *  Author: Maison
 */

#include <avr/io.h>
#include <util/delay.h>

int i=0;
const unsigned long delay = 100;
int main(void)
{ //Setting of the port
DDRA = 0xFF; //Toutes les sorties en mode output
PORTA = 0;   // sortie à l'état bas
DDRB = 0xFF; //Toutes les sorties en mode output
PORTB = 0;   // sortie à l'état bas
    while(1)
    {
for (i=1;i<256;i=
i*2) {
PORTA= i;
_delay_ms(delay);
}
PORTA = 0;
_delay_ms(delay);
PORTA = 0xff;
_delay_ms(delay);
PORTA = 0;
_delay_ms(delay);
PORTA = 0xff;
_delay_ms(delay);
PORTA = 0;
for (i=1;i<256;i=i*2) {
PORTB= i;
_delay_ms(delay);
}
PORTB = 0;
_delay_ms(delay);
PORTB = 0xff;
_delay_ms(delay);
PORTB = 0;
_delay_ms(delay);
PORTB = 0xff;
_delay_ms(delay);
PORTB = 0;
} }

Et voici une courte vidéo pour le résultat finale :

3-Mais comment charger le code AVRAtmel depuis EasyAVR

J'essaierai de rajouter des captures d'écran une prochaine fois.
Mais il suffit de charger le .hex généré depuis AVRStudio depuis l'utilitaire AVRFlash Prog de MikroElektronika.

Nota : il est aussi possible d'utiliser le port JTAG ou AVRISP de l'EasyAVR pour utiliser un programmateur externe. Mais j'essaierai d'illustrer cela une prochaine fois.






jeudi 22 novembre 2012

Atmel AVR Studio 6 + Arduino Mega 2560 + Avrdude : premier pas

Un petit post très rapide pour mettre au propre les idées de ce soir.
Sur les conseils d'un éminent ami, je suis (enfin) passé sous AVR Studio en lieu et place de l'IDE Arduino... Ceci dans le but de faire du vrai C.
Bref passons.

Le test de ce soir est un simple Blinky depuis une carte Arduino Mega 2560.
Voici le code :

/*
* Blinky.c
*
* Created: 22/11/2012 21:49:32
* Author: Florent Tainturier
* Description du projet :
* Premier tutoriel avec AVR Studio et Arduino Mega
*/




#include <avr/io.h>
#include <avr/delay.h>

int main(void)
{
//Configuration du portb
DDRB |= (1<<PB7);
while(1)
{
PORTB |= (1<<PB7); //Led sur la PIN3 = PB7
_delay_ms(1000);
PORTB &= ~(1<<PB7);
_delay_ms(1000);
//TODO:: Please write your application code
}
return 1;
}
 Bon, rien de très transcendant.
L'intérêt est la manipulation de la ligne AVRDUDE.

Voici la ligne soumise :
avrdude -p m2560 -c avrisp -P com6 -c arduino -F -U flash:w:Blinky.hex
Et voici la vilaine réponse :
avrdude: stk500_getsync(): not in sync: resp=0x00  
D'après les informations des forums, il semble que le problème proviennent de l'ancien IDE arduino utilisé.
(source : http://franck.simon.free.fr/?p=236 ).

Essayons...
Bon, cela ne fonctionne toujours pas....-->Je pense que le problème vient des options...

Mise à jour du 23/11/2012:
Après quelques recherches sur le net (ici : http://kevintechnology.com/post/25156701195/programming-arduino-mega-using-avrdude) et surtout avec le support appuyé d'un collègue, voici la nouvelle ligne soumise à AVRDude:
avrdude -p m2560 -c stk500v2 -P COM6 -b 115200 -F -U flash:w:Blinky.hex
...
Toujours mieux...

Bon, il semble qu'il y ait également une piste du coté du DFU programmer de l'arduino (source : http://arduino.cc/en/Hacking/DFUProgramming8U2 ) ==> à tester.



lundi 15 octobre 2012

Arduino-Premier tutoriel avec un LCD

Et bien après pas mal d'attente, me voici (enfin) parti à l'assaut d'un premier test.
En effet, j'ai enfin convergé vers un projet de montage.
Il s'agit d'une sorte de télécommande pour mon Pentax. Pour le moment, je n'en dis pas plus car je pense que cela fera l'objet d'un post à part entière.

Dans tous les cas, ce projet (simple et modeste) requiert une interface graphique. Quoi de plus simple que l'utilisation d'un afficheur LCD 2x16 caractères ? (un 7 segments....)
Du coup, je suis partie jeter un coup d'oeil à l'ensemble des excellents tutoriaux disponibles sur la toile (site de Adafruit, forum de Snootlab, etc...et j'en passe).
Là, je ne vais pas réinventer la poudre. Le code Arduino est en parti celui livré avec le logiciel. Après, ce sont surtout les modifications des codes d'exemples qui sont intéressant afin de bien comprendre les librairies et leurs potentiels.

De ce fait, je poste uniquement le schéma (réalisé sous l'excellent Kicad) du montage de base.
J'ai fait le choix d'un montage en utilisant l'intégralité des bornes de l'afficheur LCD. La librairie Arduino (LiquidCrystal) permet bien entendu de n'utiliser que les 4 premières lignes de Data. Libre à chacun.
Il est vrai que pour le besoin futur du projet, c'est plutôt ce mode là qui sera retenu. Ceci afin de limiter la consommation des GPIO de la carte.
Les deux dernières bornes XX et XX (ne sont pas représentées dans ma librairie Kicad). Elles symbolisent les bornes +5V et GND nécessaire à l'alimentation du rétro-éclairage du LCD.


Schéma Kicad--Raccord carte Arduino Mega + LCD (rien de bien foudroyant....)


Nota:

  • Pour les personnes intéressées, je peux fournir une librairie complète pour le LCD que j'ai employé. Il s'agit d'une librairie Kicad qui inclut : la schématique, le fichier .mod et même le fichier 3D. Bon, cette librairie n'est pas parfaite (surtout le 3D). En revanche, le .mod permet de réaliser des PCB pour réaliser des shields d'adaptation.
  • En ce qui concerne le schéma de la carte Arduino Mega, il s'agit en fait d'une librairie d'un Shield détourné. Cette librairie est gracieusement disponible sur le site suivant (un grand merci à l'auteur) : http://www.thingiverse.com/thing:5280



dimanche 30 septembre 2012

Test avec GoogleMap

Message vide pour le moment


Et voici la carte de notre périple du premier jour !
à insérer


Afficher Voyage Rome--Premier Jour-Partie 1 / sur une carte plus grande

Au final, si l'on en croit Google....nous avons réalisé un parcourt d'environ 17km sur la première journée.
De quoi mériter une bonne pizza !

samedi 4 août 2012

Arduino Mega2560--Premier Pas et installation Windows 7

Et bien, ca y est !

Après commande sur snootlab et 4 jours de validation de commande de délais postal, tout est arrivé à bon port !

Du coup, j'ai vite déballé mes nouveaux jouets!
Starter Kit de SnootLab--de quoi démarrer pour le moment
Arduino Mega 2560 dans son emballage d'origine (Made in Italy)--Le Stylo permet de se rendre compte de la taille.

La bêtbête sans son emballage

Le contenu du StarterKit--Breadboard en Rouge !

L'afficheur LCD 2 lignes--j'ai préféré la version (très) épurée pour démarrer

Et voilà l'ensemble de la commande.
 Bon, pour la prise en main, je suis parti sur l'ensemble des explications disponibles sur:

Alors, pour éviter de faire la même erreur que moi, un conseil, si vous tournez sous Windows 7 : il est nécessaire de mettre à jour le driver FTDI pour la version 64 bits.
Ce driver est disponible sur le site officiel de FTDI : http://www.ftdichip.com/Drivers/VCP.htm
Une fois ceci fait, j'ai pu passer à la connexion de l'arduino sur le PC.

Le raccord sur le port USB entraine un grognement de Windows.
Depuis le logiciel Arduino, rien ne se passe et le port n'apparait pas (Outils-->Port Série)...
La raison est mieux expliquée dans le lien ci-dessus.
Concrètement, il suffit d'aller dans le gestionnaire de périphérique (touches Windows + Pause). La Page d'information de Windows apparait dans une fenêtre. Ensuite, on clique sur "Gestionnaire de périphérique". Là, tous les périphériques de votre PC apparaissent dans un menu Liste.
Naviguer jusqu'à la ligne "Ports (COM et LPT)":
  • Soit votre arduino apparait,
  • soit elle n'apparait pas...comme moi.
 Pour ma part, il a fallu que je navigue dans la liste pour trouver un "périphérique inconnu". Là, j'ai fait un clique droit puis "Mettre à jour le périphérique". Dans la fenêtre qui apparait, j'ai sélectionné l'option "Rechercher un pilote sur mon ordinateur". Après quoi, j'ai été rechercher l'emplacement des driver FTDI 64 bits nouvellement installé.
Après quelques secondes de réflexion de Windows, une fenêtre de validation est apparu, et la liste des périphériques a été mise à jour avec l'Arduino (voir image ci-dessous).

Gestionnaire de Périphériques--Windows 7


Et voilà, à partir de là, la carte Arduino est correctement installé sur Windows 7.
Le logiciel Arduino est capable de trouver le bon port série de communication (Outils-->Port Série-->COM6 dans mon cas).
Un rapide essai avec le fichier d'exemple "Blink" permet de valider tout cela.

La suite, une prochaine fois.