Francenanorecif

Bienvenue, Invité
Nom d'utilisateur : Mot de passe : Se souvenir de moi

SUJET : Arduino et LED, une vraie année de lumière

Arduino et LED, une vraie année de lumière 07 Mar 2012 12:55 #322523

  • billyboyk
  • Portrait de billyboyk
  • Hors Ligne
  • Chargé de Rédaction
  • Messages : 2258
  • Remerciements reçus 58
EDIT: Afin de faire les choses proprement je vais résumer ici tout ce qui se passe dans le sujet. L'idée de départ était de trouver un allumage moins linéraire qu'une simple rampe de progression et de fil en aiguille, on améliore les choses ;)

12 avril 2012: Passage en 10 bit pour la résolution du signal PWM:

Les PIN PWM sont gérer de la manière suivante sur l'Arduino Mega 2560:

Timer 0 pour les pins 4,13
Timer 1 pour les pins 11,12
Timer 2 pour les pins 9,10
Timer 3 pour les pins 2,3,5
Timer 4 pour les pins 6,7,8

Pour modifier un Timer en 10bit, il faut rajouter dans setup():

TCCRnA |= (1 << WGMn0);    
TCCRnA |= (1 << WGMn1);    
TCCRnB &= ~(1 << WGMn3);    
TCCRnB |=  (1 << WGMn2);

Où n est le numéro de timer


Je conseille de ne pas modifier le Timer 0 car ensuite tous les fonctions de temps vont être perturbées (millis(), delay()...)


5 avril 2012: Lissage de la courbe, la valeur PWM est modifiée toutes les secondes pour éviter les "sauts"

Le code, j'ai modifié les paramètres de chaques série de LED en les mettant dans un tableau de float, ça deveanit un peu trop le bazard:
//                                       PINLED, DUREE_TOTALE, DURE_RAMPE, MAX, ZENITH, MINUTEPREC, VALEURACTUELLE, VALEURSUIVANTE, PASVALEUR;
float Parametres_LED_Bleu_EST[]          = {2,       720,         120,     200,  930,       0,             0,             0,             0};

Puis modifié la fonction appellée maintenant toutes les secondes:
void DefinirValeurLED()
{    
     minutesDepuisMinuit = heures * 60 + minutes;

     Bleu_Est_Val = LisserRampeLED(minutesDepuisMinuit, Parametres_LED_Bleu_EST);     
  }

Et les deux fonctions pour le calcul:
float LisserRampeLED(float minuteActuelle, // Minutes actuelles depuis minuit
                     float p[])            // Paramètres pour la serie de LED actuelle
{
    //Calcul toutes les minutes des valeurs
    if (minutes!=p[MINUTEPREC])
    {  
        p[MINUTEPREC] = minutes;
        p[VALEURACTUELLE] = p[VALEURSUIVANTE];
        if(millis() < 2000){p[VALEURACTUELLE] = CalculValeurLED((minuteActuelle), p);}
        p[VALEURSUIVANTE] = CalculValeurLED((minuteActuelle + 1), p);
	p[PASVALEUR] = (p[VALEURSUIVANTE] - p[VALEURACTUELLE]);
    }
    
    if (p[PASVALEUR] > 1) //Calcul de valeurs intermédiaires
    {
         p[VALEURACTUELLE] = p[VALEURACTUELLE] + (p[PASVALEUR] / 60);
    }

    analogWrite(p[PINLED], p[VALEURACTUELLE]);
    return p[VALEURACTUELLE];
    
}
float CalculValeurLED(float minuteActuelle,       // Minutes actuelles depuis minuit
                      float p[])                  // Parametres de la serie de LED
{  
    float valeurLED = -1;
    
    dureeEntreMilieux = p[DUREE_TOTALE] - p[DUREE_RAMPE];
    
    
    if (minuteActuelle <= p[ZENITH])
    {
        valeurLED = p[MAX] / ( 1 + exp((-(13/p[DUREE_RAMPE]) * (minuteActuelle-(p[ZENITH] -(dureeEntreMilieux/2))))));
    }
    if (minuteActuelle > p[ZENITH])
    {
        valeurLED = p[MAX] / ( 1 + exp((-(13/p[DUREE_RAMPE]) * (p[ZENITH] + (dureeEntreMilieux/2) - minuteActuelle) )));
    }  
 
    return valeurLED;
}







10 mars 2012: La durée d'éclairement en fonction du jour de l'année

L'idée est d'adapter le temps d'éclairement en fonction du jour de l'année. Pour cela, on va jouer sur le paramètre "durée" de la fonction setLed. En été cela donnera 170 et en hiver, les jours sont plus courts, 130.

Le résultat:



La fonction:
float DureeDuJour(float TQuantieme)
{
  float valeur;

  valeur = 0.00000004 * pow(TQuantieme,4) - 0.0000284 * pow(TQuantieme,3) + 0.005 * pow(TQuantieme,2) + 0.0077 * TQuantieme + 131.69;
  return valeur;
}

09 mars 2012: La lune

On reprend la même fonction avec la valeur max de la lune correspond à la phase lunaire du jour. Pour éviter les soucis à minuit, on décale la base de tmeps de 12h pour la lune.

Le résultat, en pleine lune:



La fonction pour décaler le temps:
int GetMinutesDepuisMidi(int heuresActuelles, int minutesActuelles)
{
    int nbMinutes = 0;
    
    if(heuresActuelles > 11 && heuresActuelles < 24)
    {
        nbMinutes = heuresActuelles * 60 + minutesActuelles - 720;
    }
    else
    {
      
        nbMinutes = heuresActuelles * 60 + minutesActuelles + 720;
    }
    
    return nbMinutes;
}

La fonction pour déterminer la valeur max de la lune:
int valeurLuneMax(int jourActuel, int moisActuel, int anneeActuel)
{   
    int aa,mm;
    long K1,K2,K3,J,V;
    int valeurPWM;

    aa = anneeActuel -((12 - moisActuel) / 10);
    mm = moisActuel + 9;
    if (mm >= 12) mm -= 12;
    K1 = 365.25 * (aa + 4712);
    K2 = 30.6 * mm + .5;
    K3 = int(int((aa/100)+49)*.75)-38;
    
    J = K1 + K2 + jourActuel + 59 - K3;
    
   
    V = (J-2451550.1)/0.29530588853;
    
    V -= int(V/100)*100;
    V = abs(V-50);
    
    valeurPWM = 5.1*abs(50-V); 
    if (valeurPWM < 10) valeurPWM = 0; //Pour une "vraie" nouvelle lune

    return valeurPWM;  
}

L'appel de la fonction:
Lune_Val = setLed(Pin_LED_Lune, GetMinutesDepuisMidi(heures, minutes), LED_Lune_Duree, valeurLuneMax(jour, mois, annee), LED_Lune_Zenith);


08 mars 2012: La lumière du jour

J'ai choisi la solution proposée par Hugo qui utilise une fonction de Gauss qui réplique avec un mimétisme quasi parfait l'éclairement solaire sur une journée, encore merci! ;)

Le résultat:



Le code de la fonction:
float setLed(int pinLED,           // La pin de la serie de LED
             float minuteActuelle, // Minutes actuelles depuis minuit
             float duree,          // Quart du temps supérieur à 50%
             float valeurMAX,      // Valeur max
             float zenith)         // Temps en minutes pour le zenith
{  
    float valeurLED = 0;
    valeurLED = valeurMAX * exp( -(minuteActuelle - zenith) * (minuteActuelle - zenith) / (2 * duree * duree) );
    
    analogWrite(pinLED, valeurLED);    
    return valeurLED;
}


07 mars 2012:

Salut tout le monde!

Je voulais allumer et éteindre ma rampe de manière exponentielle et je ne trouve pas :(

Actuellement, niveau matériel, j'utilise un MEGA 2560 avec les drivers Meanwell (et l'interface entre deux qui va bien). Niveau soft, c'est comme ça:
ledVal = map(mins, startLED, startLED + fade, 0, ledMax);
 

ledval = Ma consigne PWM qui doit aller de 0 à ledMax (255 si à 100%)
mins = les minutes écoulées depuis minuit
startLED = le démarrage des LED en minutes depuis minuit (600 pour 10h00 par exemple)
fade = le temps en minutes de la rampe de démarrage
ledMax = la valeur Max des LED


Ca marche très bien mais je trouve que l'allumage est trop linéaire et je voulais utiliser plutot une courbe exponentielle.

Le seul soucis, c'est que je trouve pas :( Je pense à la fonction Pow() mais je ne vois pas comment l'utiliser.

Quelqu'un allume ses rampes "tranquillement"?
Dernière édition: 13 Avr 2012 10:04 par billyboyk.
L'administrateur a désactivé l'accès en écriture pour le public.

Re: Arduino -> PWM exponentiel, comment faire? 07 Mar 2012 12:59 #322524

  • Coroebus
  • Portrait de Coroebus
  • Hors Ligne
  • Membre
  • Messages : 5436
  • Remerciements reçus 91
tu peux jeter un œil là :
arduino.cc/en/Reference/Pow

sinon moi j'utilise des tableaux de valeurs
L'administrateur a désactivé l'accès en écriture pour le public.

Re: Arduino -> PWM exponentiel, comment faire? 07 Mar 2012 13:10 #322528

  • billyboyk
  • Portrait de billyboyk
  • Hors Ligne
  • Chargé de Rédaction
  • Messages : 2258
  • Remerciements reçus 58
Oui c'est en voyant cette page que j'ai pensé à cette fonction, mais je ne vois pas comment l'appliquer.

Pour les tableaux de valeurs, j'y avais pensé mais je préfère la focntion paramétrable. J'ai 4 lignes de LEDs sur ma rampe indépendantes, actuellement le soleil se lève d'un côté et se couche de l'autre côté en jouant sur les heures de démarrage et d'exctinction. Si je me lance dans les tablaux, il va me falloir 4 tableaux par rampe et si je veux ajuster, il faut que je change les 4 tableaux en entier si je veux conserver cette indépendance entre chaque série de LED. Et j'évite ainsi le saut entre 2 valeurs du tableau.

Aussi, je prévois bientôt l'ajout des conditions climatiques (passages de nuages, journées grans soleil ou légèrement nuageuses, durée des journées et heures de levé/couché de soleil selon la date...). Je suis la discution sur un autre forum de gens qui bossent là dessus et ils sont partis sur le même principe que moi (la base c'est le controller Typhon). Je voudrais éviter de complètement changer ma méthose actuelle ;)
Dernière édition: 07 Mar 2012 13:11 par billyboyk.
L'administrateur a désactivé l'accès en écriture pour le public.

Re: Arduino -> PWM exponentiel, comment faire? 07 Mar 2012 17:33 #322568

  • NotBad
  • Portrait de NotBad
  • Hors Ligne
  • Membre
  • Messages : 556
  • Remerciements reçus 1
Pourquoi n'utilises tu pas une formule mathématique qui aurait l'allure d'une parabole par exemple...?
L'administrateur a désactivé l'accès en écriture pour le public.

Re: Arduino -> PWM exponentiel, comment faire? 07 Mar 2012 18:09 #322575

  • hugonnep
  • Portrait de hugonnep
  • Hors Ligne
  • Membre
  • Messages : 53
  • Remerciements reçus 2
pour ma part j'utilise une fonction de Gauss, une hyperbole a un départ beaucoup plus rapide qu'une gaussienne
http://fr.wikipedia.org/wiki/Loi_normale

j'ai trouvé cela beaucoup plus simple qu'un tableau et plus de possibilité


la fonction est la suivante (pareil pour les blancs) :
//
calcul courbe de gauss, intensite du soleil led bleu
#include <math.h>

float fonctionLedBleu(float Minute, float W)
{
float valeur;

valeur = MaxIntensiteLedBleu * exp( -(Minute - 900) * (Minute - 900) / (2 * W * W) );
return valeur;
}

et dans le programme principale (loop) :

IntensiteBleu = fonctionLedBleu(MinuteArduino, Duree);

analogWrite(LedBleuPine, IntensiteBleu );

Quelques explications :
MinuteArduino : le temps arduino en minute 15 heures 58 minutes = 15 * 60 + 58
900 = l’apogée de la courbe en minute = 15 h
duree = moitie de la durée de l'éclairement à 50% de la hauteur (à un chouiat près) en minute devient W dans la fonction 180 = 3h soit 6h d'éclairement à mi hauteur

la courbe est entre 0 et 1 donc multiplier par MaxIntensiteLedBleu (constante = 255) pour obtenir entre une courbe entre 0 et un maximun

pour les leds blanches c'est pareils même paramétres sauf duree ou W égale à durée des bleus - 20 soit un décalage de 40 minutes au démarrage (je crois)

attention faut déclarer en float pour que la fonction exponentiel calcule correctement

avantage que je trouve est que comme tout est sous équation, est paramétrable, c'est simple (cas de la lune) de réaliser une fonction sinus de période 29 jours fonction du quantième (du jour) pour simuler les phase de la lune, voir une fonction qui varie la durée d'éclairement en fonction de la date pour simuler les saisons, simuler une durée d’éclairement différente entre le 1 janvier et le 21 juin (j'doit avoir 3h de différence)


dans ton cas : 4 équations pour les bleus, 4 équation pour les blancs, pour simuler les mouvement du soleil tu modifie l'apogée 10h 13h 16h 19h, tu peux varier l'intensité max sur les bords (moitié par rapport au centre) et au premier abord peut être varie la durée d'éclairement pour avoir un total qui ne soit pas excessif. à modéliser sur excel


A vous relire
Dernière édition: 07 Mar 2012 19:36 par hugonnep.
L'administrateur a désactivé l'accès en écriture pour le public.
Cet utilisateur a été remercié pour son message par: billyboyk

Re: Arduino -> PWM exponentiel, comment faire? 08 Mar 2012 10:49 #322675

  • billyboyk
  • Portrait de billyboyk
  • Hors Ligne
  • Chargé de Rédaction
  • Messages : 2258
  • Remerciements reçus 58
Notbad-> Oui c'est ce qu'il faudrait que je fasse avec le resultat de map ;)

hugo -> Trés intéressant! C'est ce que je chercher à faire mais dans mon cas, j'ai l'intensité qui "plate" toute la journée. Ton idée me plait car que pense que c'est encore plus naturel.

Je commence avec une serie bleue d'un coté, puis la bleue de l'autre coté, suivie de la premiere blanche et 2eme blanche.

Pour la phase lunaire je veux bien ta fonction sinusoidale, j'utilise actuellement une fonction trés(trop) compliquée et je saute de 25% en 25%.
L'administrateur a désactivé l'accès en écriture pour le public.

Re: Arduino -> PWM exponentiel, comment faire? 08 Mar 2012 11:45 #322682

  • billyboyk
  • Portrait de billyboyk
  • Hors Ligne
  • Chargé de Rédaction
  • Messages : 2258
  • Remerciements reçus 58
Hugo -> Merci! C'est nickel!: :whistle:



Je vais partir là dessus, encore plus simple que la fonction que j'utilise actuellement, paramétrable à souhait, bravo! B)

Par contre, tes coraux ne commencent pas à se fermer à partir du moment où l'on attaque la descente?

J'attend la lune avec impatience!
L'administrateur a désactivé l'accès en écriture pour le public.

Re: Arduino -> PWM exponentiel, comment faire? 08 Mar 2012 14:58 #322695

  • billyboyk
  • Portrait de billyboyk
  • Hors Ligne
  • Chargé de Rédaction
  • Messages : 2258
  • Remerciements reçus 58
Voilà, je l'ai intégré à mon code, plutôt que faire 4 fonctions, j'ai intégré la pin PWM dans une fonction principale:
float setLed(int pinLED,           // La pin de la serie de LED
             float minuteActuelle, // Minutes actuelles depuis minuit
             float duree,          // Quart du temps supérieur à 50%
             float valeurMAX,      // Valeur max
             float zenith)         // Temps en minutes pour le zenith
{  
    float valeurLED = 0;
    valeurLED = valeurMAX * exp( -(minuteActuelle - zenith) * (minuteActuelle - zenith) / (2 * duree * duree) );
    
    analogWrite(pinLED, valeurLED);    
    return valeurLED;
}

Ce qui est bien, c'est que pour faire les passages de nuages and co, je pourrai juste rajouter des coef dans ma fonction, encore bravo Hugo!
L'administrateur a désactivé l'accès en écriture pour le public.

Re: Arduino -> PWM exponentiel, comment faire? 08 Mar 2012 15:12 #322696

  • Coroebus
  • Portrait de Coroebus
  • Hors Ligne
  • Membre
  • Messages : 5436
  • Remerciements reçus 91
Bravo à tous les deux, je m'empresse de vous piquer le code :P
L'administrateur a désactivé l'accès en écriture pour le public.

Re: Arduino -> PWM exponentiel, comment faire? 08 Mar 2012 15:39 #322702

  • billyboyk
  • Portrait de billyboyk
  • Hors Ligne
  • Chargé de Rédaction
  • Messages : 2258
  • Remerciements reçus 58
Je vais finir la mise en place de mon nouvel automate et je met en route le démarrage doux des Meanwell P. J'ai déjà les Opto-coupleur pour "shunter le potar"
L'administrateur a désactivé l'accès en écriture pour le public.

Re: Arduino -> PWM exponentiel, comment faire? 08 Mar 2012 15:41 #322703

  • Coroebus
  • Portrait de Coroebus
  • Hors Ligne
  • Membre
  • Messages : 5436
  • Remerciements reçus 91
ça aussi ça m'intéresse :laugh:
L'administrateur a désactivé l'accès en écriture pour le public.

Re: Arduino -> PWM exponentiel, comment faire? 08 Mar 2012 15:53 #322708

  • billyboyk
  • Portrait de billyboyk
  • Hors Ligne
  • Chargé de Rédaction
  • Messages : 2258
  • Remerciements reçus 58
Ca va venir, faut juste attendre un peu que mon CAF remonte! :whistle:
L'administrateur a désactivé l'accès en écriture pour le public.
Modérateurs: unjall, tulottes
Temps de génération de la page : 0.305 secondes

Une bouteille à la mer

billyboyk - 17:19

20 kilos de PV avec du mou, ça tiendra 2 jours dans un bidon brassé/chauffé ;)

billyboyk - 08:22

:D Bonne année à tous !!! xD

habaqouq - 22:06

bonsoir comme insérer une image dans un post merci

delphizorglub - 18:08

Ouaou :p super

babe91800 - 12:18

Bonjour à tous :) petit come back après un moment d'absence

The shoutbox is unavailable to non-members