Cours:TPS 2103 5 : Différence entre versions

De troyesGEII
Aller à : navigation, rechercher
m (Présentation)
m (Changer la vitesse de transmission)
Ligne 136 : Ligne 136 :
 
=={{Bleu|Travail à réaliser}}==
 
=={{Bleu|Travail à réaliser}}==
 
===Changer la vitesse de transmission===
 
===Changer la vitesse de transmission===
 +
La librairie présentée fonctionne pour une vitesse de transmission de 9600 bauds. Cette vitesse est choisie
 
{{Question|Modifier la librairie pour la faire fonctionner à 19200 bauds.}}
 
{{Question|Modifier la librairie pour la faire fonctionner à 19200 bauds.}}
 +
 
===Changer le rapport cyclique===
 
===Changer le rapport cyclique===
 
On désire changer l'intensité d'éclairage d'une LED à l'aide d'une PWM rapide. La valeur du rapport cyclique varie entre 0 et 255 et sera systématiquement envoyée par la liaison série sous forme de deux caractères 0,...,9,A,...,F.
 
On désire changer l'intensité d'éclairage d'une LED à l'aide d'une PWM rapide. La valeur du rapport cyclique varie entre 0 et 255 et sera systématiquement envoyée par la liaison série sous forme de deux caractères 0,...,9,A,...,F.

Version du 3 septembre 2014 à 22:08

Communication série asynchrone rs232

Vous avez déjà eu l'occasion d'utiliser cette liaison avec les primitives Arduino. Rappelez-vous le programme utilisé pour sortir les valeurs des capteurs analogiques :

void setup()
{
  Serial.begin(9600);
}
 
void loop()
{
  Serial.print("Photocoupleur : ");
  Serial.println(analogRead(A2),DEC);
  delay(500);  
}

Nous allons maintenant utiliser cette liaison en C.

La partie du circuit spécialisée gèrant la liaison série (ou RS232) s'appelle une UART.

Trame RS232

On rappelle que ce type de liaison série permet d'envoyer des informations sans horloge de référence. Elle est à un logique au repos. Une trame est composée des 8 bits à transmettre, précédé d'un bit de start ("0" logique), et suivi par au moins un bit de stop ("1" logique). Le bit de stop peut être doublé et éventuellement précédé par un bit de parité. Pour une parité paire, le bit de parité est mis à "0" quand le nombre de "1" est pair tandis qu'une parité impaire met à "0" pour un nombre impair de "1".

La vue de l'image ci-contre semble indiquer le contraire de ce que je suis en train d'expliquer. Mais n'oubliez pas que du point de vue électrique, un niveau logique "0" est représenté par une tension de +3 V à +25 V et un niveau logique "1" par une tension de -3 V à -25 V (codage NRZ). Ordinairement, des niveaux de +12 V et -12 V sont utilisés.

Comme nous allons utiliser pour nos essais des platines Arduino pour lesquelles la liaison série est réalisée à l'aide de l'USB, les problèmes de tension n'ont pas lieu.

La liaison série est très populaire à cause de son évolution justement avec l'USB et surtout que tous les systèmes d'exploitation proposent un logiciel pour communiquer par la liaison série. Il est appelé hyperterminal sous Windows. Même si nous utilisons essentiellement Linux pour nos essais, nous continuerons à l'appeler hyperTerminal.

Présentation

Une librairie d'utilisation

Nous avons trouvé sur Internet la librairie suivante qui a été écrite pour un ATMega168. Nous l'avons fait fonctionner telle quelle sur un ATMega2560 et la platine Arduino correspondante. Nous la publions avec quelques modifications.

 /*
Title:		SerialCom.c 
Date Created:   6/9/2009
Last Modified:  6/9/2009
Target:		Atmel ATmega168
Environment:	AVR-GCC 
  Note: the makefile is expecting a '168 with a 16 MHz crystal.
Adapted from the Arduino sketch "Serial Call and Response," by Tom Igoe.
  //  This program sends an ASCII A (byte of value 65) on startup
  //  and repeats that until it gets some data in.
  //  Then it waits for a byte in the serial port, and 
  //  sends three (faked) sensor values whenever it gets a byte in.
Written by Windell Oskay, http://www.evilmadscientist.com/
Copyright 2009 Windell H. Oskay
Distributed under the terms of the GNU General Public License, please see below.
Additional license terms may be available; please contact us for more information.
More information about this project is at 
http://www.evilmadscientist.com/article.php/peggy
-------------------------------------------------
USAGE: How to compile and install
A makefile is provided to compile and install this program using AVR-GCC and avrdude.

To use it, follow these steps:
1. Update the header of the makefile as needed to reflect the type of AVR programmer that you use.
2. Open a terminal window and move into the directory with this file and the makefile.  
3. At the terminal enter
		make clean   <return>
		make all     <return>
		make program <return>
4. Make sure that avrdude does not report any errors.  If all goes well, the last few lines output by avrdude
should look something like this:

avrdude: verifying ...
avrdude: XXXX bytes of flash verified
avrdude: safemode: lfuse reads as E2
avrdude: safemode: hfuse reads as D9
avrdude: safemode: efuse reads as FF
avrdude: safemode: Fuses OK
avrdude done.  Thank you.
If you a different programming environment, make sure that you copy over 
the fuse settings from the makefile.
-------------------------------------------------
This code should be relatively straightforward, so not much documentation is provided.  If you'd like to ask 
questions, suggest improvements, or report success, please use the evilmadscientist forum:
http://www.evilmadscientist.com/forum/
-------------------------------------------------
 This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include <avr/io.h> 

#define F_CPU 16000000	// 16 MHz oscillator.
#define BaudRate 9600
#define MYUBRR (F_CPU / 16 / BaudRate ) - 1 

unsigned char serialCheckRxComplete(void)
{
	return( UCSR0A & _BV(RXC0)) ;		// nonzero if serial data is available to read.
}

unsigned char serialCheckTxReady(void)
{
	return( UCSR0A & _BV(UDRE0) ) ;		// nonzero if transmit register is ready to receive new data.
}

unsigned char serialRead(void)
{
	while (serialCheckRxComplete() == 0)		// While data is NOT available to read
	{;;} 
	return UDR0;
}

void serialWrite(unsigned char DataOut)
{
	while (serialCheckTxReady() == 0)		// while NOT ready to transmit 
	{;;} 
	UDR0 = DataOut;
}

void serialInit(void) {
  //Serial Initialization
 	/*Set baud rate 9600 */ 
	UBRR0H = (unsigned char)(MYUBRR>>8); 
	UBRR0L = (unsigned char) MYUBRR; 
	/* Enable receiver and transmitter   */
	UCSR0B = (1<<RXEN0)|(1<<TXEN0); 
	/* Frame format: 8data, No parity, 1stop bit */ 
	UCSR0C = (3<<UCSZ00);	
}

Cette librairie a été utilisée avec succès avec une platine Arduino MEGA2560 ou une carte UNO mais ne peut pas être utilisée avec une carte Leonardo !!!

Travail à réaliser

Changer la vitesse de transmission

La librairie présentée fonctionne pour une vitesse de transmission de 9600 bauds. Cette vitesse est choisie Question.jpg Modifier la librairie pour la faire fonctionner à 19200 bauds.

Changer le rapport cyclique

On désire changer l'intensité d'éclairage d'une LED à l'aide d'une PWM rapide. La valeur du rapport cyclique varie entre 0 et 255 et sera systématiquement envoyée par la liaison série sous forme de deux caractères 0,...,9,A,...,F. Question.jpg Un sous-programme sera donc chargé de lire ces deux caractères d'en vérifier la syntaxe. Écrire ce sous-programme et le tester avec les afficheurs de l'exercice 6. On affichera "--" en cas d'erreur de syntaxe.

Question.jpg Changer votre programme de test précédent pour qu'il réalise un rapport cyclique sur le bit OC0A du PORTB.

Communication par bus SPI

Brochages de quelques cartes Arduino pour le SPI

Voici présenté les brochages utilisés par les cartes Arduino que nous possédeons à l'IUT :

SPI MISO MOSI SCK SS
UNO PB4 (Arduino:12) PB3 (Arduino:11) PB5 (Arduino:13) PB2 (Arduino:10)
LEONARDO PB3 (ICSP:1) PB2 (ICSP:4) PB1 (ICSP:3) -
MEGA2560 PB3 (Arduino:50) PB2 (Arduino:51) PB1 (Arduino:52) PB0 (Arduino:53)

Comme on peut le voir dans ce tableau, les broches utilisées pour SPI sur la Leonardo ne sont pas reliées aux connecteurs mais directement sur le programmateur ICSP. Il n'y a aucune broche dédiée au SS.

Pour éviter des recherches sur internet, nous rappelons la connectique associée des six broches avec les deux photos ci-dessous :

Connectique SPI

Voici par exemple ci- dessous la connectique ICSP présente sur une carte Arduino.

Connectique ISP de l'Arduino

Dialoguer en i2c avec une manette Nunchuk

Adaptation de tensions

Les cartes Arduino que nous utilisons sont en général en 5V. Il existe cependant un certain nombre de périphériques I2C qui sont en 3,3V. La manette Nunchuk en est un exemple. Il faut donc réaliser une adaptation bidirectionnelle. Ce genre d'adaptation est décrit par exemple dans ce lien.

La manette Nunchuk est quant à elle décrite dans la WIKIVersité et aussi ici (rédigé par les étudiantes KONAK Sumeyye et SAVRY Maelle).

Exemple de programme

#include <Servo.h>;
#include <Wire.h>;

// Doit être ajusté en fonction de chaque nunchuck
#define ZEROX 530
#define ZEROY 530
#define ZEROZ 530


// adresse I2C du nunchuck
#define WII_NUNCHUK_I2C_ADDRESS 0x52

// définition d'une variable Servo
Servo servomoteur;
// définition d'une variable counter
int counter;

// définition d'un tableau de données
uint8_t data[6];


void setup()
{
  // on attache le servomoteur à la pin 11 (PWM) 
  servomoteur.attach(11);
  // initialisation du nunchuck
  Wire.begin();
  Wire.beginTransmission(WII_NUNCHUK_I2C_ADDRESS);
  Wire.write(0xF0);
  Wire.write(0x55);
  Wire.endTransmission();

  Wire.beginTransmission(WII_NUNCHUK_I2C_ADDRESS);
  Wire.write(0xFB);
  Wire.write(0x00);
  Wire.endTransmission();
}


void loop()
{ 
  // on demande 6 octets au nunchuck
  Wire.requestFrom(WII_NUNCHUK_I2C_ADDRESS, 6);
  counter = 0;  // tant qu'il y a des données
  while(Wire.available())
  {
    // on récupère les données
    data[counter++] = Wire.read();
  }

  // on réinitialise le nunchuck pour la prochaine demande
  Wire.beginTransmission(WII_NUNCHUK_I2C_ADDRESS);
  Wire.write(0x00);
  Wire.endTransmission();

  if(counter >= 5)
  {
     // on extrait les données
     // dans mon exemple j'utilise uniquement les données d'accélération sur l'axe Y
     double accelX = ((data[2] << 2) + ((data[5] >> 2) & 0x03) - ZEROX);
     double accelY = ((data[3] << 2) + ((data[5] >> 4) & 0x03) - ZEROY);
     double accelZ = ((data[4] << 2) + ((data[5] >> 6) & 0x03) - ZEROZ);

     // on limite la valeur entre -180 et 180
     int value = constrain(accelY, -180, 180);
     // on mappe cette valeur pour le servomoteur soit entre 0 et 180
     value = map(value, -180, 180, 0, 180);
     // on écrit sur le servomoteur la valeur
     servomoteur.write(value);

     // un petit delai pour pas saturer le servomoteur
     delay(100);
   }
}