/*! \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
*/
int ledPin = 3; // LED connected to digital pin 3
int inPin = 2; // pushbutton connected to digital pin 2
int analogPin = A0; // potentiometer wiper (middle terminal) connected to analog pin 3
void setup() {
//-------------------------------------------------------------------
// CODE A COMPLETER PAR LES ETUDIANTS
//-------------------------------------------------------------------
SetupES();
Serial.begin(115200);
/* pinMode(inPin, INPUT);
pinMode(ledPin, OUTPUT);
pinMode(analogPin, INPUT); */
char nom[]="Labarthe et Mezino";
//adresse ip de la boucle locale pour simulation
//char ip[]="127.0.0.1";
//adresse ip de la maquette arduino réelle sur le réseau iut gomette bleue
char ip[]="172.16.6.60";
char port[]="4242";
init_millis();
int r=setupES(strdup((std::string(ip).data())),strdup((std::string(port).data())));
if (r!=0){
printf("erreur ouverture socket, merci de lancer le simulateur ou d'allumer la carte téléopérée\n");
exit(-1);
}
setName(strdup((std::string(nom).data())));
printf("Elapsed time: %ld milliseconds\n", millis());
//programmeDeTest1();
//pinMode(LEDPIN, OUTPUT); // Initialisation de la broche en tant qu'entrée
}
//-------------------------------------------------------------------
/*!
* \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() {
//-------------------------------------------------------------------
// CODE A COMPLETER PAR LES ETUDIANTS
//-------------------------------------------------------------------
// 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());}
}
////////////////////////////////////////////////////////////////////
//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) ;
}
////////////////////////////////////////////////////////////////////
#include "Arduino.h"
#include <stdio.h>
#include <unistd.h>
struct timeval __millis_start;
void init_millis() {
gettimeofday(&__millis_start, NULL);
};
unsigned long int millis() {
long mtime, seconds, useconds;
struct timeval end;
gettimeofday(&end, NULL);
seconds = end.tv_sec - __millis_start.tv_sec;
useconds = end.tv_usec - __millis_start.tv_usec;
mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5;
return mtime;
};
/-------------------------------------------------------------------
/*!
* \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(){
//-------------------------------------------------------------------
// CODE A COMPLETER PAR LES ETUDIANTS
//-------------------------------------------------------------------
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(){
//-------------------------------------------------------------------
// CODE A COMPLETER PAR LES ETUDIANTS
//-------------------------------------------------------------------
unsigned char val = readPort();
unsigned char e20 = val & 0x7; //0b111
unsigned char e7 = (val & 0x80) >> 7;
// equivalent et moins rapide que : unsigned char e7 = (val >> 7 & 0x80);
// 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};
//-------------------------------------------------------------------
// CODE A COMPLETER PAR LES ETUDIANTS
//-------------------------------------------------------------------
unsigned char val = readPort();
unsigned char e30 = val & 0b1111; //0b111
unsigned char e7 = val >> 0x80 & 0x1;
val=tab[e30] | (e7<<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.
* 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(){
//-------------------------------------------------------------------
// CODE A COMPLETER PAR LES ETUDIANTS
//-------------------------------------------------------------------
unsigned char val = digitalRead(inPin);
digitalWrite(ledPin,val);
}
//-------------------------------------------------------------------
/*!
* \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(){
//-------------------------------------------------------------------
// CODE A COMPLETER PAR LES ETUDIANTS
//-------------------------------------------------------------------
unsigned int numero_led = 1;
unsigned int val = analogRead(analogPin); // read the input pin
val = val/128;
for (int i = 1; i <= val; i++) {
if (val == 0) {
numero_led = 1;
} else {
numero_led = numero_led * 2;
}
}
Serial.println(numero_led);
writePort(numero_led);
}
//-------------------------------------------------------------------
/*!
* \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(){
//-------------------------------------------------------------------
// CODE A COMPLETER PAR LES ETUDIANTS
//-------------------------------------------------------------------
unsigned int val = analogRead(analogPin);
digitalWrite(ledPin, HIGH);
delay(val);
digitalWrite(ledPin,LOW);
delay(val);
}
//-------------------------------------------------------------------
/*!
* \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(){
//-------------------------------------------------------------------
int iPotValue = analogRead(A0);
Serial.println(iPotValue);
analogWrite(LEDPIN, iPotValue>>2);
// analogWrite(LEDPIN, 0);
// delay(iPotValue);
// analogWrite(LEDPIN, 255);
// delay(iPotValue);
//-------------------------------------------------------------------
}
//-------------------------------------------------------------------
/*!
\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();
static uint8_t etat=0;
digitalWrite(LEDPIN,etat);
delay(2000);
etat = etat^1;
}
/*!
* \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
//-------------------------------------------------------------------
unsigned char val=readPort();
writePort(val);
if (val<=0xF)
Serial.print(0);
Serial.print(val,HEX);
Serial.println();
static unsigned long timer = millis();
unsigned int periodicite = 2000;
if (millis() - timer >= 2000)
{
timer = timer + periodicite;
static uint8_t etat=0;
digitalWrite(LEDPIN,etat);
// delay(2000);
etat = etat^1;
}
}
//-------------------------------------------------------------------
/*!
* \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
//-------------------------------------------------------------------
tache1();
delay(500);
}
//-------------------------------------------------------------------
/*!
* \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(){
//-------------------------------------------------------------------
// CODE A COMPLETER PAR LES ETUDIANTS
//-------------------------------------------------------------------
static unsigned char compteur = 0;
imageSortie=(imageSortie & 0xf0) | (compteur & 0x0F);
writePort(imageSortie);
unsigned char modulo = (readPort() & 0x0F) + 1;
compteur = (compteur + 1) % modulo;
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
//-------------------------------------------------------------------
tache1();
tache2();
delay(500);
}
//-------------------------------------------------------------------
/*!
* \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};
//-------------------------------------------------------------------
// CODE A COMPLETER PAR LES ETUDIANTS
//-------------------------------------------------------------------
byte * tabtab[4] = {tab1,tab2,tab3,tab4};
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
//-------------------------------------------------------------------