Comment utiliser le multitâche avec Arduino ? Projet lampe interractive

Bonjour à toutes et à tous,

Pour la réalisation de mon projet robotisé, je dois être en mesure d'élaborer un système automatique permettant de réaliser différentes tâches en parallèle.

Je dispose de différents éléments qui sont les suivant :

  • Une photorésistance pour mesurer la luminosité et déclencher des actions en fonction du niveau capté

  • Un servo moteur SG90 pour un angle de rotation à 180° relier à un engrenage "ouverture / fermeture"

  • Un anneau de LEDs (16 pilotables)

  • 6 fils de cuivre qui serviront de capteurs magnétiques permettant de changer les couleurs des LEDs en fonction du touché

D'après mes recherches il existe des librairies, fsm, etc. Mais je suis tombé sur ce tutoriel en FRANCAIS, très bien structuré. Alors je pense qu'il s'agit d'une bonne base et qui correspond surtout à mon besoin.

#include "Etape.h"
#include <Adafruit_NeoPixel.h>
#ifdef AVR
#include <avr/power.h>
#endif
#define PIN 6

Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, PIN, NEO_GRB + NEO_KHZ800);

//****************************************************************************************************

int photocellPin = 0; // the cell and 10K pulldown are connected to a0
int photocellReading; // the analog reading from the analog resistor divider

//****************************************************************************************************

const int NBMINUTERIE = 7; // Nb de minuteries à gérer (pour chacune des bases de temps)

volatile unsigned int minuterie1ms[NBMINUTERIE]; //Table des minuteries base de temps de 1 ms
volatile unsigned int minuterie100ms[NBMINUTERIE]; //Table des minuteries base de temps de 100 ms
byte compteur100ms = 100;

const int NBTACHE = 6; // Nb de tâches à réserver

volatile boolean etatTache[NBTACHE]; //Table de l'état d'activité des tâches
volatile byte Etape [NBTACHE]; //Table de l'étape active des tâches

typedef void (*action_t)(void); //définir un pointeur pour les tâches

//****************************************************************************************************
//****************************************************************************************************

/******** déclaration des tâches ********/

void Tache_init();
void Tache_T_1();
void Tache_T_2();
void Tache_T_3();
void Tache_T_4();
void Tache_T_5();

/******** N° des tâches **************/
const unsigned int _init = 0;
const unsigned int _T_1 = 1;
const unsigned int _T_2 = 2;
const unsigned int _T_3 = 3;
const unsigned int _T_4 = 4;
const unsigned int _T_5 = 5;
/*************************************/

/****************************************
Tableau de pointeurs sur les tâches
dans l'ordre des N° des tâches
*****************************************/

action_t Tache[] = {
Tache_init,
Tache_T_1,
Tache_T_2,
Tache_T_3,
Tache_T_4,
Tache_T_5
};

//****************************************************************************************************

void setup() {
/------------initialise toutes les minuteries à 0 -------------/

for (int i=0; i<NBMINUTERIE;i++) {
minuterie1ms = 0;
_ minuterie100ms = 0;_
* }*

* initTimer2(); // initialise TIMER2 comme Base de Temps*
_ /------------- initialise les tâches et les étapes initiales -----------------/_

* for (int i =0;i<NBTACHE;i++) { *
_ etatTache*=false;_
Etape= initX0;*
* }*_

* etatTache[init] = true; // active la tâche maître*
}
//**************************************************************************************************
void loop() {
//=========== balayage des tâches ==============
_

* for (int i =0;i<NBTACHE;i++) { *
if (etatTache_==true) Tache*();
}
}
//****************
//

// LES TÂCHES
//

/PHOTOSYNTHESE/_
void Tache_init(){

* switch (Etape[init]) {
case initX0 :*
* photocellReading = analogRead(photocellPin);*

* Serial.print("Il fait = ");*
* Serial.print(photocellReading); // the raw analog reading*
* //===== faire ici les actions transitoires =====*
* Etape[_init] = _X0; *

* case X0:*
* if (photocellReading < 10) {
Serial.println(" - Nuit");
}*_

* break;*
* case initX1 :*
* //===== faire ici les actions transitoires =====_
Etape[init] = X1;
case X1:*
* if (photocellReading < 200) {*

* Serial.println(" - Sombre");
}*_

* break;*
* case initX2:*
* //===== faire ici les actions transitoires =====_
Etape[_init] = _X2; *

* case X2:*
* break;
}*_

}
void Tache_T_1(){}
void Tache_T_2(){}
void Tache_T_3(){}
void Tache_T_4(){}
void Tache_T_5(){}
//****************************************************************************************************
/**********************************************************************
* initialiser le timer2 en mode CTC avec interruption*
**********************************************************************/
void initTimer2()
{
* noInterrupts(); // désactiver toutes les interruptions*
* TCCR2A = 0;*
* TCCR2B = 0;*
* TCNT2 = 0;*
* TCCR2A |= (1 << WGM21); // CTC mode*
* TCCR2B |= (1 << CS22); // 64 prescaler*
* //TCCR2B |= (1 << CS21); // 8 prescaler*
* OCR2A = 250; // 16MHz/64/1000Hz => Base de Temps = 1 ms*
* //OCR2A = 25; // 16MHz/64/10000Hz => Base de Temps = 100 µs*
* TIMSK2 |= (1 << OCIE2A); // Activer l'IT du mode comparaison*
* interrupts(); // valiser les interruptions*
}
/**********************************************************************
* BASE DE TEMPS 1 ms
**********************************************************************/
ISR(TIMER2_COMPA_vect) // fonction appelée sur interruption du TIMER2
*{ *
_ /******** décrémentation des minuteries Base de Temps = 1 ms ***/
for (byte i=0; i<NBMINUTERIE;i++) {

if (minuterie1ms != 0) {minuterie1ms --;}
}_

_ /******* décrémentation des minuteries Base de Temps = 100 ms /
if (compteur100ms != 0) {

compteur100ms--;

}

* else {
compteur100ms = 100;
for (byte i=0; i<NBMINUTERIE;i++) {
if (minuterie100ms != 0) {minuterie100ms --;}
}
}
}
[/quote]*

Comme vous pouvez le voir je commence à vouloir compléter la structure avec comme étape initiale la photosynthèse qui va devoir analyser l'obscurité / la luminosité ambiante pour activer le servo en fonction du jour et de la nuit.
Si il fait nuit noir, j'aimerais déclencher simultanément ma fonction d'ouverture du servo et ma fonction d'éclaire progressif des LEDs.
S'il fait sombre, une ouverture lente + lumière lente
S'il il fait jour, fermeture + extinction des lumières
Concernant les capteurs de cuivre 6 couleurs doivent être assignées, et l'état doit être continue (bouclé) lorsque celui ci est touché
Si deux sont toucher en même temps, on mélange les couleurs progressivement ...
J'aimerais trouver rapidement des solutions si vous avez déjà programmé ce type de projet n'hésitez à m'éclairer !
Aidez moi s'il vous plait_

Regardez l'exemple blink without delay

Bonjour, après beaucoup de patience je comprends mieu le principe d'une telle structure, cependant je ne parviens pas dès le départ à utiliser la photorésistance comme un déclencheur d'état (pour déclancher le servo moteur en fonction d'un seuil).

J'ai essayé au niveau de la tâche initiale CaptureLumiere de le faire mais malheureusement je ne trouve pas la solution ...

Retirer le break permet d’exécuter une seule fois l'analyse de la photorésistance, ce qui prolonge la boucle dans l'étape d'action qui lui correspond.

Je souhaite donc activer l'action servo s'il fait sombre. Et ça ne fonctionne pas

En théorie j'y crois, mais en pratique je dois vous avouer que j'ai besoin d'un coup main !

Merci

#include <Adafruit_NeoPixel.h>
#include <Servo.h>
#ifdef AVR
#include <avr/power.h>
#endif
#define PIN 6

Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, PIN, NEO_GRB + NEO_KHZ800);

//**********

/* PHOTOCELL*/
int photocellPin = 0; // the cell and 10K pulldown are connected to a0
int photocellReading; // the analog reading from the analog resistor divider

/* SERVO */
int servoPin = 9;
Servo servo;
int servoAngle = 0; // servo position in degrees

//************

const byte _AnalyseLuminositeTemp = 1;
const byte _Jour = 2;
const byte _Moyen = 3;
const byte _Nuit = 4;

//****************************************************************************************************
const int NBMINUTERIE = 6; // Nb de minuteries à gérer (pour chacune des bases de temps)

volatile unsigned int minuterie1ms[NBMINUTERIE]; //Table des minuteries base de temps de 1 ms
volatile unsigned int minuterie100ms[NBMINUTERIE]; //Table des minuteries base de temps de 100 ms
byte compteur100ms = 100;

/Declaration ordre minuterie/
const int TIMER_PHOTOCELL = 1; //N° de la minuterie utilisée pour la photoresistance

const int NBTACHE = 2; // Nb de tâches à réserver

volatile boolean etatTache[NBTACHE]; //Table de l'état d'activité des tâches
volatile byte Etape [NBTACHE]; //Table de l'étape active des tâches

typedef void (*action_t)(void); //définir un pointeur pour les tâches

//**************

/******** déclaration des tâches ********/

void Tache_CaptureLumiere();
void Tache_SUITE();
/*void Tache_T_2();
void Tache_T_3();
void Tache_T_4();
void Tache_T_5();

/******** N° des tâches **************/
const unsigned int _CaptureLumiere = 0;
const unsigned int _SUITE = 1;
/const unsigned int _T_2 = 2;
const unsigned int _T_3 = 3;
const unsigned int _T_4 = 4;
const unsigned int _T_5 = 5;
/
************************************/

/****************************************
Tableau de pointeurs sur les tâches
dans l'ordre des N° des tâches
*****************************************/

action_t Tache[] = {
Tache_CaptureLumiere,
Tache_SUITE,
/* Tache_T_2,
Tache_T_3,
Tache_T_4,
Tache_T_5 */
};

//**********************

void setup() {
/------------initialise toutes les minuteries à 0 -------------/

for (int i=0; i<NBMINUTERIE;i++) {
minuterie1ms = 0;
_ minuterie100ms = 0;_
* }*

* initTimer2(); // initialise TIMER2 comme Base de Temps*
_ /------------- initialise les tâches et les étapes initiales -----------------/_

* for (int i =0;i<NBTACHE;i++) { *
_ etatTache*=false;_
Etape= AnalyseLuminositeTemp;*
* }
Serial.begin(9600);_

etatTache[CaptureLumiere] = true; // active la tâche maître*
}_

//******************
void loop() {
* //=========== balayage des tâches ==============*

* for (int i =0;i<NBTACHE;i++) { *
if (etatTache_==true) Tache*();
}
}
//*

//
LES TÂCHES ***********

/PHOTOSYNTHESE/_
void Tache_CaptureLumiere(){

* switch (Etape[CaptureLumiere]) {
case AnalyseLuminositeTemp :*
* photocellReading = analogRead(photocellPin);*

* Serial.print("Lumens = ");*
* Serial.println(photocellReading); // the raw analog reading*
* if (photocellReading < 233) {*
* Serial.println("OBSCUR");*
// Etape[_CaptureLumiere] = _Nuit;

* } else if (photocellReading < 377) {*
* Serial.println("TRAITDUNION");*
// Etape[_CaptureLumiere] = _Moyen;

* } else {*
* Serial.println("CLAIR");*
* // Etape[CaptureLumiere] = Jour;*
* }*

* break;*
* //===== faire ici les actions transitoires =====*
* Etape[_CaptureLumiere] = _Jour; *

* case Jour:
// etatTache[Tache_SUITE] = false; SI CEST ACTIF IL Y A UNE ERREUR BOOLEAN QUE JE NE SAURAIS EXPLIQUER*

* Etape[CaptureLumiere] = AnalyseLuminositeTemp; *
* break;*

* case Moyen :
// etatTache[Tache_SUITE] = true;*

* //===== faire ici les actions transitoires =====*

* Serial.println("hey"); *
* Etape[CaptureLumiere] = AnalyseLuminositeTemp; *
* break;*

* case Nuit:
// etatTache[Tache_SUITE] = true;*

/*********************ICI JE SOUHAITE EFFECTUER MA FONCTION DOUVERTURE CERVEAU MAIS ELLE NE SE LANCE PAS /
for(servoAngle = 0; servoAngle < 1; servoAngle++) //move the micro servo from 0 degrees to 180 degrees
{
servo.write(servoAngle);
delay(2.5/10);
}

for(servoAngle = 1; servoAngle < 2; servoAngle++) //now move back the micro servo from 0 degrees to 180 degrees

{
servo.write(servoAngle);
delay(5.0/10);
}

for(servoAngle = 2; servoAngle < 3; servoAngle++) //now move back the micro servo from 0 degrees to 180 degrees

{
servo.write(servoAngle);
delay(7.5/10);
}

for(servoAngle = 3; servoAngle < 5; servoAngle++) //now move back the micro servo from 0 degrees to 180 degrees

{
servo.write(servoAngle);
delay(12.5/10);
}

for(servoAngle = 5; servoAngle < 8; servoAngle++) //now move back the micro servo from 0 degrees to 180 degrees

{
servo.write(servoAngle);
delay(20.0/10);

}

for(servoAngle = 8; servoAngle < 13; servoAngle++) //now move back the micro servo from 0 degrees to 180 degrees

{
servo.write(servoAngle);
delay(32.5/10);
}
for(servoAngle = 13; servoAngle < 21; servoAngle++) //now move back the micro servo from 0 degrees to 180 degrees

{
servo.write(servoAngle);
delay(52.5/10);
}
for(servoAngle = 21; servoAngle < 34; servoAngle++) //now move back the micro servo from 0 degrees to 180 degrees

{
servo.write(servoAngle);
delay(85.0/10);
}
for(servoAngle = 34; servoAngle < 55; servoAngle++) //now move back the micro servo from 0 degrees to 180 degrees

{
servo.write(servoAngle);
delay(137.5/10);
}
for(servoAngle = 55; servoAngle < 89; servoAngle++) //now move back the micro servo from 0 degrees to 180 degrees

{
servo.write(servoAngle);
delay(222.5/10);
}
for(servoAngle = 89; servoAngle < 144; servoAngle++) //now move back the micro servo from 0 degrees to 180 degrees
{
servo.write(servoAngle);
delay(360/10);
}_

Etape[_CaptureLumiere] = AnalyseLuminositeTemp; *
break;
}*_

}
void Tache_SUITE(){
* }*
void Tache_T_2(){}
void Tache_T_3(){}
void Tache_T_4(){}
void Tache_T_5(){}
//****************************************************************************************************
/**********************************************************************
* initialiser le timer2 en mode CTC avec interruption*
**********************************************************************/
void initTimer2()
{
* noInterrupts(); // désactiver toutes les interruptions*
* TCCR2A = 0;*
* TCCR2B = 0;*
* TCNT2 = 0;*
* TCCR2A |= (1 << WGM21); // CTC mode*
* TCCR2B |= (1 << CS22); // 64 prescaler*
* //TCCR2B |= (1 << CS21); // 8 prescaler*
* OCR2A = 250; // 16MHz/64/1000Hz => Base de Temps = 1 ms*
* //OCR2A = 25; // 16MHz/64/10000Hz => Base de Temps = 100 µs*
* TIMSK2 |= (1 << OCIE2A); // Activer l'IT du mode comparaison*
* interrupts(); // valiser les interruptions*
}
/**********************************************************************
* BASE DE TEMPS 1 ms
**********************************************************************/
ISR(TIMER2_COMPA_vect) // fonction appelée sur interruption du TIMER2
*{ *
_ /******** décrémentation des minuteries Base de Temps = 1 ms ***/
for (byte i=0; i<NBMINUTERIE;i++) {

if (minuterie1ms != 0) {minuterie1ms --;}
}_

_ /******* décrémentation des minuteries Base de Temps = 100 ms /
if (compteur100ms != 0) {

compteur100ms--;

}

* else {
compteur100ms = 100;
for (byte i=0; i<NBMINUTERIE;i++) {
if (minuterie100ms != 0) {minuterie100ms --;}
}
}
}
[/quote]*_