Des ressources téléchargeables pour vos projets.



Lire et écrire sur une carte SD.
Ecriture automatique sur carte SD.
Grille évaluation oral anglais 1.
Extraction trame GPS.
Comptage de vibrations par interruption.

Ecrire et lire sur une carte SD avec arduino.

Voici un programme qui permet d'écrire et de lire sur une carte SD avec un Arduino.
Il vous faut une carte Ethernet pour la carte SD.

Ce programme permet d'enregistrer dans un fichier texte les données de deux résistances variables câblées sur les entrées A0 et A2 de l'arduino. Il vous faut créer le fichier texte "resvar.txt" sur la carte SD au péalable.

#include <SPI.h>
#include <SD.h> // crée automatiquement un objet racine SD représentant la carte mémoire SD
int ajustable1 = A0;
int ajustable2 = A2;
float V1;
float V2;
File myFile; // objet file
char fileName[] = "resvar.txt"; // tableau de caractères pour le nom du fichier
char pathFile[] = "/resvar.txt"; // tableau de caractères pour le nom du fichier
int test;
void setup()
{
Serial.begin(9600); // utiliser le meme debit coté Terminal Serie
//----- initialisation de la carte SD -----
Serial.println("Initialisation de la SD card...");
pinMode(10, OUTPUT); // laisser la broche SS en sortie - obligatoire avec librairie SD
test=SD.begin(4); // initialisation de la carte SD avec broche 4 en tant que CS - renvoie true/false
if (test!=true) { // si initialisation n'est pas réussie
Serial.println("Echec initialisation!"); // message port Série
}
else { // si nitialisation réussie
Serial.println("Initialisation reussie !"); // message port Série
} // fin si SD.begin
//----- test de l'existence d'un répertoire
test=SD.exists(pathFile); // test si le répertoire existe - renvoie true/false
Serial.print ("Test="); Serial.println(test);
if (test!=true) { // si le répertoire n'existe pas
Serial.println ("Le fichier n'existe pas !");
}
else { // si le répertoire existe
Serial.println ("Le fichier existe !");
//SD.remove(pathFile); // efface le fichier
//Serial.println ("Fichier efface !");
//----- ouverture du fichier ---
}
}// fin setup()
void loop()
{
myFile=SD.open(pathFile,FILE_WRITE); // ouvre le fichier en écriture et crée fichier si existe pas
//Serial.print ("Test="); Serial.println(test);
if (myFile!=true) { // si échec ouverture
Serial.println ("Echec ouverture fichier !");
}
else { // si ouverture réussie
Serial.println ("Ouverture fichier reussie !");
myFile.seek(myFile.size()); // positionnement à la fin du fichier
Serial.println ("Positionnement a la fin du fichier!");
V1 = analogRead(ajustable1);
V1 = V1 / 204.8;
// myFile.println(); // ajoute un saut de ligne
myFile.println("Resistance 1"); // ajoute une ligne
myFile.println(V1); // ajoute la ligne au fichier
delay(3000);
V2 = analogRead(ajustable2);
V2 = V2 / 204.8;
// myFile.println(); // ajoute un saut de ligne
myFile.println("Resistance 2"); // ajoute une ligne
myFile.println(V2); // ajoute la ligne au fichier
delay(3000);
/*-- affiche une nouvelle série de 30 valeur
for (int i=0; i<30; i++) {
myFile.println(i); // ajoute la ligne au fichier
}
*/
myFile.close(); // fermeture du fichier
Serial.println ("Fermeture fichier effectuee!");
test=SD.exists(pathFile); // test si le fichier existe - renvoie true/false
Serial.print ("Test="); Serial.println(test);
if (test!=true) { // si fichier existe pas
Serial.println ("Le fichier existe pas !");
}
else { // si fichier existe
Serial.println ("Le fichier existe !");
} // fin else si fichier existe
} // fin else si ouverture répertoire réussie
}// fin else si répertoire

Télécharger le fichier arduino.

Exemple d'écriture automatique du taux d'humidité sur une carte SD.

Le capteur utilisé est un DHT 22.
Les données "humudité" et "température" sont écrites sur la carte SD toutes les 3 secondes.

#include <SPI.h>
#include <SD.h> // crée automatiquement un objet racine SD représentant la carte mémoire SD
#include "DHT.h"
#define DHTPIN A0
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
File myFile;
char fileName[] = "data_atm.txt";
char pathFile[] = "/data_atm.txt";
int test;

void setup()
{
  pinMode(3, OUTPUT);
  dht.begin();
  pinMode(10, OUTPUT); // laisser la broche SS en sortie - obligatoire avec librairie SD
  test=SD.begin(4); // initialisation de la carte SD avec broche 4 en tant que CS - renvoie true/false
}  

void loop()
{
  myFile=SD.open(pathFile,FILE_WRITE);  
  myFile.seek(myFile.size()); // positionnement à la fin du fichier
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  myFile.print("Humidity: "); 
  myFile.print(h);
  myFile.print(" %\t");
  myFile.print("Temperature: "); 
  myFile.print(t);
  myFile.println(" *C");
  delay(3000);
  myFile.close();
}

Télécharger le fichier arduino.

L'oral d'anglais LV1 Techno Partie 1.

L'épreuve d'anglais technologique se déroule en cours d'année en deux parties.
Seuls les points supérieurs à 10 sur 20 sont pris en compte ( Coëfficient 2).
La première partie de l'épreuve porte sur la conduite du projet. L'évaluation est individuelle. Elle est notée sur 10.
Les compétences de communication du candidat en langue vivante 1 sont évaluées dans le contexte de la conduite de projet. ( note de service n° 2014-132 du 13-10-2014)


Objectifs de l'évaluation :
- Le candidat a bien compris et expliqué les enjeux du projet
- Il a bien cerné et su expliquer les enjeux techniques les plus importants à surmonter
- Il a su démontrer ses capacités à faire des choix justifiés d’architecture technique
- En cas de doute et de demande d’aide, il a su expliquer de manière intelligible tous les obstacles techniques qu’il a du mal à surmonter et formuler éventuellement des propositions de résolution de ces obstacles


Remarque
Cette grille d'évaluation est en accès libre sur internet mais à destination des enseignants. Certains termes vous sembleront peut être obscurs. Elle vous est donnée ici uniquement à titre informatif. Le contenu à présenter pendant l'épreuve orale vous sera précisé en cours et correspond approximativement à la revue de projet 2.

Télécharger la grille d'évaluation au format pdf.

Extraction des trames GPS NMEA

Pour certains projet, vous avez besoin d'extraire une trame particulière parmis toutes celles envoyées par le système GPS.
Le programme ci dessous permet, par la technique du parsing d'extraire uniquement les trames GGA.
Attention !! Il faut utiliser une carte Arduino Mega.

#define offset_utc        07
 #define offset_latitudeDegres   18  
 #define offset_latitudeMinutes   20  
 #define offset_latitudeDecimaux   23  
 #define offset_lattitudeOrientation   28    
 #define offset_longitudeDegres  30
 #define offset_longitudeMinutes  33
 #define offset_longitudeDecimaux  36
 #define offset_longitudeOrientation  41
 #define offset_fix        43
 #define offset_satellite  45
 #define offset_altitude   52
 #define offset_checksum   72
 char trameRecu[600]; //tableau qui recoit la trame nmea qui contient toute les trames envoyées pendant une periode données
 char trameGPGGA[80]; //tableau qui recoit une trame GPGGA contenu dans trameRecu
 char prefixTrame[6];  //tableau de 6 caractères por stocker le prefix de la trame traitée

 
 char latitudeDegres[6],latitudeMinutes[6],latitudeDecimaux[6],longitudeDegres[6],longitudeMinutes[6],longitudeDecimaux[6],latitudeOrientation[1],longitudeOrientation[1] , utc[10] ,hauteur[10]; 
 int tailleTrameRecuMax = 600;
 int indexTrameRecu=0;
 

 
 void setup()
 {
       Serial.begin(115200); // liaison série à 115200 bauds avec le PC
       Serial1.begin(4800)     ; // liaison série à   4800 bauds avec le gps 
 }


void loop()
{
     //    millis() donne le nombre de millisecondes écoulées depuis l'exécution du logiciel sur l'Arduino.
    //    Les fonctions gps.available() et gps.read() sont fournies par la bibliothèque Serial).
   
    int i = 0  ;
    int start = millis()  ;
    do
    {
       while ((Serial1.available())&&(i < tailleTrameRecuMax)) 
       {
         trameRecu[i++] = Serial1.read()  ;       // on remplit le tableau avec les trames recues pendant 500 mS
       }
    } 
    while(millis() - start < 500)  ;

    // On essaie de retrouver une trame CGA dans les trames recues
    indexTrameRecu = 0      ;
    boolean trouve = false  ;
    boolean typeTrameGPGGA = false  ;

    
    while(!trouve)
    {
     while((trameRecu[indexTrameRecu] != '$')&&(indexTrameRecu < tailleTrameRecuMax)) 
         {
            if(indexTrameRecu == tailleTrameRecuMax) break  ;    // on reccherche le début d'une trame commencant par $
            indexTrameRecu++;    
         }
      substring(trameRecu,prefixTrame,indexTrameRecu , 6)  ;// l'appel de cette fonction permet de stocker le prefix de la trame dans prefixTrame
      typeTrameGPGGA= cmpstr(prefixTrame,"$GPGGA");    // on compare le prefix avec GPGGA
      if(!typeTrameGPGGA)
        {
          int indexTrameGPGGA=0;
          while((trameRecu[indexTrameRecu] != 0x0D)&&(indexTrameRecu < tailleTrameRecuMax))
            {
              trameGPGGA[indexTrameGPGGA]=trameRecu[indexTrameRecu];  // si le prefix GPGGA est trouvé, on recopie la suite dans un tableau trame GPGGA jusqu'au retour chariot (0x0D)
              indexTrameRecu++;
              indexTrameGPGGA++;
            }
          trouve=true;
        }
       else
       {
        indexTrameRecu += 6 ;    // poursuivre la recherche en augmentant l'index de 6
       }
    }

for (int i= 0;i<80;i++)
  {
    Serial.print(trameGPGGA[i]);
  }

Serial.println("");  

char temp1,temp0;;
int lattitude =0;

  /*
// creation des sous chaînes lattitude, longitude...
substring2(trameGPGGA,latitudeDegres,offset_latitudeDegres);
substring2(trameGPGGA,latitudeMinutes,offset_latitudeMinutes);
substring2(trameGPGGA,latitudeDecimaux,offset_latitudeDecimaux);
substring2(trameGPGGA,latitudeDecimaux,offset_latitudeDecimaux);
substring2(trameGPGGA,latitudeOrientation,offset_lattitudeOrientation);
substring2(trameGPGGA,longitudeDegres,offset_longitudeDegres);
substring2(trameGPGGA,longitudeMinutes,offset_longitudeMinutes);
substring2(trameGPGGA,longitudeDecimaux,offset_longitudeDecimaux);
substring2(trameGPGGA,latitudeOrientation,offset_longitudeOrientation);
substring2(trameGPGGA,utc,offset_utc);
//substring2(trameGPGGA,altitude,offset_altitude);
Serial.print("   latitude : ") ;
Serial.print(latitudeDegres) ;
Serial.print("°") ;
Serial.print(latitudeMinutes) ;
Serial.print("   Minutes : ") ;
*/
delay(1000);

}



/*
Accepte en argument une chaine représentative d'un byte (entier non signé sur 8 bits))
codé par 2 chiffre hexadécimaux .
Retourne la valeur de cet entier.
Cette routine est utilisée pour numériser le checksum lu sur une trame NMEA.
On rappelle que les caractères '0' à '9' sont codés 0x30 à 0x39.
Les caractères 'A' ( 10 en hexa) à 'F' (15 en hexa) sont codés de 0x41 à 0x46 . 
*/


byte ascToByte(char *str)
{
    byte sum  ;

    sum = 0  ;
    if( *(str) < 0x3A)       sum += (*(str)- 0x30)<< 4   ; // poids fort multiplié par 16
    else                   sum += (*(str) -0x37)<< 4   ;
    
    if( *(str + 1) < 0x3A) sum += *(str+1)- 0x30     ;  // poids faible
    else                   sum += *(str+1) -0x37     ;
    return sum  ;
  }









/*substring()
Extrait de la chaine pointée par le premier argument, une sous chaine pointée par le
second argument.
Cette sous chaine est déterminée par son offset (3 ème argument) et sa longueur (4 ème argument).
*/


void substring(char *mainstr, char *substr, int origin, int len)
{
    int i , j   ;
    int fin     ;
    
    j = 0       ;
    fin = origin + len  ;
    for(i=origin; i < fin ; i++){
        *(substr + j) = *(mainstr + i)  ;
        j++             ;
    }
    *(substr + j)= 0    ;
  }
/*Effectue la comparaison de deux chaines .
Premier argument : pointeur sur la première chaine .
Deuxième argument : pointeur sur la deuxième chaine .
Un ou-exclusif est effectué sur tous les caractères des 2 chaines de même rang .
Si les deux chaines sont identiques cette routine retourne zéro. */

int cmpstr(char *str1, char *str2)
{
    int len1, i ;
    int sum  ;
    
    len1 = strlen(str1) ;
    if (len1 != strlen(str2))
      {
        sum = len1 ;  // chaines de longueur inégales
      }
   else
    {
       sum = 0  ;
       for(i=0; i< len1 ; i++)
       {
          sum += (*(str1+i) ^ *(str2+i))  ;
       }
    }
    return sum ;
  }
  
/*
Cette variante de substring() permet d'extraire des chaines de longueur variables.
La sous chaine est déterminée par tous les caractères de la chaine primitive à compter
du paramètre d'offset (3 ème argument) jusqu'à rencontre du caractère ',' .
Cette routine est utile pour extraire les champs d'une trame NMEA (séparés par des virgules ou des points) .
*/

  void substring2 (char *mainstr, char *substr,int offset )
  {
    int i , j   ;
    
    j = 0       ;
    i = offset  ;
    do{
        *(substr + j) = *(mainstr + i)  ;
        i++; j++                        ;
    } while(((*(mainstr + i) != ',')||(*(mainstr + i) != '.')))      ;
    *(substr + j)= 0                    ;
  }


Télécharger le fichier arduino.

Comptage de vibrations par interruption.

Nous allons ici compter des vibrations sur à l'aide d'un détecteur.

Image manquante ! La première méthode serait de surveiller constament la broche d'entrée du capteur pour détecter chaque vibration.Cela aurait comme inconvénient de monopoliser le processeur pour des évènements qui ne surviennent que de façon très espacés.

L'utilisation des interruptions est idéale lors d'actions ( clavier, bouton ...) ou changement d'état rapide ( signal infrarouge coupé, détecteur ...) sans pour cela "écouter" constamment la broche où va se produire le signal que l'on attend.

syntaxe et fonctionnement:

attachInterrupt( interruption utilisée, fonction appellée, mode de déclenchement)

- interruption utilisée : numéro de l'interruption utilisée. Pour l'Arduino UNO: 0 (INT0 => broche 2) et 1 (INT1 => broche 3)
- fonction appellée : fonction qui ne sera exécutée que si l'événement se produit sur la broche d'interruption choisie.
- mode de déclenchement : sur front montant => RISING / sur front descendant => FALLING / sur état bas => LOW / sur changement d'état => CHANGE.

Le montage: Image manquante !
Nous utilisons l'interruption 0, le détecteur est donc câblé sur la broche IO2.
Nous validerons le comptage des vibrations sur la broche 2 par la mise en service de l'alarme câblée sur la broche AD0.
Lorsque nous aurons 1000 vibrations de comptées, nous allumerons simplement une LEd dans cette exemple. Elle est câblée sur la broche 8.

Pour la simulation nous rajoutons un écran LCD pour visualiser le nombre d'impulsions compté.
Pour la simulation nous remplaçons le détecteur par un bouton poussoir.

ATTENTION !!! Modifier le câblage de l'écran, la broche RS ne doit pas être câblée sur IO2 car IO2 est déjà prise par l'interruption.


/* Main.ino file generated by New Project wizard
 *
 * Created:   Thu Sep 5 2013
 * Processor: ATmega328P
 * Compiler:  Arduino AVR
 
 */
#include  // inclusion de la librairie LCD
// déclaration des broches de l'afficheur
const int RS=9; // broche RS 
const int E=3; // broche E
const int D4=4; // broche D4    // variable de type constante
const int D5=5; // broche D5
const int D6=6; // broche D6
const int D7=7; // broche D7

LiquidCrystal lcd(RS,E,D4,D5,D6,D7); // déclaration d'un objet lcd

const int LED=8; // led broche 2
int compt =0; // variable comptant le nombre de vibrations
int etat_alarme=1; // variable indiquant l'état de l'alarme ( alarme=0 => activée / alarme=1 => désactivée )
const int alarme=A0; // interrupteur de mise en marche de l'alarme sur la broche AD0

void setup()
 {
 pinMode(LED,OUTPUT); // broche 8  en sortie
 pinMode(alarme,INPUT); //broche A0 en entrée
 // interruption INT0 ( broche 2 ) sur front montant du signal et qui appelle la fonction comptage //
attachInterrupt(0, comptage, RISING); 

 digitalWrite(LED,LOW); // led éteinte au démarrage
 lcd.begin(16,2); // initialise LCD 16 colonnes et 2  lignes
 lcd.clear(); // effacement de l'écran au démarrage
 }


 void loop()
 {
      lcd.clear(); // effacement de l'écran
      lcd.setCursor(0,0); // curseur en haut a gauche
      lcd.print(compt); // affichage du nombre de vibrations comptées
      delay(20); // délais pour la persistance rétinienne
       etat_alarme= digitalRead(alarme);  // lecture de la broche alarme pour savoir si elle est activée
	 if (compt>10000) // si le nombre de vibrations comptées est supérieur à 10000 .....
	 {
	 digitalWrite(LED,HIGH); // ....... on allume la led
	 }
 }



void comptage()   // fonction d'interruption
{
	 if (etat_alarme==0) // si l'alarme est activée ...
	 {
	      compt=compt+1; // .... on incrémente le compteur de vibrations à chaque vibration.
	 }
	 
	 if(etat_alarme==1) // si l'alarme est désactivée ....
	 {
	 compt=0; // ... on remet le compteur de vibrations à 0. 
	 }
}
 

Télécharger le projet Proteus.

Image manquante !