[Résolu] Fonction pour faire clignoter une LED

Bonjour,

Je débute en C et j'ai beaucoup de mal avec les fonctions, malgré la lecture de l'excellent Site du Zéro, je ne comprends pas commun faire une fonction pour faire clignoter une LED, et surtout je ne sais pas comment appeler cette fonction ensuite, je bloque bêtement.
Voici ma fonction :

void blinkLED()
  {
   digitalWrite (LED,HIGH);
   static unsigned long prevMillis = 0;
   unsigned long curMillis = millis();
   if(curMillis - prevMillis > 100) 
   {
      prevMillis = curMillis;   
      digitalWrite (LED,LOW);
   }

  }

Merci pour votre coup de pouce.

Au début du programme tu dois rajouter :

 #define LED 13

13 correspond à la sortie sur laquelle brancher le + de ta led.

Regarde sur cette page :

Tout en bas il y a un programme avec la structure minimum de base.

Yop Bribri,

Je vois un petit problème avec

static unsigned long prevMillis = 0;

cette variable sera local à ta fonction donc à chaque sortie de fonction ta variable disparait tout simplement, elle sera redéclaré au prochain appel mais dit toi bien que ce n'est plus la même ...
Ne pas oublié que loop doit être interprété comme une boucle infinie (la boucle est masquée, c'est trompeur mais elle existe bien après traitement de l'ide arduino avant compil, voir cores arduino) , le code situé à l’intérieure est bouclé constamment (remplace void loop() par while(1) pour mieux visualisé ce qui ce passe réellement).
Maintenant il faut également que tu conserves l'etat de ta sortie comme à chaque tour la fonction est appelée, il faut bine connaître l'etat actuel de ta diode pour savoir quel traitement effectuer.

//variable globale au programme, durée de vie longue ,tout au long du programme
static unsigned long prevMillis = 0;
uint8_t etatLed = 0;

void loop() //on entre dans loop -> code de la fonction //modifie loop par while(1) 
{
    blinkLED(); // ta fonction sera appelé constament à chaque tour
}                // -> sortie loop -> on recommence

  void blinkLED()
  {
   digitalWrite (LED,HIGH);
   
   unsigned long curMillis = millis(); // variable local à la fonction, durée de vie courte, le temps d’exécution de la fonction.
   if(curMillis - prevMillis > 100) 
   {
      prevMillis = curMillis;
      if(etatLed)
      {   
          digitalWrite (LED,LOW);
      }
      else
      {
          digitalWrite (LED,HIGH);
      }
   }

  }

Simplifié mais voici veritable visage du code arduino :

#include <Arduino.h>

int main(void)
{
	init();
	
	setup();
    
	for (;;) {
		loop();
	}
        
	return 0;
}

Merci pour ta réponse.

Ca, je l'avais fait.

La compilation de la fonction se passe très bien.

C'est après dans l'appel de la fonction où j'avais simplement écrit :

blinckLED() ;

Voici l'erreur de compilation

DS18B20_test_Mega_A8_LCD_ino.cpp: In function 'void loop()':
DS18B20_test_Mega_A8_LCD_ino:110: error: 'blinckLED' was not declared in this scope

Mais je pense que je me prends les pieds dans le tapis, car je considère les fonctions comme un sous-programme en assembleur.
Je n'arrive pas à comprendre la logique du truc, qui doit pourtant être simple.

Brisebee:
Merci pour ta réponse.

Ca, je l'avais fait.

Ah oki, parce que comme tu l'avais exposé ça ne pouvait pas marché. :grin:

Edit : post croisé, ça ne me concernait pas. :sweat_smile:

Brisebee:
La compilation de la fonction se passe très bien.

C'est après dans l'appel de la fonction où j'avais simplement écrit :

blinckLED() ;

Voici l'erreur de compilation

DS18B20_test_Mega_A8_LCD_ino.cpp: In function 'void loop()':
DS18B20_test_Mega_A8_LCD_ino:110: error: 'blinckLED' was not declared in this scope

Mais je pense que je me prends les pieds dans le tapis, car je considère les fonctions comme un sous-programme en assembleur.
Je n'arrive pas à comprendre la logique du truc, qui doit pourtant être simple.

Là je comprend pas bien l'erreur que tu donnes ne peux être que le résultat d'une fonction mal nommée à l'appel par exemple ou inexistante je vois rien d'autre, il faudrait voir plus du code pour voir où ça cafouille ?

Où est construite ta fonction ?

Brisebee:
Mais je pense que je me prends les pieds dans le tapis, car je considère les fonctions comme un sous-programme en assembleur.
Je n'arrive pas à comprendre la logique du truc, qui doit pourtant être simple.

Tu peux limite voir une fonction comme un sous programme ou utilitaire, elles sont surtout utile pour évité le code répétitif et similaire.

Merci pour toute vos réponses, c'est super.

Les choses vont très vite !

Mon post précedent s'adressait à kindermoumoute.

kindermoumoute:
Au début du programme tu dois rajouter :

 #define LED 13

13 correspond à la sortie sur laquelle brancher le + de ta led.

Brisebee:
Merci pour ta réponse.

Ca, je l'avais fait.
....

Jean-François:
Regarde sur cette page :

Faire clignoter une LED - Mon Club Elec

Tout en bas il y a un programme avec la structure minimum de base.

En fait je veux utiliser cette fonction dans un programme plus complexe dont je ne veux pas bloquer l'éxécution avec des delay.

Pour Osaka : je vais tester et te tiens au courant;

@+

N’empêche tu n'es pas le premier à avoir des difficultés avec les fonctions en venant de l'assembleur, c'est parait plus déroutant qu'en partant de zero à la limite. :~

Ce n'est pas pour le programme Blink avec delay que je te proposais cette page, mais simplement pour illustrer la structure:

-Déclaration
-Setup
-Loop
-Prototype

En nous montrant seulement une partie de ton code, il faut t'attendre à ne pas avoir les réponse que tu attends.

Jean-François:
En nous montrant seulement une partie de ton code, il faut t'attendre à ne pas avoir les réponse que tu attends.

OK, tu as parfaitement raison !

Pour Osaka :

Ton programme ne fonctionne pas, car etatLed reste toujours à 0

j'ai modifié ainsi (même si je suis sûr que ce n'est pas le plus propre qui soit):
dans les déclarations :

static unsigned long prevMillis = 0;
int etatLed = 0;

pour la fonction :

 void blinkLED()
  {
   digitalWrite (LED,HIGH);
   
   unsigned long curMillis = millis();
   if(curMillis - prevMillis > 100) 
   {
      prevMillis = curMillis;
      if(etatLed == 0)
      {   
          digitalWrite (LED,LOW);
          etatLed = 1;
      }
      else
      {
          digitalWrite (LED,HIGH);
          etatLed = 0;
      }
   }
  }

Et là ça marche !

Mais il faudra que tu m'explique :

uint8_t etatLed = 0;

est-ce un booléen comme (TRUE et FALSE) ?

Arf vi, ai oublier d'enregistrer l'etat ... :grin:

Sinon uint8_t voir avr-libc: <stdint.h>: Standard Integer Types
Il s'agit simplement d'une redéfinition d'un unsigned char, ses redéfinitions permettent d'être certain de choisir le bon type de variable selon la taille désirée, 8 bit dans ce cas ci en non signé.

uint8_t =
u pour unsigned
int pour entier
8_t pour taille 8

Dans le code effectivement on s'en servira comme un booleen, j'aurais pus directement mettre le type booleen, byte ou unsigned char ça revient au même ce sont tous des unsigned char.

int etatLed = 0;

Donc quand tu utilises un int pour ceci, tu utilises 2 octet là ou 1 seul suffit pour les deux valeurs possible (1 et 0).

Pour les booleen ici :

if(etatLed == 0)

tu peux mettre directement

if(etatLed) // si vrai (1, 15, 0.1, -15, -0.00005, 125689464)

if(!etatLed) // ! = différent de, donc ici c'est si faux (0)

! Dans une structure conditionnel en c/c++ toute valeurs différentes de 0 sont considéré comme vrai.
Donc : 1, 15, 0.1, -15, -0.00005, 125689464 sont vrai, seul 0 sera interprété comme faux.

OK merci Osaka, je comprends mieux.

Le C cache tellement de subtilités, qu'il y a des prises de tête en perspective.

J'aurai certainement encore plein de questions.

Je vais commander une caisse d'aspirine !!!

@+