/*! \file cesi1.ino
\brief Premier TD pour le CESI.
\author Bertrand Vandeportaele IUT GEII
\date 28/10/2021
*/
#include "lib_io_tp.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
*/
void setup() {
//Début solution
Serial.begin(115200);
SetupES();
pinMode(LEDPIN, OUTPUT);
digitalWrite(LEDPIN, HIGH);
pinMode(BUTTONPIN, INPUT_PULLUP);
setupINT0(); //Configuration de l'interruption sur la broche 2
//Fin solution
}
//-------------------------------------------------------------------
/*!
* \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() {
//Début solution
exo12();
//Fin solution
}
//-------------------------------------------------------------------
/*!
* \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(){
//Début solution
unsigned char E=readPort();
writePort(E);
Serial.print(" ");
Serial.print(E,HEX);
Serial.println();
//Fin solution
}
//-------------------------------------------------------------------
/*!
* \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(){
//Début solution
unsigned char E=readPort();
unsigned char numSortie=E&0x7;
unsigned char valEntree7=(E>>7)&1;
unsigned char valSortie=valEntree7<<numSortie;
writePort(valSortie);
Serial.print(E,HEX);
Serial.print(" ");
Serial.print(valSortie,HEX);
Serial.println();
//Fin solution
}
//-------------------------------------------------------------------
/*!
* \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};
//Début solution
unsigned char E=readPort();
unsigned char valSortie=tab[E&0xf] | (E&0x80);
writePort(valSortie);
Serial.print(E,HEX);
Serial.print(" ");
Serial.print(valSortie,HEX);
Serial.println();
//Fin solution
}
//-------------------------------------------------------------------
/*!
* \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.
* https://www.arduino.cc/reference/en/language/functions/digital-io/pinmode/
* https://www.arduino.cc/reference/en/language/functions/digital-io/digitalread/
* https://www.arduino.cc/reference/en/language/functions/digital-io/digitalwrite/
*/
void exo4(){
//Début solution
unsigned char etat=digitalRead(BUTTONPIN);
digitalWrite(LEDPIN,etat);
Serial.print(etat,HEX);
Serial.println();
//Fin solution
}
//-------------------------------------------------------------------
/*!
* \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(){
//Début solution
unsigned int val=analogRead(A0);
Serial.print(val,DEC);
Serial.print(" ");
Serial.print(val>>7,DEC);
Serial.print(" ");
Serial.print(7-(val>>7),DEC);
Serial.print(" ");
unsigned char valSortie=1<<(7-(val>>7));
Serial.print(valSortie,HEX);
Serial.println();
writePort(valSortie);
//Fin solution
}
//-------------------------------------------------------------------
/*!
* \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(){
//Début solution
unsigned int val=analogRead(A0);
Serial.print(val,DEC);
Serial.println();
digitalWrite(LEDPIN,0);
delay(val/2);
digitalWrite(LEDPIN,1);
delay(val/2);
//Fin solution
}
//-------------------------------------------------------------------
/*!
* \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(){
//Début solution
unsigned int val=analogRead(A0);
Serial.print(val,DEC);
Serial.println();
analogWrite(LEDPIN,val/4); //durée à l'état haut entre 0 et 255, led allumée 100% du temps quand broche est à 0
//Fin solution
}
//-------------------------------------------------------------------
/*!
* \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. Constatez si le port de sortie est mis à jour instantanément lorsque le port d'entrée est modifié.
*/
void exo8(){
//Début solution
static char etat=0;
unsigned char E=readPort();
writePort(E);
digitalWrite(LEDPIN,etat);
etat=(etat+1)%2;
delay(2000); //attente bloquante -> le port de sortie est bloqué pendant ce temps
//Fin solution
}
//-------------------------------------------------------------------
/*!
* \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 scutation:
* https://www.arduino.cc/reference/en/language/functions/time/millis/
*/
void exo9(){
//Début solution
static char etat=0;
unsigned char E=readPort();
writePort(E);
unsigned int periodicite=2000;
static unsigned long timer = millis();
if (millis() - timer >= periodicite) {
timer += periodicite;
digitalWrite(LEDPIN,etat);
etat=(etat+1)%2;
}
//Fin solution
}
//-------------------------------------------------------------------
/*!
* \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(){
//Début solution
tache1();
delay(500);
//Fin solution
}
//-------------------------------------------------------------------
/*!
* \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(){
//Début solution
static unsigned char compteur=0;
imageSortie=(imageSortie&0xf0) | (compteur&0xf);
writePort(imageSortie);
unsigned char moduloCompteur=(readPort()&0x0f)+1;
compteur=(compteur+1)%moduloCompteur;
Serial.println("t1");
//Fin solution
}
//-------------------------------------------------------------------
/*!
* \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(){
//Début solution
tache1();
tache2();
delay(500);
//Fin solution
}
//-------------------------------------------------------------------
/*!
* \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};
//Début solution
static unsigned char compteur=0;
unsigned char E=readPort();
//choix du tableau avec pointeur byte * tab=tab1 ou tab2
byte * tab;
//if (((E>>5)&1)==1) tab=tab2; else tab=tab1;
switch((E>>5)&3){
case 0: tab=tab1; break;
case 1: tab=tab2; break;
case 2: tab=tab3; break;
case 3: tab=tab4; break;
}
imageSortie=(imageSortie&0x0f) | ((tab[compteur]&0xf)<<4);
writePort(imageSortie);
if (((readPort()>>4)&1)==1)
compteur=(compteur+1)%6;
Serial.println("t2");
//Fin solution
}
//-------------------------------------------------------------------
/*!
* \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(){
//Début solution
unsigned int periodiciteTache1=500;
unsigned int periodiciteTache2=analogRead(A0);
static unsigned long timerTache1 = millis();
static unsigned long timerTache2 = millis();
if (millis() - timerTache1 >= periodiciteTache1) {
timerTache1 += periodiciteTache1;
tache1();
}
if (millis() - timerTache2 >= periodiciteTache2) {
timerTache2 += periodiciteTache2;
tache2();
}
//Fin solution
}
//-------------------------------------------------------------------
/*!
* \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();
}
//Début solution
void setupINT0(){
pinMode(LEDPIN, OUTPUT);
digitalWrite(LEDPIN,HIGH);
pinMode(BUTTONPIN, INPUT_PULLUP);
cli(); // disable all interrupts
EICRA= (EICRA&0xFC) |2; //ICS0 = 10 pour front descendant
EIMSK= EIMSK|1; //enable INT0
sei(); // enable all interrupts
}
//-------------------------------------------------------------------
//PROBLEME IL Y A LES REBONDS SUR LE POUSSOIR.... anti rebond par logiciel en inhibant les interruptions après la première pendant un certain temps
ISR(INT0_vect) {
unsigned int minTempsEntreIT0=300;
static unsigned long timerIT0 = millis();
static unsigned char counter=0;
unsigned long timeActuel=millis();
if ( timeActuel - timerIT0 >= minTempsEntreIT0) {
timerIT0=timeActuel;
if (counter==0)
digitalWrite(LEDPIN,LOW); //allume
else
digitalWrite(LEDPIN,HIGH); //eteind
counter = (counter+1)%2;
Serial.println("it");
}
}
////autre exo à envisager: désactivation dans l'it puis réactivation dans loop via timer partagé
//-------------------------------------------------------------------
//temporisation avec interruption timer -> sera vu au tp suivant sur afficheur 7 segments
//-------------------------------------------------------------------
//Fin solution