Clignotement millis intervalles différents

Salut !

Pourriez-vous me dire à partir de l'exemple Blink without delay, comment vous feriez pour que la durée d'allumage de la led soit différente de la durée d'extinction svp ? Je n'arrive pas à comprendre comment faire. Je me base sur ce code mais évidemment si je change l'intervalle il sera effectif autant pour le LOW que le HIGH. Merci de votre aide, j'ai beau chercher mais ça me dépasse un peu..

const int ledPin = LED_BUILTIN; 
int ledState = LOW; 

unsigned long previousMillis = 0;  

const long interval = 1000; 

void setup() {
   pinMode(ledPin, OUTPUT);
}

void loop() {
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {

    previousMillis = currentMillis;

    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    digitalWrite(ledPin, ledState);
  }
}

If you post on these English language fora, it is polite to use google translate so we all don't have to do that for ourselves.

You only have one interval. Introduce a second interval variable, call it macaroni, no call it intervalB, and rename interval to intervalA.

Now this statement needs to use intervalA or intervalB depending on the LED state.

if (currentMillis - previousMillis >= interval) {

You precede that statement an if/else statement to put either intervalA or intervalB into a new variable theInterval to use in the millis expression.

HTH

a7

Hi,

oh OK I will try to do that.

Sorry for the language, to me the forum is in french and the post is in the french category ^^

I may come back to you if I don't succeed :smile:

Thanks again.

Ne t'inquiéte pas. C'était dans une autre section il y a quelques minutes… ou alors je dormais encore.

a7

je changerais la valeur de la variable interval à chaque fois que je passerais dans le IF ou le ELSE.
J'en profiterais d'ailleurs pour enlever cette condition, pour passer sur une machine à état, si ton but est l'apprentissage :laughing:

à remplacer par

    if (ledState == LOW) {
      ledState = HIGH;
      interval = INTERVAL_HIGH;
    } else {
      ledState = LOW;
      interval = INTERVAL_LOW;
    }

ajouter au début

const long INTERVAL_LOW = 1800;
const long INTERVAL_HIGH = 200;
1 Like

Merci ! Ca marche pour une LED. Par contre j'ai peur de ne pas arriver à transposer l'idée dans mon projet. C'est ma dernière étape pour finaliser mais c'est aussi le plus compliqué. Car j'ai en fait 24 led à contrôler. J'utilise 3 IC 74HC595, jusque là pas de soucis. Quand l'appareil est en idle les leds suivent un pattern bien précis mais je ne sais pas le faire sans delay, et le problème c'est que lorsque des capteurs piezo sont activés le pattern change et des sons sont émis. Les codes fonctionnent séparément mais si je mets tout ensemble ça foire à cause des delay. J'espère déjà que je suis sur la bonne piste avec millis. Je ne sais pas si je peux mettre mon code ici, c'est un gros trucs avec plein de répétitions de débutant lol mais il faut que je reste simple. Je ne mets que la partie qui me bloque. C'est ma fonction ledIdle qui bloque le reste dès que je la mets dans la loop, car dans celle-ci j'ai aussi la lecture des piezo. Est-ce que tu crois que millis est la solution dans ce cas précis ?
Merci encore.


void ledIdle(){

ledJaune();

delay (350) ;

ledRouge();

delay (350) ;

ledBleue();

delay (350) ;

ledVerte();

delay (350) ;

}

///////////////////////////////

void ledJaune(){

digitalWrite(latchPin, LOW);

shiftOut(dataPin, clockPin, LSBFIRST, B01000100); // Vers SIPO 3

shiftOut(dataPin, clockPin, LSBFIRST, B00100000); // Vers SIPO 2

shiftOut(dataPin, clockPin, LSBFIRST, B10100010); // Vers SIPO 1

digitalWrite(latchPin, HIGH);

}

void ledRouge(){

digitalWrite(latchPin, LOW);

shiftOut(dataPin, clockPin, LSBFIRST, B00010010); // Vers SIPO 3

shiftOut(dataPin, clockPin, LSBFIRST, B10010111); // Vers SIPO 2

shiftOut(dataPin, clockPin, LSBFIRST, B00001000); // Vers SIPO 1

digitalWrite(latchPin, HIGH);

}

void ledBleue(){

digitalWrite(latchPin, LOW);

shiftOut(dataPin, clockPin, LSBFIRST, B00100000); // Vers SIPO 3

shiftOut(dataPin, clockPin, LSBFIRST, B00001000); // Vers SIPO 2

shiftOut(dataPin, clockPin, LSBFIRST, B00000100); // Vers SIPO 1

digitalWrite(latchPin, HIGH);

}

void ledVerte(){

digitalWrite(latchPin, LOW);

shiftOut(dataPin, clockPin, LSBFIRST, B10001001); // Vers SIPO 3

shiftOut(dataPin, clockPin, LSBFIRST, B01000000); // Vers SIPO 2

shiftOut(dataPin, clockPin, LSBFIRST, B01010001); // Vers SIPO 1

digitalWrite(latchPin, HIGH);

}

pour utiliser millis je conseille souvent de lire (en anglais)

dans le dernier lien vous verrez différents code. La version d'exemple que j'ai proposée contient une classe FlashingLed et on donne la durée ON et OFF et le N° de pin. Jetez y un oeil, ça pourrait vous simplifier la vie : une fois la classe définie, le code devient assez simple:

// on définit les LEDS
FlashingLed leds[] = {
  {2, 500, 500},   // pin 2, 500ms ON and 500 ms OFF
  {3, 1750, 350}   // pin 3, 1750ms ON and 350ms OFF
}; 

void setup() {
  for (auto &l : leds) l.begin();  // on les active
}

void loop() {
  for (auto &l : leds) l.flashWhenNeeded(); // à faire souvent pour faire le clignotement  quand c'est nécessaire
}

➜ dans wokwi sketch.ino - Wokwi ESP32, STM32, Arduino Simulator

1 Like

Je t'ai fait un wokwi assez moche, mais qui te montre le passage du delay() au millis()

1 Like

Waw merci ça marche nickel ! Du coup j'ai plus qu'à mettre mes shiftout à la place des HIGH/LOW et ça devrait le faire. J'ai déjà mis mes composants sur pcb, j'attends juste le quartz et je pourrais tester en conditions réelles. Je viendrais clôturer le sujet le cas échéant. Merci à tous :slight_smile:

Oui, mais non car cela va rester moche :frowning:
Je n'ai pas spécialement réfléchi à ton cas, mais il faudrait peut être s'inspirer de cette façon de faire.
En gros il faudrati factoriser le if (millis() - timer > tempo) et mieux le rentrer dans une machine à état

Bonjour dabigben

Ton montage final aura 24 LED, tu n'a jamais envisagé l'usage de LED adressables genre Neopixel, WS2812 etc., ça te simplifierai grandement le câblage et t'augmenterai les possibilités du point de vue des couleurs.

Cordialement
jpbbricole

Non je suis parti sur des 74hc595 mais en effet si je devais le refaire je me pencherais vers du rgb.

Honnêtement je crois que ça va bien fonctionner comme ça. C'est un prop à la con, un jouet quoi, et je t'avoue que la prog ça a été une sorte de...fussoir pour moi :smile: Du coup si en pratique ça fonctionne comme souhaité je vais en rester là.

Je comprends tout à fait, mais en tant que développeur, je me devais qu'en même de signaler que c'est moche :slight_smile:
Pour la remarque de @jpbbricole, ce n'est pas trop une question de RGB ou de couleur unique.
mais plus que les néopixels sont toutes en séries et donc tu pilotes tes 24 LEDs avec seulement 3 fils, alimentation comprise.

En fait j'aurais plutot dû partir sur des chip drivers de leds mais j'ai pas encore etudié ces trucs là. J'avais des SIPO sous la main donc chuis parti la dessus. Mais c'est ce que je testerais la prochaine fois en tous cas.

Bonjour dabigben

Je me suis amusé à l'exercice et ça donne ceci:

Uns structure contenant les temps et les pin des LED

struct ledTempoDef
{
	unsigned long tempoOn;     // Temps allumée
	unsigned long tempoOff;     // Temps éteinte
	const int pin;     // Pin de la LED
};

remplie ainsi

ledTempoDef ledTempo[] = 
{
	// tempoOn TempoOff  Pin
	{	350,	350,     8   },     // LED 0
	{	350,	350,     9   },     // LED 1
	{	350,	350,    10   },     // LED 2
	{	350,	350,    11   },     // LED 3
};

Pour ajouter ou supprimer des LED, il suffit d'ajouter une ligne dans ledTempo[]

La ligne
const int ledEtatOn = HIGH; // Quel état pour allumer la led
sert à définir quel état allume tes LED.

Tu peux, en tout temps, changer la pause d'une LED par un
ledTempo[4].tempoOff = 600;
pour mettre la pause de la LED 4 à 600 millisesecondes.

Le programme:

/*
    Name:       AF_dabigben_LedTempoDifférents.ino
    Created:	03.05.2024 08:39:27
    Author:     jpbbricole
	Remarque:	Faire clignoter des LED à des tempo différents
				https://forum.arduino.cc/t/clignotement-millis-intervalles-differents/1254945/6
*/
//------------------------------------- LED
//const int ledPin[] = {8, 9, 10, 11};     // Tableau des pin.
//const int ledNombre = sizeof(ledPin) / sizeof(ledPin[0]);     // Nombre de led
const int ledEtatOn = HIGH;     // Quel état pour allumer la led
int ledActive = 0;     // LED en cours de traitement

struct ledTempoDef
{
	unsigned long tempoOn;     // Temps allumée
	unsigned long tempoOff;     // Temps éteinte
	const int pin;     // Pin de la LED
};

ledTempoDef ledTempo[] = 
{
	// tempoOn TempoOff  Pin
	{	350,	350,     8   },     // LED 0
	{	350,	350,     9   },     // LED 1
	{	350,	350,    10   },     // LED 2
	{	350,	350,    11   },     // LED 3
};
const int ledNombre = sizeof(ledTempo) / sizeof(ledTempo[0]);     // Nombre de led

unsigned long ledClignTempo = 0;     // Temporisation de la led actuellement en action
unsigned long ledClignMillis = 0;     // Temporisation de la led actuellement en action, chrono

void setup()
{
	Serial.begin(115200);

	//--------------------------------- Initialisation des LED
	for (int l = 0; l < ledNombre; l ++)
	{
		pinMode(ledTempo[l].pin, OUTPUT);
		digitalWrite(ledTempo[l].pin, !ledEtatOn);     // Eteindre la LED
	}

	//--------------------------------- Amorçage du système
	ledActive = 0;
	ledCycleDebut(ledActive);
}

void loop()
{
	if (millis() - ledClignMillis >= ledClignTempo)     // Si periode du cycle terminée
	{
		if (digitalRead(ledTempo[ledActive].pin) == ledEtatOn)     // Si LED allumée
		{
			digitalWrite(ledTempo[ledActive].pin, !ledEtatOn);     // Eteindre la LED

			ledClignTempo = ledTempo[ledActive].tempoOff;     // Passage des temps de pause
			ledClignMillis = millis();     // Démarrage du chrono
		}
		else     // Si la led éteinte
		{
			digitalWrite(ledTempo[ledActive].pin, !ledEtatOn);     // Extinction de la LED
			Serial.println("Led " + String(ledActive) + " OFF");
			
			ledActive ++;     // LED suivante
			if (ledActive >= ledNombre)
			{
				ledActive = 0;
			}
			ledCycleDebut(ledActive);     // Redémarrage du cycle suivant
		}
	}
}

void ledCycleDebut(int ledNum)     // Démarrage d'une séquence de LED
{
	digitalWrite(ledTempo[ledNum].pin, ledEtatOn);     // Allumage de la LED
	ledClignTempo = ledTempo[ledNum].tempoOn;
	ledClignMillis = millis();     // Démarrage du chrono

	Serial.println("Led " + String(ledNum) + " ON");
}

A+
Cordialement
jpbbricole

Pourquoi ne pas avoir mis la pin dans la structure aussi ? Vous vous rapprochez de la POO :wink:

Bonsoir J-M-L

Oui, c'est vrai.
J'ai, des fois, des raisonnement un peu bizarres :woozy_face:

C'est quoi la POO?

Bonne soirée
jpbbricole

Programmation orientée objet

Cf