/* SevSeg Counter Example
Copyright 2017 Dean Reading
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
This example demonstrates a very simple use of the SevSeg library with a 4
digit display. It displays a counter that counts up, showing deci-seconds.
*/
////////////////////////////////////////////////////////////////////
class CStateMachineRotary //déclaration de la classe
{
public: //membres accessibles depuis l'extérieur de la classe, il s'agit de l'interface d'interaction de la classe
CStateMachineRotary(int brocheAinit, int brocheBinit); //Constructeur avec paramètres pour régler les 2 broches Arduino utilisées
void clock(); //méthode pour cadencer la machine à état (faire 1 coup d'horloge)
int getPosition()//méthode accesseur pour accéder à l'attribut privé position
{ return position;} //on parle de méthode inlinée car l'implémentation est faite dans la déclaration de la classe
private: //membres privés pour réaliser l'encapsulation: ces attributs sont inacessibles directement depuis l'extérieur de la classe
byte etat; //numéro de l'état actif
byte entreeA; //valeur lue sur l'entrée A
byte entreeB; //valeur lue sur l'entrée B
int brocheA; //numéro de broche Arduino utilisée pour l'entrée A
int brocheB; //numéro de broche Arduino utilisée pour l'entrée B
virtual void frontDetecte(){}; //methode abstraite, sera implémentée dans la classe fille
virtual void actionSurTousLesEtats(){}; //methode abstraite, sera implémentée dans la classe fille
protected: //ces membres peuvent être accédés dans les classes filles
int position; //position angulaire mesurée
}; //ne pas oublier le ;
////////////////////////////////////////////////////////////////////
//Implémentation de la méthode constructeur
CStateMachineRotary::CStateMachineRotary(int brocheAinit, int brocheBinit){
// à compléter
//configurer et initialiser ce qui doit l'être
etat=0;
brocheA=brocheAinit;
brocheB=brocheBinit;
pinMode(brocheA, INPUT_PULLUP);
pinMode(brocheB, INPUT_PULLUP);
entreeA=digitalRead(brocheA);
entreeB=digitalRead(brocheB);
position=0;
}
//Implémentation de la méthode clock
void CStateMachineRotary::clock(){
// à compléter
//lecture et mémorisation des entrées
entreeA=digitalRead(brocheA);
entreeB=digitalRead(brocheB);
//actions sur transition
if ((etat==0) && (entreeA==1)){
position++;
frontDetecte();
}
if ((etat==1) && (entreeA==0)){
position--;
frontDetecte();
}
//évolution de l'état
switch (etat){
case 0: if (entreeA==1)
etat=1;
else if (entreeB==1)
etat=3;
break;
case 1: if (entreeB==1)
etat=2;
else if (entreeA==0)
etat=0;
break;
case 2: if (entreeA==0)
etat=3;
else if (entreeB==0)
etat=1;
break;
default:
case 3: if (entreeB==0)
etat=0;
else if (entreeA==1)
etat=2;
break;
}
//actions sur état
actionSurTousLesEtats();
//Serial.println(etat);
}
////////////////////////////////////////////////////////////////////
class CStateMachineRotaryWithSpeed: public CStateMachineRotary
{
public:
CStateMachineRotaryWithSpeed(int brocheAinit, int brocheBinit);
float getSpeed(); //méthode accesseur pour accéder à l'attribut privé speed
private:
void actionSurTousLesEtats(){};
float speed; //vitesse mesurée
unsigned long lastPulseTime; //horodatage du dernier front
void frontDetecte(); //implémentation pour effectuer des traitements lorsqu'un front est detecté
};
////////////////////////////////////////////////////////////////////
//Implémentation du constructeur de la classe fille, exécutée après avoir exécuté le constructeur de la classe mère
CStateMachineRotaryWithSpeed::CStateMachineRotaryWithSpeed(int brocheAinit, int brocheBinit): CStateMachineRotary(brocheAinit, brocheBinit){
lastPulseTime=micros(); //initialisation de la date initiale pour l'horodatage des fronts
speed=0; //initialise vitesse nulle au démarrage. Attention, en simu, l'encodeur génère des fronts parasites
}
////////////////////////////////////////////////////////////////////
//implémentation de la méthode frontDetecte() qui n'était pas implémentée dans la classe mère
void CStateMachineRotaryWithSpeed::frontDetecte()
{
// à compléter
unsigned long newPulseTime=micros();
speed=1000000./(newPulseTime-lastPulseTime);
lastPulseTime=newPulseTime;
}
//implémentation de la mesure de vitesse
float CStateMachineRotaryWithSpeed::getSpeed(){
//à faire: calculer la vitesse et l'affecter à l'attribut speed
unsigned long newPulseTime=micros();
if ((newPulseTime-lastPulseTime)>=2000000)
speed=0;
return speed;
}
////////////////////////////////////////////////////////////////////
class CStateMachineRotaryWithSpeedWithReset: public CStateMachineRotaryWithSpeed
{
public:
CStateMachineRotaryWithSpeedWithReset(int brocheAinit, int brocheBinit,int brocheCinit);
private:
void actionSurTousLesEtats();
int brocheC;
};
////////////////////////////////////////////////////////////////////
CStateMachineRotaryWithSpeedWithReset::CStateMachineRotaryWithSpeedWithReset(int brocheAinit, int brocheBinit,int brocheCinit) : CStateMachineRotaryWithSpeed( brocheAinit, brocheBinit)
{
brocheC=brocheCinit;
pinMode(brocheC, INPUT);
}
void CStateMachineRotaryWithSpeedWithReset::actionSurTousLesEtats(){
if (digitalRead(brocheC)==1)
position=0;
}
//Preambule :
/*
#include "SevSeg.h"
SevSeg sevseg; //Instantiate a seven segment controller object
#define POT A0
void setup() {
byte numDigits = 4;
byte digitPins[] = {2, 3, 4, 5};
byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12, 13};
bool resistorsOnSegments = false; // 'false' means resistors are on digit pins
byte hardwareConfig = COMMON_ANODE; // See README.md for options
bool updateWithDelays = false; // Default 'false' is Recommended
bool leadingZeros = false; // Use 'true' if you'd like to keep the leading zeros
bool disableDecPoint = false; // Use 'true' if your decimal point doesn't exist or isn't connected
sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments,
updateWithDelays, leadingZeros, disableDecPoint);
sevseg.setBrightness(90);
//Code pour piloter l'affichage avec la valeur 10bits lue sur l'entrée A0.
Serial.begin(115200);
Serial.println("debut");
}*/
// Loop de base
/* void loop() {
static unsigned long timer = millis();
static int deciSeconds = 0;
if (millis() - timer >= 100) {
timer += 100;
deciSeconds++; // 100 milliSeconds is equal to 1 deciSecond
if (deciSeconds == 10000) { // Reset to 0 after counting for 1000 seconds.
deciSeconds=0;
}
sevseg.setNumber(deciSeconds, 1);
}
sevseg.refreshDisplay(); // Must run repeatedly
} */
//Code pour piloter l'affichage avec la valeur 10bits lue sur l'entrée A0.
/* void loop() {
static int potValue = 0;
potValue = analogRead(POT);
sevseg.setNumber(potValue, 0);
sevseg.refreshDisplay(); // Must run repeatedly
} */
#include "lib7seg.h"
/* #define POT0 A0
#define POT1 A1
#define POT2 A2
#define POT3 A4 */
#define SWITCH A4
#define LED A5
static unsigned char cpt=-1; //balayage des digits
int datain[4];
static float getter=0;
CStateMachineRotaryWithSpeed encoder(A0,A1);
void setup() {
Serial.begin(115200);
Serial.println("debut");
/* pinMode(A3, OUTPUT);
digitalWrite(A3, LOW);
pinMode(POT0, INPUT);
pinMode(POT1, INPUT);
pinMode(POT2, INPUT);
pinMode(POT3, INPUT); */
pinMode(SWITCH, INPUT);
pinMode(LED, OUTPUT);
setup7seg();
setupTimer2();
setDots(1);
}
void loop() {
/*
digitalWrite(digitPins[2], LOW); // Active le digit des dizaines
digitalWrite(segmentPins[5], HIGH); // Allume le segment F
digitalWrite(segmentPins[7], HIGH); // Allume le point décimal
digitalWrite(digitPins[0], LOW); // Active le digit des milliers
digitalWrite(segmentPins[0], HIGH); // Allume le segment A
digitalWrite(segmentPins[4], HIGH); // Allume le segment E
*/
/*
setDigit(0,0x10);
setDigit(1,0x20);
setDigit(2,0x40);
setDigit(3,0x80);
*/
/* setDigit(0,1);
setDigit(1,2);
setDigit(2,3);
setDigit(3,4); */
encoder.clock();
unsigned int periodiciteTache1=200; // 200ms entre chaque incrémentation de la valeur à afficher
//unsigned int periodiciteTache2=2000; //2000ms pour l'affichage de chaque digit
static unsigned long timerTache1 = millis();
// static unsigned long timerTache2 = millis();
if (millis() - timerTache1 >= periodiciteTache1) {
timerTache1 += periodiciteTache1;
// tache1();
tache3();
}
/* if (millis() - timerTache2 >= periodiciteTache2) {
timerTache2 += periodiciteTache2;
tache2();
} */
//tache3();
/* Une première tâche réalise l'acquisition des mesures sur ces 4 entrées
en permanence dans une tache, chaque 100ms. Les valeurs lues devront
être stockées dans un tableau unsigned int datain[4]. */
}
//Timer 2 : https://www.aranacorp.com/fr/utilisation-des-timers-de-larduino/
// timer2 (8 bits) qui est utilisé par la fonction Tone() et la génération de la PWM sur les broches 3 et 11.
void setupTimer2(){
cli(); // disable all interrupts
TCCR2A = (1<<WGM21)|(0<<WGM20); // Mode CTC
TIMSK2 = (1<<OCIE2A); // Local interruption OCIE2A
TCCR2B = (0<<WGM22)|(1<<CS22)|(1<<CS21); // prediviser /256
OCR2A = 250; //250*256*1/16000000 = 4ms
sei(); // enable all interrupts
}
//appelée toutes les 4ms:
ISR(TIMER2_COMPA_vect){ // timer compare interrupt service routine
tache4();
//refresh();
}
/* Une première tâche réalise l'acquisition des mesures sur ces 4 entrées
en permanence dans une tache, chaque 100ms. Les valeurs lues devront
être stockées dans un tableau unsigned int datain[4]. */
/* void tache1() {
datain[0] = analogRead(POT0);
datain[1] = analogRead(POT1);
datain[2] = analogRead(POT2);
datain[3] = analogRead(POT3);
for (int i=0;i<4;i++){
Serial.print(datain[i]);
Serial.print(" ");
}
Serial.println();
} */
/* Dans une seconde tâche, exécutée chaque deux secondes,
le numéro de l'entrée dont la valeur est affichée sur
l'afficheur 7 segments sera changée, de sorte que l'on balaye les 4 entrées
en 8 secondes. Cette tache remplie le rôle de choix d'aiguillage.
Elle devra également indiquer sur l'afficheur quelle est la valeur
en cours d'affichage, cette tache devra régler la valeur de commande
des points décimaux (avec la fonction setDots(…)) pour
allumer le point décimal i lors de l'affichage de la valeur datain[i]. */
void tache2(){
cpt=(cpt+1)%4;
setDots(cpt);
}
void tache3(){
if (digitalRead(SWITCH)){
getter = encoder.getSpeed();
}
else{
getter = encoder.getPosition();
}
setFloat(getter);
//byte digitValue = digits[i] % 16;
//Serial.println(datain[cpt]); =
//setNumber(datain[cpt]);
}
void tache4(){
refresh();
}
////////////////////////////////////////////////////////////////////