/*! \file cesi1.ino
\brief Premier TD pour le CESI.
\author Bertrand Vandeportaele IUT GEII
\date 28/10/2021
*/
#include <Arduino.h>
#include "sketch.h"
#include "lib_io_tp.h"
#include <stdio.h>
#include <unistd.h>
/** Variable globale indiquant la broche Arduino connectée à la LED */
const unsigned int LEDPIN=3;
/** Variable globale indiquant la broche Arduino connectée au bouton poussoir */
const unsigned int BUTTONPIN=2;
/** Variable globale permettant de stocker la dernière valeur écrite sur le
port de sortie, pour pouvoir en modifier uniquement certains bits */
unsigned char imageSortie=0;
//-------------------------------------------------------------------
/*! \fn void setup()
\brief Initialisation des périphériques et des variables globales
*/
CStateMachine maeUtile;
void setup() {
//-------------------------------------------------------------------
// CODE A COMPLETER PAR LES ETUDIANTS
//-------------------------------------------------------------------
Serial.begin(115200);
char nom[]="Labarthe et Mezino";
SetupES();
readPort();
setName(nom);
setMsg("Message sent");
}
//-------------------------------------------------------------------
/*!
* \fn void loop()
* \brief La fonction loop doit appeler une seule fonction exo... à la
* fois, vous devez conserver le code de tous les exercices mais n'en
* utiliser qu'un à la fois
*/
void loop() {
// unsigned int periodiciteTache1=10;
// static unsigned long timerTache1 = millis();
// if (millis() - timerTache1 >= periodiciteTache1) {
// timerTache1 += periodiciteTache1;
// writePort(readPort());
// }
unsigned int periodiciteTache2=1000;
static unsigned long timerTache2 = millis();
if (millis() - timerTache2 >= periodiciteTache2) {
timerTache2 += periodiciteTache2;
static unsigned int cpt=0;
cpt++;
char chaine[100];
sprintf(chaine,"etat=%u", maeUtile.getEtat());
printf("%s",chaine);
setMsg(chaine);
}
unsigned int periodicite=5;
static unsigned long timer = millis();
if (millis() - timer >= periodicite) {
timer += periodicite;
maeUtile.setEntree(readPort());
maeUtile.clock();
writePort(maeUtile.getSortie());}
}
//-------------------------------------------------------------------
/*!
* \fn void exo1()
* \brief Exercice 1:
* Vous devez piloter le port de sortie en recopiant l'état du port
* entrée et afficher sur la console série en héxadécimal la valeur lue
* sur le port d'entrée
* Utilisez les fonctions void SetupES(void); unsigned char readPort(void);
* et void writePort(unsigned char value); de lib_io_tp.h
* Configurez et utiliser l'interface de communication Série/USB
* https://www.arduino.cc/reference/en/language/functions/communication/serial
* https://www.arduino.cc/reference/en/language/functions/communication/serial/print/
* https://www.arduino.cc/reference/en/language/functions/communication/serial/println/
*/
void exo1(){
unsigned char val=readPort();
writePort(val);
if (val<=0xF)
Serial.print(0);
Serial.print(val, HEX);
Serial.println();
}
//-------------------------------------------------------------------
/*!
* \fn void exo2()
* \brief Exercice 2:
* Vous devez piloter le port de sortie en recopiant l'entrée 7 sur la
* sortie dont le numéro est défini par entree(2..0)
*/
void exo2(){
unsigned char val=readPort(); // un masque -> bits à 0 ou à 1... tBC
unsigned char e20= val & 0b111; //0x07
unsigned char e7 = (val >> 7) & 0x1; // ou alors e7 = (val & 0x80) >> 7;
// unsigned char tab[]={1,2,4,8,16,32,64,128};
// val=e7*tab[e20];
writePort(val);
}
//-------------------------------------------------------------------
/*!
* \fn void exo3()
* \brief Exercice 3:
* Vous devez piloter le port de sortie pour réaliser le transcodage de la
* valeur 4 bits lues sur entrée(3..0) vers les 7 bits du port de sortie
* (6..0) en utilisant le tableau tab fourni,
* puis ajouter le pilotage de la sortie 7 avec l'entrée 7
*/
void exo3(){
byte tab[]={0x3f,0x06,0x5b,0x4F,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
unsigned char val=readPort(); // un masque -> bits à 0 ou à 1... tBC
unsigned char e20= val & 0b1111; //0x07
unsigned char e7 = (val >> 7) & 0x1; // ou alors e7 = (val & 0x80) >> 7;
writePort(val);
}
//-------------------------------------------------------------------
/*!
* \fn void exo4()
* \brief Exercice 4:
* Vous devez configurer les entrées sorties numériques de l'arduino numéro
* BUTTONPIN et LEDPIN, puis effectuer la recopie de l'entrée BUTTONPIN sur la
* sortie LEDPIN en boucle.
* GPIO:
* https://www.arduino.cc/reference/en/language/functions/digital-io/pinmode/
* https://www.arduino.cc/reference/en/language/functions/digital-io/digitalread/
* Ecrire le numéro sur un bit:
* https://www.arduino.cc/reference/en/language/functions/digital-io/digitalwrite/
*/
void exo4(){
pinMode(BUTTONPIN, INPUT);
pinMode(LEDPIN, OUTPUT);
digitalWrite(LEDPIN, digitalRead(BUTTONPIN));
}
//-------------------------------------------------------------------
/*!
* \fn void exo5()
* \brief Exercice 5:
* Vous devez configurer l'entrée analogique A0 puis effectuer la commande du
* port de sortie pour qu'une seule LED s'allume à la position approximative du
* potentiomètre.
* https://www.arduino.cc/reference/en/language/functions/analog-io/analogread/
*/
void exo5(){
pinMode(A0, INPUT);
unsigned int iPotValue = analogRead(A0);
// (1<<7-(iPotValue>>7)); // Méthode du prof
for (unsigned int iIterator = 0; iIterator < 8; iIterator++)
{
if (((128 * iIterator) < iPotValue) & (iPotValue < (128 * (iIterator + 1))))
{
writePort(0x80 >> iIterator);
}
}
}
//-------------------------------------------------------------------
/*!
* \fn void exo6()
* \brief Exercice 6:
* Vous devez configurer l'entrée analogique A0 puis effectuer la commande de
* la LED connecté à la sortie LEDPIN afin qu'elle clignote à une fréquence
* pilotée par le potentiomètre. La commande de la durée des états hauts et bas
* de la sortie LEDPIN sera gérée à l'aide d'une fonction d'attente bloquante delay:
* https://www.arduino.cc/reference/en/language/functions/time/delay/
*/
void exo6(){
pinMode(A0, INPUT);
pinMode(LEDPIN, OUTPUT);
unsigned int iPotValue = analogRead(A0);
digitalWrite(LEDPIN, HIGH);
delay(iPotValue);
digitalWrite(LEDPIN, LOW);
delay(iPotValue);
}
//-------------------------------------------------------------------
/*!
* \fn void exo7()
* \brief Exercice 7:
* Vous devez configurer l'entrée analogique A0 puis effectuer la commande de
* la LED connecté à la sortie LEDPIN afin qu'elle clignote avec un rapport cyclique
* piloté par le potentiomètre. La commande de la durée des états hauts et bas de
* la sortie LEDPIN sera cette fois ci gérée à l'aide d'une sortie PWM (la broche
* LEDPIN est compatible PWM) à l'aide de la fonction analogWrite() :
* https://www.arduino.cc/reference/en/language/functions/analog-io/analogwrite/
*/
void exo7(){
//-------------------------------------------------------------------
// CODE A COMPLETER PAR LES ETUDIANTS
//-------------------------------------------------------------------
}
//-------------------------------------------------------------------
/*!
* \fn void exo8()
* \brief Exercice 8:
* Vous devez combiner les exercices 1 et 6 en utilisant une durée de 2 secondes
* pour les états hauts et bas du signal pilotant la sortie LEDPIN. Faire en sorte
* que la fonction génère une demi période du signal carré. Constatez si
* le port de sortie est mis à jour instantanément lorsque le port d'entrée est
* modifié.
*/
void exo8(){
unsigned char val=readPort();
writePort(val);
if (val<=0xF)
Serial.print(0);
Serial.print(val, HEX);
Serial.println();
}
//-------------------------------------------------------------------
/*!
* \fn void exo9()
* \brief Exercice 9:
* Vous devez modifier l'exercice 8 pour faire en sorte que la recopie du port
* d'entrée se fasse sur le port de sortie en permanence. Pour cela utiliser une
* fonction non bloquante pour gérer la temporisation à l'aide d'un timer par
* scrutation:
* https://www.arduino.cc/reference/en/language/functions/time/millis/
*/
void exo9(){
//-------------------------------------------------------------------
// CODE A COMPLETER PAR LES ETUDIANTS
//-------------------------------------------------------------------
}
//-------------------------------------------------------------------
/*!
* \fn void exo10()
* \brief Exercice 10:
* Découverte du pseudo parallélisme: Dans un premier temps exo10 appelle juste
* la fonction tache1() puis réalise une attente bloquante de 500ms.
*/
void exo10(){
//-------------------------------------------------------------------
// CODE A COMPLETER PAR LES ETUDIANTS
//-------------------------------------------------------------------
}
//-------------------------------------------------------------------
/*!
* \fn void tache1()
* \brief tache1:
* Découverte du pseudo parallélisme: la tache 1 consiste à réaliser un compteur
* sur 4 bits sur les bits (3..0) du port de sortie. La valeur maximale prise par
* ce compteur est réglé par les bits (3..0) du port d'entrée. "t1" doit être
* affiché dans la console série.
*/
void tache1(){
static unsigned char compteur=0;
imageSortie=((imageSortie&0xf0) | (compteur&0x0f));
//writePort (imageSortie);
unsigned char modulo=(readPort()&0x0f)+1;
compteur = (compteur+1)%6;
Serial.println("t1");
}
//-------------------------------------------------------------------
/*!
* \fn void exo11()
* \brief Exercice 11:
* Découverte du pseudo parallélisme: Dans un second temps exo11 appelle les
* fonctions tache1() et tache2() puis réalise une attente bloquante de 500ms.
*/
void exo11(){
//-------------------------------------------------------------------
// CODE A COMPLETER PAR LES ETUDIANTS
//-------------------------------------------------------------------
}
//-------------------------------------------------------------------
/*!
* \fn void tache2()
* \brief tache2:
* Découverte du pseudo parallélisme: la tache 2 consiste à réaliser un
* chenillard sur 4 bits sur les bits (7..4) du port de sortie. 4 séquences
* différentes sont définies dans les tableaux tab1 à 4 fournis. Le choix de
* la séquence utilisée est réalisé à l'aide des bits d'entrées (6..5). Si le
* bit d'entrée 4 est à 0 alors la séquence est mise en pause. "t2" doit être
* affiché dans la console série.
*/
void tache2(){
byte tab1[]={0x1,0x2,0x4,0x8,0x4,0x2};
byte tab2[]={0x1,0x3,0x7,0xf,0x7,0x3};
byte tab3[]={0x8,0xC,0xE,0xf,0xC,0x8};
byte tab4[]={0x8,0x1,0x4,0x2,0x1,0x4};
static unsigned char compteur=0;
byte val=tab1[compteur];
unsigned char entree=readPort();
unsigned char e56=(entree<<5)&3;
imageSortie=(imageSortie&0x0F) | ((val&&0x0f)<<4);
writePort (imageSortie);
if (((entree<<4)&1)==1)
compteur = (compteur+1)%6;
Serial.println("t2");
}
//-------------------------------------------------------------------
/*!
* \fn void exo12()
* \brief Exercice 12:
* Découverte du pseudo parallélisme: la tache1 doit être réalisée toutes les
* 500ms et la tache2 doit être réalisée toutes les Nms, N étant la valeur sur
* 10bits lue sur l'entrée analogique 0.
*/
void exo12(){
//-------------------------------------------------------------------
// CODE A COMPLETER PAR LES ETUDIANTS
//-------------------------------------------------------------------
}
//-------------------------------------------------------------------
/*!
* \fn void exo13()
* \brief Exercice 13:
* Gestion d'une interruption matérielle: ajouter à l'exo12 la commande de la
* commutation de la LED connectée à LEDPIN par l'appui sur le bouton poussoir
* connecté à BUTTONPIN. Pour cela vous utiliserez une interruption sur broche.
* La liste des vecteur d'interruption est visible en page 49 de
* https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf
* vous utiliserez external interrupt en page 53, BUTTONPIN doit être égal à 2
* car c'est uniquement cette broche qui peut déclencher cette interruption.
*/
void exo13(){
exo12();
}
//-------------------------------------------------------------------
// CODE A COMPLETER PAR LES ETUDIANTS
//-------------------------------------------------------------------
////////////////////////////////////////////////////////////////////
//Implémentation de la méthode reset, tout ce qui est fait pour (re)démarrer la machine à états
void CStateMachine::reset(){
etat=0;
sortie=0; //mettre des valeurs initiales correctes
}
////////////////////////////////////////////////////////////////////
//Implémentation de la méthode clock
void CStateMachine::clock(){
//variables intérmédiaires pour les entrées
unsigned char entree0=(entree>>0)&1;
unsigned char entree1=(entree>>1)&1;
unsigned char entree2=(entree>>2)&1;
unsigned char entree3=(entree>>3)&1;
//variables intérmédiaires pour les sorties
//codage des sorties
unsigned char sortie0;
unsigned char sortie1;
unsigned char sortie2;
unsigned char sortie3=1; // Rétracteur toujours actif
//Sortie convoyeur
if (etat==5 || etat==8 || etat==11)
sortie0=0;
else
sortie0=1;
// Sortie switch 1
if (etat==7)
sortie1=1;
else
sortie1=0;
// Sortie switch 2
if (etat==4)
sortie2=1;
else
sortie2=0;
//codage de l'évolution de l'état
switch (etat){
default:
case 0: if ((entree0==1) && (entree2==0))
etat=1;
else if (entree0==0)
etat=9;
break;
case 1: if ((entree0==1) && (entree1==0))
etat=2;
else if (entree0==0)
etat=6;
break;
case 2: if (entree0==0)
etat=3;
break;
case 3: if (entree3==1)
etat=4;
break;
case 4: if (entree3==0)
etat=5;
break;
case 5: if (entree3==1)
etat=0;
break;
case 6: if (entree3==1)
etat=7;
break;
case 7: if (entree3==0)
etat=8;
break;
case 8: if (entree3==1)
etat=0;
break;
case 9: if (entree3==1)
etat=10;
break;
case 10: if (entree3==0)
etat=11;
break;
case 11: if (entree3==1)
etat=0;
break;
}
//reconstruction de sortie à partir des variables intermédiaires
sortie=(sortie3<<3) | (sortie2<<2) | (sortie1<<1) | (sortie0<<0) ;
}
////////////////////////////////////////////////////////////////////