LOCODUINO

Parlons Arduino => Vos projets => Discussion démarrée par: petitrain le février 01, 2015, 11:15:17 pm

Titre: Un Arduino par module....ou pas.
Posté par: petitrain le février 01, 2015, 11:15:17 pm
  Après avoir tester plein de petits programmes ( clignotements, chenillards, feux de signalisation, la PWM ou les servos...) depuis un bon bout de temps, j'ai envie de m'attaquer à un projet plus ambitieux.
  Je suis l'heureux possesseur de quatre modules de voie unique au norme de la FFMF, une petite gare de passage et deux modules de décor. Ils ne demandent qu'à faire des petits. La gestion des trains est en DCC et me va très bien, surtout dans les expos.
  J'aimerai confié à l'Arduino la gestion de tout le reste: l'éclairage des modules ( rubans de leds RVB et Halogène 220V), l'éclairage des bâtiments et des parties publiques, les aiguillages, le PN, un ouvrier qui soude, etc., et des petits modules de son.
  J'aimerai avoir aussi un afficheur LCD et une horloge HO sur 4 digits.
  J'ai imaginé pour cela un arduino sous chaque module avec deux ULN2803 comme interface de puissance . Pour les rubans de leds 500mA pas de problème, pour les ampoules halogène je passe en 220v sinon l'ampérage est trop important en 12v. Il faut que je teste une commande par triac( pas encore fait). Pour le son j'ai trouvé des petits lecteurs MP3 que je compte booster avec des ampli stéréo 2*3w.
  Je compte utiliser une alimentation d'ordinateur , sortie 12v et 5v avec pas mal d'Ampère., commune à tous les modules.
  Cette disposition me permet d'avoir les I/O suffisantes, pas trop de fils entre chaque module, mais il faut que je puisse réaliser une liaison entre tous mes arduino. En effet il va me falloir un arduino maître pour commander les différences séquences d'éclairage ( plein feu, éteint, à moitié pour travailler  dessus et diverses animations).
  Après toute cette réflexion....le doute s'installe.... est-ce que c'est le mieux....
  Aussi j'ai fait un petit dessin récapitulatif et j'aimerai que vous me disiez ce que vous en pensez....   
Titre: Re : Un Arduino par module....ou pas.
Posté par: Guillaume le février 02, 2015, 08:09:16 am
Pourquoi pas je dirais. C'est une réflexion que j'ai eu à un moment, mais je suis passé à un autre projet plus petit en taille (surface au sol du HO, du HOe c'est plus petit en appartement)

Il y a d'autres questions que tu dois te poser qui vont probablement changer ton schéma. Quelles sont tes entrées  ? Je n'en vois pas sur ton schéma.
Un arduino par module est bien vu que cela permet de laisser le moins de fils entre les modules mais il faut synchroniser tout cela, quel protocole ?

Conduite à vue ou automatique ? un tableau de retour de l'occupation des rails.

Ce que tu peux faire, c'est commencer simplement sur un module pour tester déjà comment cela se passe.
J'ai vu aussi un PN dans le lot c'est déjà bien comme petit truc : détection, fermeture des barrières, lumières clignotants et son.

Je sais que ce ne sont pas des réponses mais cela peut t'aiguiller.
Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le février 02, 2015, 09:12:45 am
Bonjour petitrain

Joli projet, il y a beaucoup de choses.

Quelques questions:

1) quelle serait la longueur de fil maximum totale pour la communication entre les Arduino ?
2) est-ce que tous les Arduino emettent des informations ou bien y a-t-il un seul émetteur et plusieurs récepteurs.
3) est-ce que c'est gênant que la communication se fasse mal ponctuellement ?

Concernant l'horloge HO avec un afficheur à DEL, il existe des afficheurs de petite taille conçus pour l'heure avec le ´:´ de séparation : http://www.tme.eu/fr/details/lfd028aue-103a/afficheurs-led-quadruples/#  A l'échelle ça donne une horloge avec des chiffres de 60cm de haut. Ça consomme 13 fils, un Arduino y passe.

Concernant les ULN2803, chaque sortie supporte effectivement 500mA mais si les 8 sorties sont en route, ça fait 4A. La datasheet n'est pas très claire à ce sujet mais, vers la fin, elle parle de 2,5A. Donc je ne suis pas sûr que l'ULN puisse tenir dans ces conditions. A tester, un ULN ne coûte pas si cher. Si il s'agit de commander l'éclairage par bande de DEL, l'alternative est de ne pas les alimenter indépendamment mais en une fois avec un MOSFET de puissance. Pour mon réseau, j'ai un MOSFET pour 5m de DEL 5050 ton chaud et un MOSFET pour 5m de DEL 5050 blanc. De mémoire j'ai 7,5A par ruban.
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le février 02, 2015, 09:19:19 am
 Il y a d'autres questions que tu dois te poser qui vont probablement changer ton schéma. Quelles sont tes entrées  ? Je n'en vois pas sur ton schéma

Au niveau des entrées, j'en aurai sur les modules de la gare, surement, pour commander mes aiguilles . Actuellement je les commande avec des moteurs conrad avec des fins de course, je pense mettre un petit relai 2RT pour inverser la polarité du courant ou, si ça ne va pas, des servos comme l'explique jean luc sur son site. Donc une entrée par aiguille. Je n'ai pas précisé: sur mon dessin, les ULN2803 laissent libre les broches RX et TX, les broches A4 et A5 (i2c), et les broches A0,A1,A2 et A3 sont basculables en entrées ou sorties par des straps.
Sur le module maitre, il me faut un bouton pour incrementer une liste de programme et un bouton de validation.

J'ai vu aussi un PN dans le lot c'est déjà bien comme petit truc : détection, fermeture des barrières, lumières clignotants et son

Je pense juste mettre un bouton qui ferme ou ouvre les barrières car, sinon, la détection se retrouve sur les modules voisins et c'est encore des fils suplémentaires.

Un arduino par module est bien vu que cela permet de laisser le moins de fils entre les modules mais il faut synchroniser tout cela, quel protocole ?

Pour la synchro (pas testée), j'ai imaginé créer des créneaux sur une sortie du maitre et les envoyer sur une entrée des esclaves via un bus.
J'aurai dans le programme maitre :
 une variable incrementée par le bouton
--->un switch(ma variable)
case(1)--->digitalWrite(sortie x, HIGH) pendant, disons 50ms
case(2)--->(digitalWrite(sortie x, HIGH) pendant, disons 50ms)2 fois
etc...
Dans chaque esclave:
une variable s'incrémentant sur l'entrée du bus
--->un switch(ma variable)
case(1)--->programme 1
case(2)--->programme 2
etc...
Tout ça a tester.
Reste le grave problème de delay() à régler.
A ce propos, est-ce que c'est la seule fonction bloquante?               


 
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le février 02, 2015, 09:43:09 am
Merci pour vos réponses rapides,
Bonjour petitrain

Joli projet, il y a beaucoup de choses.

Quelques questions:

1) quelle serait la longueur de fil maximum totale pour la communication entre les Arduino ?
2) est-ce que tous les Arduino emettent des informations ou bien y a-t-il un seul émetteur et plusieurs récepteurs.
3) est-ce que c'est gênant que la communication se fasse mal ponctuellement ?

Concernant l'horloge HO avec un afficheur à DEL, il existe des afficheurs de petite taille conçus pour l'heure avec le ´:´ de séparation : http://www.tme.eu/fr/details/lfd028aue-103a/afficheurs-led-quadruples/#  A l'échelle ça donne une horloge avec des chiffres de 60cm de haut. Ça consomme 13 fils, un Arduino y passe.

Concernant les ULN2803, chaque sortie supporte effectivement 500mA mais si les 8 sorties sont en route, ça fait 4A. La datasheet n'est pas très claire à ce sujet mais, vers la fin, elle parle de 2,5A. Donc je ne suis pas sûr que l'ULN puisse tenir dans ces conditions. A tester, un ULN ne coûte pas si cher. Si il s'agit de commander l'éclairage par bande de DEL, l'alternative est de ne pas les alimenter indépendamment mais en une fois avec un MOSFET de puissance. Pour mon réseau, j'ai un MOSFET pour 5m de DEL 5050 ton chaud et un MOSFET pour 5m de DEL 5050 blanc. De mémoire j'ai 7,5A par ruban.
Concernant la communication des arduino j'ai un peu expliqué mon idée à Guillaume:
mes modules mesurent 1m de long, pour l'instant j'en ai quatre de fini, mais sur ma pré-maquette, j'en ai prévu 13, je ne sais pas si j'irai jusque là...
si la communication se fait mal, il suffit de refaire la consigne, j'imagine....
Pour ma petite horloge, qui est déjà fonctionnelle, j'ai implantée sur un CI un ATméga328,un quartz et 2 condos avec 4 afficheurs 7 segments que j'avais en stock. Je peux mettre à disposition mon étude si ça intéresse quelqu'un.
Tes réflexions sur les limites des ULN2803 posent effectivement des questions et méritent des tests... à voir....
J'aime bien l'idée de commander l'éclairage  sur chaque module car cela permet des animations plus variées 
Titre: Re : Un Arduino par module....ou pas.
Posté par: Guillaume le février 02, 2015, 09:54:04 am
Delay() n'est pas vraiment un souci ca se contourne assez facilement. Sais-tu comment faire clignoter une DEL avec millis(). Si non triche et regarde les programmes d'exemples.
La seule fonction : à ma connaissance oui mais elle est petite la mienne. Et encore on a les interruptions ;), mais effectivement mieux vaut s'en passer.

La détection pas obligée de fils supplémentaires, tout dépend comment tu veux ton protocole typiquement la voie série est à oublier un arduino envoie à plusieurs, si on fait avec la voie série le premier arduino va devoir trier ce qui est à lui ou non et renvoyer le message si non (arduinos en cercle dirons nous)
Après tu as l'i2c , peut être bien si les arduinos esclaves n'ont pas d'infos à faire remonter comme pour le PN par exemple et aussi tout dépend de la longueur des fils comme demande le Jean Luc.
Sinon le bus CAN qui rassemble fiabilité sur la longueur et chaque arduino envoie à tout le monde. Bon résumé Jean Luc me tapera dessus sinon.
edit : vu la longueur le bus can parait mieux si j'ai retenu la leçon

Par contre sur ton exemple de programme, c'est encore moins compliqué. Un truc simple peut être de diviser ta partie cerveau sur un arduino (avec entrées, TCO et tout) et des arduinos actionneurs.
Par exemple, pour l'éclairage tu appuis sur ton appui pour allumer l'arduino va envoyer sur le bus le message allumer sur tel module, l'arduino recoit et effectue toutes les manoeuvres que tu as décidé, lampadaire en route en faisant des ratés etc etc...

Le plus dur c'est de faire l'architecture et décider comment faire d'où les questions de Jean Luc, le code  viendra tout seul après.
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le février 02, 2015, 09:55:04 am
Pour Guillaume,

 J'avais, moi aussi, un réseau en Hoe, que j'ai vendu à un musée de Nice, et je garde toujours la nostalgie de cette échelle.
Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le février 02, 2015, 11:48:35 am
Si tu envisages d'aller jusqu'à 13 modules, il ne faut pas que la solution de communication choisie te limite. Même si tu ne sais pas si tu iras jusque-là. Nous avons tous nos rêves et il faut se donner les moyens de les réaliser ;)

Donc potentiellement tu auras 14 nœuds sur ton réseaux: le maître + 13 modules et un bus que s'étend sur une vingtaine de mètres. Les interfaces de communication natives de l'Arduino (I2C, SPI, série) ne sont pas du tout faites pour une telle distance si on veut un débit suffisamment élevé et une bonne sûreté de fonctionnement. De plus, elles n'implémentent que de la communication très bas niveau.  Le lien série n'est pas un bus comme le signale Guillaume et est donc hors jeu.

Donc en bus fiable, prévu pour être déployé sur une grande distance, rapide, avec détection d'erreur et des contrôleurs peu chers qui gèrent la totalité du protocole, il y a le CAN. Problème, les shields CAN sont fort chers (pour une raison qui m'échappe) et les clôneurs chinois ne se sont pas attaqués au créneau. Du coup nous avons conçu un module CAN dont le prix de revient (en kit avec PCB professionnel) est d'environ 6€50. La communication avec l'Arduino se fait par le bus SPI. La bibliothèque est tout simplement celle du shield CAN de seeedstudio. Nous avons fait fabriquer 10 ex du PCB pour 11 livrés chez Electrodragon. Dominique en a 6, Thierry 2 et moi 3. Je sais qu'Hubert est candidat pour quelques exemplaires donc une seconde commande pourrait être faite. Donc si tu veux essayer, c'est faisable. Comme c'est le bus que j'utilise sur mon réseau et que dans les projets LOCODUINO nous somme partis sur ce bus, il y aura prochainement des articles consacrés au CAN avec des exemples de mise en oeuvre.

Concernant l'éclairage public et des bâtiments, une alternative est le TLC5940 de Texas. Ce circuit permet de piloter 16 DEL en courant (donc sans résistance) chacune avec une PWM 12 bits. Il est assez cher en Europe mais bon marché sur eBay Chine. Il y a une bibliothèque pour le piloter. Ces circuits peuvent être chainés pour piloter plus de DEL sans consommer plus de fils sur l'Arduino. J'en ai quelques uns en stock et j'ai testé, ça fonctionne très bien.

Pour l'horloge de gare, nous sommes preneurs d'un article décrivant le système  :)
Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le février 02, 2015, 01:36:31 pm
Autre chose : sur ton schéma, tu diffuses du 5V à partir d'une alim centrale à tous les Arduino. Ce 5V va être bruité car tu vas avoir des longs fils. Ça risque de provoquer des reset intempestifs des Arduino. Il vaut mieux diffuser une tension plus élevée et utiliser une régulation en tension sur l'Arduino.
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le février 02, 2015, 04:59:17 pm
Pour l'horloge de gare, vous voulez un article structuré pour mettre sur le site ou simplement voir ce que j'ai fait?
Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le février 02, 2015, 05:01:39 pm
Je penche pour un article structuré :)
Titre: Re : Un Arduino par module....ou pas.
Posté par: Hubert le février 02, 2015, 06:42:46 pm
Je pense que tu dois t'orienter sur les Bus CAN pour faire dialoguer tes arduinos entre eux.
il te faut du fil assez gros pour transporter du 5v sur de longues distances et pour éviter l'effet antenne et et de résonnance il te faut du fil blindé.
Une deuxième option et je suis dessus mais pas vraiment avancé dans le projet.
 
La transmission par Wifi:
j'ai les 4 composants WIFI et il me manque une de mes cartes qui à pris un coup. je ne teste que pour 4 cartes mais si cela fonctionne pour 4, avec le wifi nous ne sommes pas limité sauf en adressage mais bon, nos réseaux sont de tailles réduits.
Explication succinte du déroulement du process.
le maître envoi l'ordre de communication avec le byte de reconnaissance spécifique à l'ensemble des cartes en écoute,
l'exclave concerné par le byte de reconnaisance se met en mode reception et traitement jusqu'au byte de fin de transmission;
Les autres cartes qui ont interceptées libèrent la fréquence quand il savent que l'ordre ne les concernent pas en restant à l'écoute d'un nouvel ordre.
A partir de ce moment et jusqu'à l'ordre de fin de transmission, la carte exclave communique avec le maître pour valider les données et peut executer les instructions en même temps.
Avec ce système tu peux avoir un byte de reconnaissance commun à tous les exclaves pour synchroniser ou executer le même ordre.
 Pas de problème de cablage ni de bruits parasitaires.
En fonction de l'ordre reçu, la carte receptrice peut effectuer la tache identifiée par son code, retransmet au maître le code  et l'acquiescement de l'éxécution dudit ordre.
exemple;
allumer la gare de passage sur le secteur 2,
tu envois le byte 1 pour lancer la communication suivi de "carteS2" pour identifier la carte du secteur2.
toutes les cartes recoivent le byte 1 mais seule la carte du secteur 2 sera concerné
tant que la carte ne réponds pas relance de l'ordre selon un timing à définir et selon un max de tentatives (carte HS).
la carte secteur2 répond : pret à recevoir les ordres en envoyant "carteS2" puis un byte à 1.
les autres cartes ne repondent pas et attentent en écoutant l'entrée wifi le byte de fin de transmission en cours .
envoi par le maitre de la commande suivante "carteS2" puis 10 (pour allumer la gare) puis le byte à 255 pour fin d'ordre
execution de l'ordre par la carte et retour de la bonne execution pour contrôle au maître.
"CarteS2" puis 10 puis 1 puis 255 pour fin de trame.
éventuellement contrôle de vérification du bon ordre et libération de la transmission par un ordre de fin
Voilà, quelque chose de ce genre.
 
 
Titre: Re : Un Arduino par module....ou pas.
Posté par: Guillaume le février 02, 2015, 06:48:57 pm
Autant en faire profiter tout le monde ;)
Je serai assez intéressé.

Pour ce qui est du code, pas de souci pour aider pour ma part. Fais par étapes et cela découlera facilement.
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le février 02, 2015, 08:08:49 pm
Merci pour l'intérêt que vous portez à mon projet.
  Il me faut réfléchir à vos diverses propositions pour la communication entre arduino ;je me doutais que c'était le point délicat .
  J'avais pensé aussi à une liaison par commande DCC. Ma centrale (une ROCO) devient le maitre et tous mes arduino esclaves: avantage pas de fils supplémentaires et j'économise une platine Arduino. Je n'ai pas vraiment beaucoup d'instruction à passer ( juste un n° de programme).
Pour une séance de jeu, je vais peut-être changé de programme 2 ou 3 fois.
j'appelle une adresse avec ma centrale---> et mes Arduino jouent un programme: simple
.... en théorie.....
car j'ai lu pas mal d'articles et je n'ai pas compris grand chose ( en plus, mon anglais est des plus rudimentaire).
J'ai jeté un oeil au datasheet de l'ULN2803, effectivement la puissance totale est assez faible. Je vais mettre des  Mosfets pour commander les rubans de leds.
Le 5v sur chaque module, c'est pour commander mes petits lecteurs MP3 pas pour les Arduino, je les alimente en 12v via la broche Vin;
  Enfin pour l'article sur mon horloge, donnez moi un peu de temps. Si vous voulez la mettre sur le blog, relisez-moi avant pour apporter les corrections que vous jugerez bonnes. Ou dois-je le poster?
Titre: Re : Un Arduino par module....ou pas.
Posté par: Guillaume le février 02, 2015, 08:28:09 pm
Ben tout dépend de comment tu voudrais faire. Il faudra réfléchir avant de se lancer.

Sinon si DCC cela veut dire que tu transforme ton arduino en décodeur mais tu n'es pas obligé de connaître tous les numéros, nicolas a fait un joli article avec le xpress.

Par programme changé 2-3 fois, tu penses plutot à lancer ou pas l'animation ?
Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le février 02, 2015, 08:59:07 pm
Pas de pb avec le sans fil :) tu y vas un peu fort Hubert. J'aurais plutôt dit l'inverse : le filaire est plus fiable.

La solution des modules sans fil à base de nrf24 est séduisantes. Mais c'est aussi un domaine où tous les emmerdements restent à decouvrir :). Le CAN a le mérite d'être largement déployé industriellement. 
Titre: Re : Re : Un Arduino par module....ou pas.
Posté par: Hubert le février 03, 2015, 12:11:29 am
Pas de pb avec le sans fil :) tu y vas un peu fort Hubert. J'aurais plutôt dit l'inverse : le filaire est plus fiable.

La solution des modules sans fil à base de nrf24 est séduisantes. Mais c'est aussi un domaine où tous les emmerdements restent à decouvrir :). Le CAN a le mérite d'être largement déployé industriellement.

j'aime le risque et nous sommes entrés dans l'aire du sans fil.  :P

Le but du jeu est aussi de découvrir pour le bien de notre hobby.
les deux valent le coup d'être testé.

Filaire VS Wifi

on fait et on compare après ( prix , facilité de mise en œuvre, fiabilité, ...) qu'en penses-tu.

j'ai fais ma commande chez Minilnthebox.com (première commande) et j'attends les pièces ( plus quelques fournitures et des nouvelles cartes Arduino).


Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le février 03, 2015, 05:13:17 am
Mmmmmh

J'ai des nrf24 sur les cartes de mes radiateurs. Parce que je ne me voyais pas passer des fils dans toute la maison pour les piloter. Sur le réseau c'est différent c'est déjà plein de fils partout et c'est pas un rj11 de plus qui va changer la donne. Par contre pour les poste de conduite je pensais effectivement utiliser des nrf24. Mais je n'en prévois que trois.

Je n'ai pas fait des tests de performance avec les nrf24 mais pourquoi pas, pas seulement le débit mais egalement la latence et sa dispersion. Je me doute déjà du vainqueur ;) pareil pour la fiabilité. Quoiqu'il en soit mes cartes servo, traction et TCO utilisent déjà du CAN, une cinquantaine de nœuds en tout.

Le sans fil oui mais là où il est utile  :)
Titre: Filaire VS Wifi
Posté par: Hubert le février 03, 2015, 11:25:35 am
Mmmmmh

J'ai des nrf24 sur les cartes de mes radiateurs. Parce que je ne me voyais pas passer des fils dans toute la maison pour les piloter. Sur le réseau c'est différent c'est déjà plein de fils partout et c'est pas un rj11 de plus qui va changer la donne. Par contre pour les poste de conduite je pensais effectivement utiliser des nrf24. Mais je n'en prévois que trois.

Je n'ai pas fait des tests de performance avec les nrf24 mais pourquoi pas, pas seulement le débit mais egalement la latence et sa dispersion. Je me doute déjà du vainqueur ;) pareil pour la fiabilité. Quoiqu'il en soit mes cartes servo, traction et TCO utilisent déjà du CAN, une cinquantaine de nœuds en tout.

Le sans fil oui mais là où il est utile  :)

Je suis d'accord avec toi pour le sans fil la ou il faut  :D  et le fait de tirer des cables un peu partout, chez moi, dans la maison familial, j'ai mis du CPL (Courant Porteur en Ligne) sur deux étages et pas mal de M², pas mal de domotique et de transport de données notamment pour l'internet et la télé et la sécurité. ;)
Je pense même si le vainqueur  :P peut déjà sabler le champagne, que ma méthode est une alternative et qu'elle mérite d'être proposée.
Dans le cas d'un branchement filaire en série ou les cartes communiquent entre elles comme le propose Petittrain, l'utilisation du wifi est gagnant sur le fait qu'il s'adresse à toutes les cartes en même temps et ou celles concernées répondent uniquement. Si dans le mode filaire série, une carte est HS, tout le dispositif en amont tombe à moins de prévoir un anneau de secour et redondant. Dans le mode Wifi, uniquement celle en défaut est touchée.

Toutes les personnes ne sont pas non plus des spécialistes en cablage et électronique. un module tout fait (CAN ou WIFI) peut répondre au besoin et aux contraintes engendrées.

De notre côté, si nous pouvons proposer des solutions faciles en mettre en oeuvre en évitant de tirer des cables source d'anomalie, je te rappelle que la plupart des incidents et anomalies détectées sont à 80%, selon le principe de Pareto, d'origine filaire (oxydation, arrachement, faux contact, mauvaise soudure, échauffement, rayonnement électrique, ...).Ne pas oublié, dans ce cas, La loi de Murphy qui s'invite aussi à la fête et que l'on nomme aussi LEM (loi de l'emmerdement maximum) et sont des lois empiriques tirées de l'expérience, notre expérience.
(http://tigroo92.ouvaton.org/local/cache-vignettes/L150xH150/Couverture_-_Pourquoi_la_tartine_tombe_toujours_du_cote_du_beurre-3616d.jpg) (http://tigroo92.ouvaton.org/IMG/jpg/Couverture_-_Pourquoi_la_tartine_tombe_toujours_du_cote_du_beurre.jpg)
Chaque solution à son lot de points positifs et négatifs, chacun choissira la solution qu'il considère la mieux pour lui mais ne pas en parler ni l'évoquer ne peut que le dissuader de progresser voir le rebuter de s'y mettre et pour finir le bloquer.
Pour moi, je recherche différentes solutions à proposer, par la suite laissons le choix à celui qui devra faire.

Anecdote:
Au travail, je vois ce que mes techniciens réseaux infra souffrent pour maintenir les liaisons dans les locaux techniques et nos clients qui ralent sur les connexions filaires. Notre réponse, sur le fait que nous ne pouvons pas mettre du wifi partout et qu'au niveau sécurité,c 'est plus difficile à gerer que le réseau filaire blindé ne semble plus les satisfaire comme  auparavent, les gens changent et leur perception du monde électronique aussi. Ils sont plus demandeur qu'avant et la fatalité n'est plus une excuse pour eux "Avoir un fil à la patte n'est pas signe de liberté".

Tu es pro-filaire et je suis pro-wifi, deux opposés qui se complêtent pour former un ensemble cohérent. :D :D
 
Il est possible aussi que je me plante sur ce coup là, hé bien, j'apprendrai de mes erreurs et me releverai plus fort.

 
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le février 03, 2015, 01:45:38 pm
Juste une aparté pour vous parler  du fournisseur MiniInthebox.
J'ai pas mal commandé chez eux, les prix sont attractifs et beaucoup de référence.
Par contre, à chaque fois, le transporteur me présente une facture de taxe supplémentaire à payer, ce qui relativise la bonne affaire!!!
A la dernière commande,sur un afficheur 20*4 I2c, il y a une ligne qui me sort des messages farfelus, c'est la deuxième ligne, j'ai fini par afficher sur trois lignes seulement... pas de SAV comme chez electrodragon (post de Jean luc). Pour les Arduino, je n'ai pas eu de problème.
Finalement, je préfère me servir chez un petit détaillant à Cannes, qui est, certes plus cher, mais avec le service en plus, et j'ai l'impression de soutenir l'emploi en France.
J'attend les résultats de votre joute pour me décider!!!!
Titre: Re : Un Arduino par module....ou pas.
Posté par: Guillaume le février 03, 2015, 02:31:54 pm
On fait les paris ; je mise sur Jean Luc.
Le wifi est imprécis, a des ratés, desfois on ne sait pas où il va mais il y va, plus les ondes qui merdouillent le signal. Plus lui en lui-meme qui font merdouiller des appareils, chez moi c'était le wifi qui faisait rebooter le terminal satellite, extrêmement désagréable.

Comme il le dit un fil de plus ne va pas changer la donne et on le connaît celui-là le CAN. Surtout que sans fil ne signifie pas entièrement sans fil tu es obligé d'amener le courant tout de même.
Par contre je ne comprends pas le fait qu'un module soit en panne fait merder tout le système. SI c'est un arduino terminal pas de souci c'est un bus qui distribue le CAN donc aucun pb si je ne me trompe pas comme l'i2c d'ailleurs sauf si bien sur c'est l'arduino TCO alors là que ce soit un système ou l'autre cela va tomber.

Chacun y voit son avantage, et ce sera à toi à choisir, le sans fil permet plus de libertés quant à certains choix, on peut placer après ou changer de plus sans retirer de fils etc...

Pour hubert, par contre j'ai bien aimé dans la même phrase cpl et sécurité ;)

Pour les douanes, commander chez un fournisseur américain garantit des frais de douanes. Les transporteurs le font automatiquement.
Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le février 03, 2015, 02:52:52 pm
Je ne suis pas spécialement pro-filaire et je pense qu'on est d'accord  :-* C'est juste que le sans fil a des temps de latence indéterminés qui dépendent de l'encombrement du médium de communication et la bande des 2,4Ghz est particulièrement encombrée (Bluetooth et wifi) et que ces conditions ne seront pas les même chez soi au calme radioélectrique (quoique en appartement...) et sur un salon où un tas de types vont se promener avec le Bluetooth de leur téléphone allumé et où plusieurs réseaux wifi seront déployés.

Tu ne peux pas faire reposer sur ce type de communication certains systèmes de contrôle où tu as besoin de connaître les temps de communication et d'être sûr de leur déterminisme pour assurer le bon fonctionnement du système. Ni sur des systèmes ou tu as besoin de la meilleure fiabilité de transmission possible.  Je ne dis pas que c'est le cas du système que veut construire petitrain. Je dis que les solutions ne sont pas uniquement à comparer quantitativement mais également qualitativement. Si le sans fil était aussi bien et universel, les constructeurs automobiles et les avionneurs n'hésiteraient pas une seconde à remplacer les dizaines ou centaines de kg de cuivre des fils par des modules radio. Ils gagneraient en coût et en simplicité de déploiement mais pas en fiabilité (pour ma part je ne monte pas dans un avion ou une voiture où les calculateurs sont interconnectés en sans fil  ::)).

C'est très différent des communications sur un réseau domestique ou entre micros où les latences sont gênantes mais ne mettent pas en danger le système. Où un clic souris qui ne passe pas n'est pas grâve. Dans ces applications, on cherche de la facilité, pas de la fiabilité et de la sûreté de fonctionnement.

En fait je pense que les deux solutions sont complémentaires. Ok pour le sans fil quand le fil est vraiment ennuyeux : manette, capteur à poser sur un module dont on n'est pas l'auteur pour prolonger un automatisme, systèmes non critique. Ok ce sont des petits trains mais pour moi les parties critiques sont les aiguillages (connaître avec de faibles chances de se tromper leur position), la détection (savoir où se trouve le matériel) et la traction (pouvoir arrêter une loco à coup sûr). Ces trois systèmes collaborent pour assurer l'anticollision. Il n'est pas souhaitable que ces systèmes soient en sans fil avec des temps de communication indéterministes.

En ce qui concerne les risques de pannes dues aux fils, il ne faut pas confondre le cas général où des fils sont déployés dans des lieux inappropriés et n'importe comment, humides, etc et le cas où c'est correctement déployé et la plupart des modélistes disposent soigneusement leur câblage. Par ailleurs, avec le CAN, on peut commencer par une séquence de « qui est là » ce qui permettra de connaître le fil ou le nœud en défaut.

Donc je ne suis pas pro-filaire ni pro-wifi, je suis pour utiliser les technologies là où elles font sens. J'ai utilisé le CAN extensivement sans rencontrer le moindre problème et avec des temps de communication parfaitement prédictibles et strictement réguliers. J'ai bricolé avec des nrf24 et je vais en utiliser là où c'est sympa et utile et je vais les soumettre à des tortures pour voir ce qu'on obtient. Donc les deux sont acceptés dans leur domaine de prédilection  ;)
Titre: Re : Re : Un Arduino par module....ou pas.
Posté par: Hubert le février 03, 2015, 03:28:06 pm
On fait les paris ; je mise sur Jean Luc.
Le wifi est imprécis, a des ratés, desfois on ne sait pas où il va mais il y va, plus les ondes qui merdouillent le signal. Plus lui en lui-meme qui font merdouiller des appareils, chez moi c'était le wifi qui faisait rebooter le terminal satellite, extrêmement désagréable.

Comme il le dit un fil de plus ne va pas changer la donne et on le connaît celui-là le CAN. Surtout que sans fil ne signifie pas entièrement sans fil tu es obligé d'amener le courant tout de même.
Par contre je ne comprends pas le fait qu'un module soit en panne fait merder tout le système. SI c'est un arduino terminal pas de souci c'est un bus qui distribue le CAN donc aucun pb si je ne me trompe pas comme l'i2c d'ailleurs sauf si bien sur c'est l'arduino TCO alors là que ce soit un système ou l'autre cela va tomber.

Chacun y voit son avantage, et ce sera à toi à choisir, le sans fil permet plus de libertés quant à certains choix, on peut placer après ou changer de plus sans retirer de fils etc...

Pour hubert, par contre j'ai bien aimé dans la même phrase cpl et sécurité ;)

Pour les douanes, commander chez un fournisseur américain garantit des frais de douanes. Les transporteurs le font automatiquement.
Bien sur que je suis certain du résultat, comme toi, il est évident que le filaire gagne. Pour autant, explorez un autre domaine fais avancer la science et la recherche.
Vu le prix du cuivre actuellement, une alternative est possible, maintenant nous n'en sommes qu'au début du sans-fil, nous en reparlerons dans une vingtaine d'année.
Une autre zone de recherche possible serait la fibre optique mais trop contraignante au niveau physique.
Quand je parlais de sécurité pour le CPL, je ne parlais pas de sécurité informatique ou de données mais de securité électrique et d'automatisation (volet,gestion d'appareil, ...) sans ajouter de fil supplémentaire .  ::)
Avec la continuité électrique hors zone, il est certain que n'importe qui se connectant au réseau peut savoir ce qui se proméne dessus, sauf à utiliser des filtres entrant et sortant mais bon. il en est de même pour les tuyau de cuivre des système de chauffages et de circuit d'eau qui transmettent aussi les signaux des cables non protégés se trouvant à proximité immédiate.

Nous sommes tous d'accord pour le CAN, voir pour l'I²C pour la fiabilité et la constance et du WIFI ou BLUETOOTH pour un système paliatif selon contraintes. 8)
 
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le février 18, 2015, 08:06:00 pm
je reprends un peu mon projet, on verra plus tard pour la communication des arduinos entre eux....
j'essaye de coder mon éclairage (celui des modules) commandé finalement par un seul arduino. J'ai installé des rubans de leds(1m de leds blanc chaud et 1m de leds RVB) et un spot halogene par module. Est-il possible de commander mes 5 sorties PWM d'une manière indépendante les unes des autres, avec des montées d'éclairage, des paliers, des descentes  à différents moments ou
est-ce que c'est trop demander à l'Arduino?
Pour l'instant, j'ai créé des compteurs avec millis() pour chaque PWM. chaque compteur incremente ou decremente mes fonctions analogWrite, pour les paliers il suffit de mettre à 255 ou à 0. Puis j'ai fait à nouveau un compteur qui compte le temps qui passe 0 à 24h mais je n'arrive pas à mettre ça en harmonie; j'essaye de poster un petit dessin de ce que j'imagine, ça sera plus clair....
Titre: Re : Un Arduino par module....ou pas.
Posté par: Guillaume le février 18, 2015, 09:09:38 pm
en quelque sorte ta limite d'imagination sera la limite de l'arduino ;)
Non tu peux imaginer tout à fait cela.
En harmonie c'est-à-dire ? Code soit disant fouilli ?
Poste ton code si tu veux un avis pas de souci pour le lire.

Je suis en quelque sorte en plein dedans ;) de ces animations lumineuses.
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le février 18, 2015, 10:41:32 pm
Merci, Guillaume de ta réponse rapide.
Non, en harmonie, c'est une façon de parler, je n'arrive à rien en fait....
J'ai fait un petit dessin de mon animation lumineuse....
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le février 18, 2015, 10:49:20 pm
Voilà mon code, individuellement les PWM marchent bien, mais dans le switch plus rien ne marche, si t'as une piste....

Citer
unsigned long tempsDebut=0;
unsigned long tempsDebut1=0;
unsigned long tempsDebut2=0;
unsigned long tempsDebut3=0;
unsigned long tempsActuel1;
unsigned long tempsActuel2;
unsigned long tempsActuel3;
int a=0;
int x=0;
int y=0;
int z=255;
int interval=20;
int interval1=50;
int interval2=200;
int interval3=300;
byte led1=3;
byte led2=5;
byte led3=6;


void setup(){
  Serial.begin(9600);
  pinMode(led1,OUTPUT);
  pinMode(led2,OUTPUT);
  pinMode(led3,OUTPUT);
}
void loop(){
  unsigned long tempsActuel= millis();       // le compteur pour le temps
  if(tempsActuel-tempsDebut>=interval){
    a++;
    tempsDebut=tempsActuel;
    Serial.println("a=");
    Serial.println(a);
    if(a==500){
      a=0;
    }
  }
  switch(a){
  case 10:
    tempsActuel1= millis();                    //La led blanc chaud
    if(tempsActuel1-tempsDebut1>=interval1){
      x++;
      tempsDebut1=tempsActuel1;
      Serial.println("x=");
      Serial.println(x);
      analogWrite(led1,x);
      if(x==255){
        x=0;
      }
    }
    break;
  case 30:
    tempsActuel2= millis();                   // L'Halogène
    if(tempsActuel2-tempsDebut2>=interval2){
      y++;
      tempsDebut2=tempsActuel2;
      Serial.println("y=");
      Serial.println(y);
      analogWrite(led2,y);
      if(y==255){
        y=0;
      }
    }
    break;

  case 50 :
    tempsActuel3= millis();                   // La led rouge
    if(tempsActuel3-tempsDebut3>=interval3){
      z--;
      tempsDebut3=tempsActuel3;
      Serial.println("z=");
      Serial.println(z);
      analogWrite(led3,z);
      if(z==0){
        z=255;
      }
    }
    break;
  }
}


Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le février 18, 2015, 11:24:17 pm
Bonsoir,

Qu'entends-tu par plus rien ne marche ?
Titre: Re : Un Arduino par module....ou pas.
Posté par: Guillaume le février 19, 2015, 10:36:23 am
Je pense que j'ai trouvé le pb. Tu initialise à chaque début de loop ta variable tempsactuel avec millis(). La variable a ne s'incrémente jamais et le switch n'est jamais fait. D'où l'absence de résultat.
Une variable temps qui s'initialise avec millis() n'est à initialiser qu'après que la condition avec millis() soit effectuée.

Si j'ai un conseil à te donner c'est d'individualiser tes animations lumières avec des if séparées ou autre condition puis avec la création de fonctions, comme cela si tu changes ton code tu n'auras plus qu'une seule partie à changer. Et après tu fais une création d'objets et op tout bon ;) mais là c'est petit à petit.

Petite aparthée pour Jean-Luc, l'apport de ton article fonctions sera très appréciée par petit train je pense ;)
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le février 19, 2015, 12:00:53 pm
En observant le retour via la liaison serie, le compteur du temps"a" s'incrémente normalement et, à chaque fois qu'il trouve case 10:,il incrémente le compteur de la led blanc chaud"x" de 1, puis avec case 30:, le compteur "y" de 1 et enfin avec case 50:, le compteur"z" perd 1 et ainsi de suite. C'est tellement long sur les sorties(leds) on a l'impression que rien ne se passe.
J'ai essayé de faire des fonctions : monteeEclairage() et descenteEclairage() mais je n'ai pas plus de succès.
Je voudrais bien comprendre la logique de l'Arduino. Je pense que ce sera plus facile, pour moi,après, de faire les différentes fonctions.
Je vais essayé d'enlever le switch et de mettre à la place des if()....else if(), je vous tiens au courant
En tous cas, merci de votre aide.....  on se sent moins seul devant cette petite platine qui n'en fait qu'à sa tête!!!
 
Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le février 19, 2015, 12:20:52 pm
Bonjour,

D'après ce que je comprends de ton programme :

La variable a est incrémentée de 0 à 500 toutes les 20ms. Au total le cycle prend 10 secondes

Quand a vaut 10, soit après 200ms la première branche du case est exécutée. Cette première branche n'incrémente x que si l'exécution a lieu après 50 ms. La première fois c'est toujours vrai. Ensuite il faut attendre 10,2 secondes pour que a vaille de nouveau 10. La seconde fois c'est également vrai et x est incrémenté. etc. Pour que la lumière passe de 0 à 255, il faudra 42 minutes et des poussière. Est-ce le comportement attendu ? Que veux tu faire exactement ?
Titre: Re : Un Arduino par module....ou pas.
Posté par: Guillaume le février 19, 2015, 12:29:45 pm
J'avoue alors que je ne sais pas sur une lecture rapide. J'étudierai plus en détail quand j'aurais plus le temps. J'ai du mal à voir le rapport entre le graphique et ton prog pour le moment.
Pour ma part, je n'utilise pas le millis() comme cela avec 2 variables temps. Chacun a ses propres pratiques de codage mais de mon coté j'utilise une seule variable time unsigned long. Je l'initialise à millis() dans le setup et dans la boucle, je fais comme cela :
if((millis() -temps)>intervallefixe){
temps=millis();
puis action
}
J'utilise comme cela moins d'espace mémoire allouable pour les variables (la ram).

Après pour ma part, j'ai pris le parti de faire une variable heure dirons nous qui dit quelle heure il est et en fonction de cette variable les animations se font ou pas. J'aurais qu'une variable unsigned long pour millis(). Je présenterai cela plus tard sur le post.
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le février 19, 2015, 12:54:54 pm
Pour Jean Luc:
 Non, ce n'est pas ce que j'attendais. Je voudrais mettre en oeuvre mon graphique:
  des sorties PWM qui puissent être réglables et qui se déclenchent à différents moments d'un cycle jour/nuit.

Pour Guillaume:
Je comprends mieux comment tu fais. OK pour la variable heure qui dit quand faire quoi; mais comment fais-tu pour commander des fonctions analogWrite(), il te faut bien d'autres variables qui dépendent elles aussi du temps....ou je me trompe?
Titre: Re : Un Arduino par module....ou pas.
Posté par: Guillaume le février 19, 2015, 01:08:12 pm
Tu as raison, schématiquement je fais comme tu as dis avec ce que j'ai dit :
donc une variable heure int qui va de 0000 à 2359 en ne mettant pas les 2267 par exemple en fait c'est l'heure mais tout attachée. Cela va définir si l'animation doit être on ou off dans le cas de sortie numérique simple sans PWM c'est suffisant. Dans le cas de PWM effectivement non, et là il faut rajouter une variable millis() avec une condition pour effectuer ta montée au début de on et la descente au début de off.
Voilà en gros, c'est la théorie, je l'ai mis en pratique pour certains trucs cela marche.
Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le février 19, 2015, 03:15:46 pm
Hem, j'avais pas vu le graphique.

Pour s'en sortir avec un programme, il faut d'abord établir les données nécessaires. Une fois les données nécessaires déterminées, le code vient (presque) tout seul. Ton appli n'est pas des plus simples car tu as plusieurs intervalles de temps à gérer et qui plus est 2 chronomètre, un pour compter les durées des rampes d'augmentation et de diminution et un pour compter les intervalles de temps entre deux augmentations ou diminutions de la PWM.

Il faut tout d'abord exprimer le temps en unités qui correspondent à ton application. Par exemple, le tick est la seconde. Le mieux est de faire une fonction qui te renvoie dans le nombre de ticks :

const unsigned long dureeDuTick = 1000;

unsigned long temps()
{
    return millis()/dureeDuTick;
}

Pour gérer tes éclairages, tu as besoin, en plus du temps, de gérer l'état de chacun des éclairages. Comme tu as certains éclairages qui accomplissent 2 cycles par 24h, la led verte et la led rouge, il faut 8 états. À savoir :

ETEINT1, AUGMENTATION1, ALLUME1, DIMINUTION1, ETEINT2, AUGMENTATION2, ALLUME2 et DIMINUTION2.

Je te propose de représenter cela par un enum

enum { ETEINT1, AUGMENTATION1, ALLUME1, DIMINUTION1, ETEINT2, AUGMENTATION2, ALLUME2, DIMINUTION2 };

Ensuite il te faut un chronomètre par éclairage pour compter le temps écoulé avant de passer d'un état au suivant et il te faut également les durées, en nombre de ticks, des états. Il te faut aussi le nombre de tick entre 2 augmentations de valeur de PWM. C'est donné par la durée de l'augmentation ou de la diminution divisée par 255.

Et enfin la pin PWM concernée et la valeur de la PWM.

Je te propose de représenter cela par une structure :

struct eclairage {
  const byte pin; /* pin de PWM */
  byte etat;
  byte valeurPWM;
  byte intervallePWM; /* nombre de ticks entre 2 changement de PWM */
  unsigned long chronometre;
  const int dureeEteint1;
  const int dureeAugmentation1;
  const int dureeAllume1;
  const int dureeDiminution1;
  const int dureeEteint2;
  const int dureeAugmentation2;
  const int dureeAllume2;
  const int dureeDiminution2;
};


Ensuite il faut instancier une struct par éclairage. Si je reprends ton graphique, on a ledVerte, ledRouge, ledBleue, ledBlancChaud et halogene.

Je n'arrive pas bien à voir les date exactes sur ton graphique mais on va dire que la led verte reste éteinte pendant 8h30 = 27000s. Puis elle augmente pendant 2h = 7200. Puis elle reste allumée pendant 0. Puis elle diminue pendant 3h = 10800. Puis elle reste éteinte pendant 5h = 18000s puis elle augmente pendant 2h = 7200 puis reste allumée 1h30 = 5400s puis diminue pendant 2h = 7200s. Total = 30600 + 7200 + 0 + 10800 + 18000 + 7200 + 5400 +7200 = 86400 / 3600 = 24. On est bon
Les temps sont en seconde car le tick est à la seconde. Ce qui donne pour ledVerte :

struct eclairage ledVerte = { pinLedVerte, ETEINT1, 0, 25200, 30600, 7200, 0, 10800, 18000, 7200, 6400, 7200 };

Le chronomètre est initialisé à une durée de 7h car au 0 de ton cycle, on a déjà consommé 1h30.

La gestion du cycle de lumière :

void gereEclairage(struct eclairage& lumiere)
{
  unsigned long dateCourante = millis();
 
  switch (lumiere.etat) {
    case ETEINT1:
      if (lumiere.dateChargementChronometre + lumiere.chronometre > dateCourante)
      {
        lumiere.dateChargementChronometre = dateCourante;
        lumiere.chronometre = lumiere.dureeAugmentation1;
        lumiere.etat = AUGMENTATION1;
        lumiere.valeurPWM = 0;
        lumiere.intervallePWM = lumiere.dureeAugmentation1 / 255;
        lumiere.dateChargementIntervallePWM = dateCourante;
      }
      break;
    case AUGMENTATION1:
      if (lumiere.dateChargementChronometre + lumiere.chronometre > dateCourante)
      {
        lumiere.dateChargementChronometre = dateCourante;
        lumiere.chronometre = lumiere.dureeAllume1;
        lumiere.etat = ALLUME1;
        lumiere.valeurPWM = 255;
      }
      else if (lumiere.dateChargementIntervallePWM + lumiere.intervallePWM > dateCourante)
      {
        lumiere.dateChargementIntervallePWM = dateCourante;
        lumiere.valeurPWM++;
        analogWrite(lumiere.pin, lumiere.valeurPWM);
      }
      break;
    case ALLUME1:
      if (lumiere.dateChargementChronometre + lumiere.chronometre > dateCourante)
      {
        lumiere.dateChargementChronometre = dateCourante;
        lumiere.chronometre = lumiere.dureeDiminution1;
        lumiere.etat = DIMINUTION1;
        lumiere.valeurPWM = 0;
        lumiere.intervallePWM = lumiere.dureeDiminution1 / 255;
        lumiere.dateChargementIntervallePWM = dateCourante;
      }
      break;
    case DIMINUTION1:
      if (lumiere.dateChargementChronometre + lumiere.chronometre > dateCourante)
      {
        lumiere.dateChargementChronometre = dateCourante;
        lumiere.chronometre = lumiere.dureeEteint2;
        lumiere.etat = ETEINT2;
        lumiere.valeurPWM = 0;
      }
      else if (lumiere.dateChargementIntervallePWM + lumiere.intervallePWM > dateCourante)
      {
        lumiere.dateChargementIntervallePWM = dateCourante;
        lumiere.valeurPWM--;
      }
      break;
    case ETEINT2:
      if (lumiere.dateChargementChronometre + lumiere.chronometre > dateCourante)
      {
        lumiere.dateChargementChronometre = dateCourante;
        lumiere.chronometre = lumiere.dureeAugmentation2;
        lumiere.etat = AUGMENTATION2;
        lumiere.valeurPWM = 0;
        lumiere.intervallePWM = lumiere.dureeAugmentation2 / 255;
        lumiere.dateChargementIntervallePWM = dateCourante;
      }
      break;
    case AUGMENTATION2:
      if (lumiere.dateChargementChronometre + lumiere.chronometre > dateCourante)
      {
        lumiere.dateChargementChronometre = dateCourante;
        lumiere.chronometre = lumiere.dureeAllume2;
        lumiere.etat = ALLUME2;
        lumiere.valeurPWM = 255;
      }
      else if (lumiere.dateChargementIntervallePWM + lumiere.intervallePWM > dateCourante)
      {
        lumiere.dateChargementIntervallePWM = dateCourante;
        lumiere.valeurPWM++;
        analogWrite(lumiere.pin, lumiere.valeurPWM);
      }
      break;
    case ALLUME2:
      if (lumiere.dateChargementChronometre + lumiere.chronometre > dateCourante)
      {
        lumiere.dateChargementChronometre = dateCourante;
        lumiere.chronometre = lumiere.dureeDiminution2;
        lumiere.etat = DIMINUTION2;
        lumiere.valeurPWM = 0;
        lumiere.intervallePWM = lumiere.dureeDiminution2 / 255;
        lumiere.dateChargementIntervallePWM = dateCourante;
      }
      break;
    case DIMINUTION2:
      if (lumiere.dateChargementChronometre + lumiere.chronometre > dateCourante)
      {
        lumiere.dateChargementChronometre = dateCourante;
        lumiere.chronometre = lumiere.dureeEteint1;
        lumiere.etat = ETEINT1;
        lumiere.valeurPWM = 0;
      }
      else if (lumiere.dateChargementIntervallePWM + lumiere.intervallePWM > dateCourante)
      {
        lumiere.dateChargementIntervallePWM = dateCourante;
        lumiere.valeurPWM--;
      }
      break;
  }
  analogWrite(lumiere.pin, lumiere.valeurPWM);
}

Dans setup :

void setup() {
  pinMode(ledVerte.pin, OUTPUT);
}

Dans loop :

void loop() {
  // put your main code here, to run repeatedly:
  gereEclairage(ledVerte);
}

Le code complet, ça compile mais ce n'est absolument pas testé.

const unsigned long dureeDuTick = 1000;

const byte pinLedVerte = 3;

unsigned long temps()
{
    return millis()/dureeDuTick;
}

enum { ETEINT1, AUGMENTATION1, ALLUME1, DIMINUTION1, ETEINT2, AUGMENTATION2, ALLUME2, DIMINUTION2 };

struct eclairage {
  const byte pin; /* pin de PWM */
  byte etat; /* etat : ETEINT, AUGMENTATION, ALLUME, DIMINUTION */
  unsigned long chronometre;
  unsigned long dateChargementChronometre;
  unsigned long dateChargementIntervallePWM;
  unsigned long intervallePWM; /* nombre de ticks entre 2 changement de PWM */
  byte valeurPWM;
  const int dureeEteint1;
  const int dureeAugmentation1;
  const int dureeAllume1;
  const int dureeDiminution1;
  const int dureeEteint2;
  const int dureeAugmentation2;
  const int dureeAllume2;
  const int dureeDiminution2;
};

struct eclairage ledVerte = { pinLedVerte, ETEINT1, 25200, 0, 0, 0, 0, 30600, 7200, 0, 10800, 18000, 7200, 6400, 7200 };

void gereEclairage(struct eclairage& lumiere)
{
  unsigned long dateCourante = millis();
 
  switch (lumiere.etat) {
    case ETEINT1:
      if (lumiere.dateChargementChronometre + lumiere.chronometre > dateCourante)
      {
        lumiere.dateChargementChronometre = dateCourante;
        lumiere.chronometre = lumiere.dureeAugmentation1;
        lumiere.etat = AUGMENTATION1;
        lumiere.valeurPWM = 0;
        lumiere.intervallePWM = lumiere.dureeAugmentation1 / 255;
        lumiere.dateChargementIntervallePWM = dateCourante;
      }
      break;
    case AUGMENTATION1:
      if (lumiere.dateChargementChronometre + lumiere.chronometre > dateCourante)
      {
        lumiere.dateChargementChronometre = dateCourante;
        lumiere.chronometre = lumiere.dureeAllume1;
        lumiere.etat = ALLUME1;
        lumiere.valeurPWM = 255;
      }
      else if (lumiere.dateChargementIntervallePWM + lumiere.intervallePWM > dateCourante)
      {
        lumiere.dateChargementIntervallePWM = dateCourante;
        lumiere.valeurPWM++;
        analogWrite(lumiere.pin, lumiere.valeurPWM);
      }
      break;
    case ALLUME1:
      if (lumiere.dateChargementChronometre + lumiere.chronometre > dateCourante)
      {
        lumiere.dateChargementChronometre = dateCourante;
        lumiere.chronometre = lumiere.dureeDiminution1;
        lumiere.etat = DIMINUTION1;
        lumiere.valeurPWM = 0;
        lumiere.intervallePWM = lumiere.dureeDiminution1 / 255;
        lumiere.dateChargementIntervallePWM = dateCourante;
      }
      break;
    case DIMINUTION1:
      if (lumiere.dateChargementChronometre + lumiere.chronometre > dateCourante)
      {
        lumiere.dateChargementChronometre = dateCourante;
        lumiere.chronometre = lumiere.dureeEteint2;
        lumiere.etat = ETEINT2;
        lumiere.valeurPWM = 0;
      }
      else if (lumiere.dateChargementIntervallePWM + lumiere.intervallePWM > dateCourante)
      {
        lumiere.dateChargementIntervallePWM = dateCourante;
        lumiere.valeurPWM--;
      }
      break;
    case ETEINT2:
      if (lumiere.dateChargementChronometre + lumiere.chronometre > dateCourante)
      {
        lumiere.dateChargementChronometre = dateCourante;
        lumiere.chronometre = lumiere.dureeAugmentation2;
        lumiere.etat = AUGMENTATION2;
        lumiere.valeurPWM = 0;
        lumiere.intervallePWM = lumiere.dureeAugmentation2 / 255;
        lumiere.dateChargementIntervallePWM = dateCourante;
      }
      break;
    case AUGMENTATION2:
      if (lumiere.dateChargementChronometre + lumiere.chronometre > dateCourante)
      {
        lumiere.dateChargementChronometre = dateCourante;
        lumiere.chronometre = lumiere.dureeAllume2;
        lumiere.etat = ALLUME2;
        lumiere.valeurPWM = 255;
      }
      else if (lumiere.dateChargementIntervallePWM + lumiere.intervallePWM > dateCourante)
      {
        lumiere.dateChargementIntervallePWM = dateCourante;
        lumiere.valeurPWM++;
        analogWrite(lumiere.pin, lumiere.valeurPWM);
      }
      break;
    case ALLUME2:
      if (lumiere.dateChargementChronometre + lumiere.chronometre > dateCourante)
      {
        lumiere.dateChargementChronometre = dateCourante;
        lumiere.chronometre = lumiere.dureeDiminution2;
        lumiere.etat = DIMINUTION2;
        lumiere.valeurPWM = 0;
        lumiere.intervallePWM = lumiere.dureeDiminution2 / 255;
        lumiere.dateChargementIntervallePWM = dateCourante;
      }
      break;
    case DIMINUTION2:
      if (lumiere.dateChargementChronometre + lumiere.chronometre > dateCourante)
      {
        lumiere.dateChargementChronometre = dateCourante;
        lumiere.chronometre = lumiere.dureeEteint1;
        lumiere.etat = ETEINT1;
        lumiere.valeurPWM = 0;
      }
      else if (lumiere.dateChargementIntervallePWM + lumiere.intervallePWM > dateCourante)
      {
        lumiere.dateChargementIntervallePWM = dateCourante;
        lumiere.valeurPWM--;
      }
      break;
  }
  analogWrite(lumiere.pin, lumiere.valeurPWM);
}

void setup() {
  pinMode(ledVerte.pin, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  gereEclairage(ledVerte);
}
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le février 19, 2015, 06:48:35 pm
Merci pour ces réponses, je vais étudier tout ça....
Finalement, quand je demandai "est-ce que c'est trop demandé à l'Arduino?" je parlai du langage Arduino. Et, je m'aperçois, en voyant la réponse de Jean Luc, qu'effectivement, c'est trop demandé... il faut passer par d'autres langages. Ne connaissant pas le C#, j'ai peur de pas tout comprendre.
Titre: Re : Un Arduino par module....ou pas.
Posté par: Guillaume le février 19, 2015, 06:57:49 pm
C'est vrai que la réponse de Jean Luc est complète, et rassures toi je n'ai pas encore tout compris. Mais cela s'apprend il n'y a pas de difficulté majeure. Je suis parti de zéro il n'y pas si longtemps et j'arrive à faire des class certes simples mais tout de même ;), et finalement on pourrait dire c'est trop dur. Mais tout le monde peut y arriver.

Chacun y arrivera à sa manière. N'hésite pas à revenir poser des questions.
Titre: Re : Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le février 19, 2015, 08:29:34 pm
... il faut passer par d'autres langages. Ne connaissant pas le C#, j'ai peur de pas tout comprendre.

Hummmm. Ce n'est pas du C#. C'est du C c'est à dire le langage de l'Arduino qui a de multiples facettes.

Si tu as des soucis de compréhension, regarde mon dernier article : Les structures (http://www.locoduino.org/spip.php?article107)

Ce que tu essayes de faire n'est pas des plus simple  :) et ça va nécessiter des notions au delà du niveau débutant.
Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le février 20, 2015, 08:19:27 am
Note que pour tester, il suffit de diminuer la constante dureeDuTick pour enchaîner la séquence à plus grande vitesse.
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le février 20, 2015, 08:56:16 am
C'est ce que j'ai fait, j'ai même réduit le tick à 1. Le programme compile bien mais ma led s'allume au debut du programme et reste tout le temps allumé. J'essaie de comprendre le programme mais c'est pas simple, il me manque beaucoup de connaissance
pour m'en sortir tout seul. Est-ce que ça ne serait pas plus simple de se servir d'un CI dédié à la PWM, par exemple le TLC5940 ou autre avec une library qui va bien, est-ce que je pourrais gérer mon éclairage d'une manière plus souple, en faisant chevaucher mes différentes sorties?
Titre: Re : Un Arduino par module....ou pas.
Posté par: Guillaume le février 20, 2015, 09:15:48 am
Les connaissances viendront mais bon tu as quand même une base en parlant des Tmachin.

Je dirais que c'est encore un peu compliqué la donne que de mettre un autre CI. L'arduino peut gérer cela, et les connaissances apprises te serviront pour autre chose.
Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le février 20, 2015, 09:25:19 am
Le TLC5940 va juste te donner des PWM supplémentaires et 12 bits (de 0 à 4095) au lieu de 8 bits. Mais leur gestion restera identique aux PWM internes de l'Arduino.

Effectivement la LED s'allume et reste allumée tout le temps. Je regarde où je me suis trompé.
Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le février 20, 2015, 10:07:24 am
Plusieurs erreurs : il faut appeler temps() au lieu de millis() au début de gereEclairage :)

Ensuite mes comparaisons de temps ... c'était n'importe quoi  :o

Voici le code corrigé. J'ai laissé les print de debug et c'est accéléré 1000 fois :

const unsigned long dureeDuTick = 1;

const byte pinLedVerte = 3;

unsigned long temps()
{
    return millis()/dureeDuTick;
}

enum { ETEINT1, AUGMENTATION1, ALLUME1, DIMINUTION1, ETEINT2, AUGMENTATION2, ALLUME2, DIMINUTION2 };

struct eclairage {
  const byte pin; /* pin de PWM */
  byte etat;
  unsigned long duree;
  unsigned long dateChargementduree;
  unsigned long dateChargementIntervallePWM;
  unsigned long intervallePWM; /* nombre de ticks entre 2 changement de PWM */
  byte valeurPWM;
  const int dureeEteint1;
  const int dureeAugmentation1;
  const int dureeAllume1;
  const int dureeDiminution1;
  const int dureeEteint2;
  const int dureeAugmentation2;
  const int dureeAllume2;
  const int dureeDiminution2;
};

void afficheEtatEclairage(byte etat)
{
  switch (etat)
  {
    case ETEINT1:       Serial.print("ETEINT-1");       break;
    case AUGMENTATION1: Serial.print("AUGMENTATION-1"); break;
    case ALLUME1:       Serial.print("ALLUME-1");       break;
    case DIMINUTION1:   Serial.print("DIMINUTION-1");   break;
    case ETEINT2:       Serial.print("ETEINT-2");       break;
    case AUGMENTATION2: Serial.print("AUGMENTATION-2"); break;
    case ALLUME2:       Serial.print("ALLUME-2");       break;
    case DIMINUTION2:   Serial.print("DIMINUTION-2");   break;
    default:            Serial.print("etat inconnu");
  }
}

void afficheEclairage(struct eclairage& lumiere)
{
  Serial.print("date:"); Serial.print(temps()); Serial.print(", ");
  Serial.print(lumiere.pin); Serial.print(", "); afficheEtatEclairage(lumiere.etat); Serial.print(", ");
  Serial.print("duree="); Serial.print(lumiere.duree);
  Serial.print(", progression="); Serial.print(temps() - lumiere.dateChargementduree);
  Serial.println();
}

struct eclairage ledVerte = { pinLedVerte, ETEINT1, 25200, 0, 0, 0, 0, 30600, 7200, 0, 10800, 18000, 7200, 6400, 7200 };

void gereEclairage(struct eclairage& lumiere)
{
  unsigned long dateCourante = temps();
 
  switch (lumiere.etat) {
    case ETEINT1:
      if (dateCourante - lumiere.dateChargementduree > lumiere.duree)
      {
        lumiere.dateChargementduree = dateCourante;
        lumiere.duree = lumiere.dureeAugmentation1;
        lumiere.etat = AUGMENTATION1;
        lumiere.valeurPWM = 0;
        lumiere.intervallePWM = lumiere.dureeAugmentation1 / 255;
        lumiere.dateChargementIntervallePWM = dateCourante;
      }
      break;
    case AUGMENTATION1:
      if (dateCourante - lumiere.dateChargementduree > lumiere.duree)
      {
        lumiere.dateChargementduree = dateCourante;
        lumiere.duree = lumiere.dureeAllume1;
        lumiere.etat = ALLUME1;
        lumiere.valeurPWM = 255;
      }
      else if (dateCourante - lumiere.dateChargementIntervallePWM > lumiere.intervallePWM)
      {
        lumiere.dateChargementIntervallePWM = dateCourante;
        lumiere.valeurPWM++;
      }
      break;
    case ALLUME1:
      if (dateCourante - lumiere.dateChargementduree > lumiere.duree)
      {
        lumiere.dateChargementduree = dateCourante;
        lumiere.duree = lumiere.dureeDiminution1;
        lumiere.etat = DIMINUTION1;
        lumiere.valeurPWM = 255;
        lumiere.intervallePWM = lumiere.dureeDiminution1 / 255;
        lumiere.dateChargementIntervallePWM = dateCourante;
      }
      break;
    case DIMINUTION1:
      if (dateCourante - lumiere.dateChargementduree > lumiere.duree)
      {
        lumiere.dateChargementduree = dateCourante;
        lumiere.duree = lumiere.dureeEteint2;
        lumiere.etat = ETEINT2;
        lumiere.valeurPWM = 0;
      }
      else if (dateCourante - lumiere.dateChargementIntervallePWM > lumiere.intervallePWM)
      {
        lumiere.dateChargementIntervallePWM = dateCourante;
        lumiere.valeurPWM--;
      }
      break;
    case ETEINT2:
      if (dateCourante - lumiere.dateChargementduree > lumiere.duree)
      {
        lumiere.dateChargementduree = dateCourante;
        lumiere.duree = lumiere.dureeAugmentation2;
        lumiere.etat = AUGMENTATION2;
        lumiere.valeurPWM = 0;
        lumiere.intervallePWM = lumiere.dureeAugmentation2 / 255;
        lumiere.dateChargementIntervallePWM = dateCourante;
      }
      break;
    case AUGMENTATION2:
      if (dateCourante - lumiere.dateChargementduree > lumiere.duree)
      {
        lumiere.dateChargementduree = dateCourante;
        lumiere.duree = lumiere.dureeAllume2;
        lumiere.etat = ALLUME2;
        lumiere.valeurPWM = 255;
      }
      else if (dateCourante - lumiere.dateChargementIntervallePWM > lumiere.intervallePWM)
      {
        lumiere.dateChargementIntervallePWM = dateCourante;
        lumiere.valeurPWM++;
        analogWrite(lumiere.pin, lumiere.valeurPWM);
      }
      break;
    case ALLUME2:
      if (dateCourante - lumiere.dateChargementduree > lumiere.duree)
      {
        lumiere.dateChargementduree = dateCourante;
        lumiere.duree = lumiere.dureeDiminution2;
        lumiere.etat = DIMINUTION2;
        lumiere.valeurPWM = 255;
        lumiere.intervallePWM = lumiere.dureeDiminution2 / 255;
        lumiere.dateChargementIntervallePWM = dateCourante;
      }
      break;
    case DIMINUTION2:
      if (dateCourante - lumiere.dateChargementduree > lumiere.duree)
      {
        lumiere.dateChargementduree = dateCourante;
        lumiere.duree = lumiere.dureeEteint1;
        lumiere.etat = ETEINT1;
        lumiere.valeurPWM = 0;
      }
      else if (dateCourante - lumiere.dateChargementIntervallePWM > lumiere.intervallePWM)
      {
        lumiere.dateChargementIntervallePWM = dateCourante;
        lumiere.valeurPWM--;
      }
      break;
  }
  analogWrite(lumiere.pin, lumiere.valeurPWM);
}

void setup() {
  Serial.begin(9600);
  afficheEclairage(ledVerte);
  pinMode(ledVerte.pin, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  gereEclairage(ledVerte);
 
  static unsigned long dateAff = 0;
  unsigned long date = millis();
  if (date - dateAff > 1000)
  {
    afficheEclairage(ledVerte);
    dateAff = date;
  }
}


Pour les autres lumières, il suffit de déclarer autant de variables de type struct eclairage qu'il y a de lumières avec les durées voulues dans l'initialisation de la struct et d'appeler gereEclairage pour chacune d'entre elles.
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le février 20, 2015, 01:52:13 pm
Un grand merci.... Ca marche.... Je n'ai plus qu'a potasser le C pour comprendre comment tu as fait. Avant que j'arrive à faire ça moi-même, jamais je n'aurais imaginé qu'il faille se torturer ôtant les méninges pour faire le jour et la nuit...
Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le février 20, 2015, 02:50:27 pm
La difficulté est de faire plusieurs choses simultanément. Un seul éclairage est très facile a faire  :)
Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le février 20, 2015, 05:04:24 pm
Ca intéresserait quelqu'un une bibliothèque permettant d'ordonnancer des appels de fonction à des intervalles dans le temps ?
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le février 21, 2015, 06:56:51 pm
tu veux dire de gerer une timeline avec des analogWrite qui se chevauchent?
Moi, je serais bigrement intéressé....
Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le février 22, 2015, 09:22:46 am
Ok, je m'occupe de ça :)
Titre: Re : Un Arduino par module....ou pas.
Posté par: fking le février 22, 2015, 09:57:00 am
Et se baser sur un module RTC genre DS1307 ??? Il suffit de tester l'heure, et en fonction, de gérer les sorties.
Titre: Re : Un Arduino par module....ou pas.
Posté par: Guillaume le février 22, 2015, 11:27:49 am
Sauf qu'un tel truc donne l'heure IRL, ici ce serait plus pour faire un cycle jour/nuit rapide un peu à la manière du wonderland d'Hamburg.
Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le février 22, 2015, 12:09:50 pm
Le problème est surtout de gérer plusieurs « timelines » simultanément pas tellement d'avoir une base de temps :)
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le février 22, 2015, 01:31:31 pm
Oui, je vois plus une time line ou on peut régler les " tics" et la durée.
Après des fonctions OUT digitalWrite(), analogWrite(), que l'on peut placer et paramètrer comme on veut dans la time line.
Par exemple, on passe en paramètre le tempsDébut, la DuréeMonté ou DuréeDescente, la hauteurPWM, etc...
La bibliothèque devient universelle pour un tas de cas dans les automatismes liés à notre hobby. Pour les entrées( capteurs, boutons), faudra-t-il prévoir des fonctions supplémentaires ou lier à des interruptions?
Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le février 25, 2015, 06:00:13 pm
Bonjour,

Voilà, la bibliothèque est implémentée. Il s'agit d'un implémentation des tables d'ordonnancement.

J'explique la philosophie.

Il s'agit d'ordonnancer des actions dans le temps. À cet effet on définit une période qui a une durée avec un instant initial qui est l'instant de démarrage et un instant final qui est l'instant initial + la durée. Entre cet instant initial et cet instant final, on place des actions. Une action est l'appel d'une fonction que l'utilisateur fournit. La période peut ensuite être répétée entre 1 et 65535 fois ou bien infiniment.

La bibliothèque offre une classe ScheduleTable que l'on peut instancier pour créer ces périodes où des actions sont ordonnancées. Pour déclarer une ScheduleTable, on écrit par exemple :

ScheduleTable myTable(3, 200);

Le premier argument est le nombre d'actions que peut contenir la table, ici 3. Le 2e est sa durée, ici 200. Par défaut, il s'agit de millisecondes. On peut fournir un 3e argument qui donne la base de temps. Par exemple :

ScheduleTable myTable(3, 200, 100);

précise une base de temps de 100 ms. Par conséquent 200 représente 200 x 100 ms de durée. Toutes les durées relative à myTable seront exprimées en centaines de millisecondes.

Ensuite dans setup(), on place des actions à des dates relative par rapport au début de la période. Par exemple si sur notre période de 200 unités de temps on veut placer une action à 50, 60, 120, on écrira dans setup :

myTable.at(50, action1);
myTable.at(60, action2);
myTable.at(120, action3);

action1, action2 et action3 sont des fonctions définies comme suit :

void action1()
{
    Serial.print(millis());
    Serial.println(" : action 1");
}

void action2()
{
    Serial.print(millis());
    Serial.println(" : action 2");
}

void action3()
{
    Serial.print(millis());
    Serial.println(" : action 3");
}

Il faut ensuite lancer la table on peut faire ça dans setup pour que ça soit en route pour toute l'application :

myTable.start()

Ensuite, il n'y a pas de miracle, il faut appeler répétitivement la méthode update() dans loop pour que la schedule table fonctionne :

myTable.update()

On peut également stopper une schedule table :

myTable.stop();

Je poste la bibliothèque et du code exemple plus tard
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le février 25, 2015, 11:36:33 pm
Bonsoir jean luc,
je viens de lire ton descriptif, ta bibliothèque a l'air bien alléchante et simple à prendre en main. Je ne pourrais, malheureusement, pas la tester tout de suite car je pars demain matin pour 3 semaines en Bretagne ( loin du réseau et de l'Arduino).
Je pense que tu vas faire plus d'un heureux avec ça, car beaucoup d'animations  sur les réseaux sont gérés selon ce principe...
à bientôt,
Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le février 26, 2015, 02:46:16 pm
Bonjour,

Une petite modif, la mise à jour des schedule tables se fait via une méthode de classe. Donc il suffit d'un appel pour tout mettre à jour :

  ScheduleTable::update();

Le github est ici : https://github.com/Koryphon/ScheduleTable

J'ai mis 3 exemples. Voici un exemple simple de feux tricolores utilisant les schedule table (j'ai écrit les commentaires en anglais, désolé)

/*
 * More complex example of the use of the ScheduleTable library
 *
 * This example uses 2 ScheduleTable with 3 actions each.
 * Each schedule table manages a traffic light.
 *
 * Each traffic light has a 30s period.
 * - Green light lasts for 13s
 * - Yellow light lasts for 2s
 * - Red light lasts for 15s
 * Schedule tables are shifted so that one light switches from
 * red to green when the other one shift from yellow to red.
 */

#include <ScheduleTable.h>
 
/* Both light cycle has 3 actions, lasts 30 time unit and has a 1000ms time base */
ScheduleTable firstLightCycle(3,30,1000);
ScheduleTable secondLightCycle(3,30,1000);

struct trafficLight {
  byte greenPin;
  byte yellowPin;
  byte redPin;
};

const struct trafficLight firstLight  = { 3, 4, 5 };
const struct trafficLight secondLight = { 6, 7, 8 };

enum { GREEN, YELLOW, RED };

void setLightState(const struct trafficLight& light, const byte state)
{
  digitalWrite(light.greenPin, LOW);
  digitalWrite(light.yellowPin, LOW);
  digitalWrite(light.redPin, LOW);
  switch (state) {
    case GREEN:  digitalWrite(light.greenPin, HIGH);  break;
    case YELLOW: digitalWrite(light.yellowPin, HIGH); break;
    case RED:    digitalWrite(light.redPin, HIGH);    break;
  }
}

void firstLightGreen()   { setLightState(firstLight, GREEN);   }
void firstLightYellow()  { setLightState(firstLight, YELLOW);  }
void firstLightRed()     { setLightState(firstLight, RED);     }
void secondLightGreen()  { setLightState(secondLight, GREEN);  }
void secondLightYellow() { setLightState(secondLight, YELLOW); }
void secondLightRed()    { setLightState(secondLight, RED);    }

void setup()
{
  pinMode(firstLight.greenPin,   OUTPUT);
  pinMode(firstLight.yellowPin,  OUTPUT);
  pinMode(firstLight.redPin,     OUTPUT);
  pinMode(secondLight.greenPin,  OUTPUT);
  pinMode(secondLight.yellowPin, OUTPUT);
  pinMode(secondLight.redPin,    OUTPUT);
 
  /* Green at start for first light */
  firstLightGreen();
  /* at 13s first light switches to yellow */
  firstLightCycle.at(13,firstLightYellow);
  /* at 15s, it switches to red */
  firstLightCycle.at(15,firstLightRed);
  /* at 30s, it switches back to green */
  firstLightCycle.at(30,firstLightGreen);

   /* Red at start for second light  */
  secondLightRed();
  /* at 15s, it switches to green */
  secondLightCycle.at(15,secondLightGreen);
  /* at 28s, it switches to yellow */
  secondLightCycle.at(28,secondLightYellow);
  /* at 30s, it switches to red */
  secondLightCycle.at(30,secondLightRed);
 
  /* starts both light forever */
  firstLightCycle.start();
  secondLightCycle.start();
}

void loop()
{
  /* update all the schedule tables at once */
  ScheduleTable::update();
}

Et l'exemple de la DEL verte de petitrain


/*
 * A third complex example of the use of the ScheduleTable library
 *
 * This example uses 3 ScheduleTable with 4 actions for the first one
 * and 1 action of the other two.
 *
 * The first schedule table manages the whole cyle with:
 * - a first action to start led dimming from 0 to 255
 * - a second action to start led dimming from 255 to 0
 * - a third action identical to the first one to start led dimming from 0 to 255
 * - a fourth action to start led dimming from 255 to 0 at faster pace
 *
 * The sketch is supposed to do the cycle in 24h but the execution is sped 1000 times
 * To change the speed, change the time base of each schedule table.
 */

#include <ScheduleTable.h>

/*
 * The Green LED cycles.
 */

/* 4 actions, period duration in seconds = 24h */
ScheduleTable greenLEDCycle(4,86400);
/* 1 action, period duration = 7200 / 255 = 28 */
ScheduleTable greenLEDPWMIncreaseCycle(1,28);
/* 1 action, period duration = 10800 / 255 = 42 */
ScheduleTable greenLEDPWMDecreaseCycle(1,42);

byte pwmGreenLED = 0;
byte pinGreenLED = 3;

/*
 * This function is called to start the increase of the PWM
 */
void startPWMIncrease()
{
  /* start the schedule table for 255 periods */
  greenLEDPWMIncreaseCycle.start(255);
}

/*
 * This function is called to start the decrease of the PWM
 */
void startPWMDecreaseFast()
{
  /* start the schedule table for 255 periods of 28s */
  greenLEDPWMDecreaseCycle.setPeriod(28);
  greenLEDPWMDecreaseCycle.start(255);
}

/*
 * This function is called to start the decrease of the PWM
 */
void startPWMDecreaseSlow()
{
  /* start the schedule table for 255 periods of 42s */
  greenLEDPWMDecreaseCycle.setPeriod(42);
  greenLEDPWMDecreaseCycle.start(255);
}

/*
 * This function is called to increase the PWM of the green LED
 */
void increaseGreenLEDPWM()
{
  pwmGreenLED++;
  analogWrite(pinGreenLED, pwmGreenLED);
}

/*
 * This function is called to decrease the PWM of the green LED
 */
void decreaseGreenLEDPWM()
{
  pwmGreenLED--;
  analogWrite(pinGreenLED, pwmGreenLED);
}

void setup() {
  pinMode(pinGreenLED,OUTPUT);
  pwmGreenLED = 0;
  analogWrite(pinGreenLED,pwmGreenLED);

 
  greenLEDCycle.at(27000,startPWMIncrease);     /* at 7:30 */
  greenLEDCycle.at(34200,startPWMDecreaseSlow); /* at 9:30 */
  greenLEDCycle.at(63000,startPWMIncrease);     /* at 17:30 */
  greenLEDCycle.at(75600,startPWMDecreaseFast); /* at 21:00 */
 
  greenLEDPWMIncreaseCycle.at(0,increaseGreenLEDPWM);
  greenLEDPWMDecreaseCycle.at(0,decreaseGreenLEDPWM);
 
  greenLEDCycle.start();
}

void loop() {
  // put your main code here, to run repeatedly:
  ScheduleTable::update();
}
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le mai 17, 2015, 11:58:21 pm
Bonsoir à tous,
  Je reprends un peu l'Arduino et mon projet.
  J'ai relu les pages du forum, les observations et les commentaires de chacun et j'ai repensé mon projet dans ce sens :
  Je vous joints le synoptique modifié. Quelques observations explicatives:
  - Toujours une carte sous chaque module. Elle commande les différents éclairages, les aiguillages,etc...
  - L'éclairage général des modules est confié à une carte ( via des mosfets de puissance) qui gère aussi l'affichage.
  - Une carte Horloge déjà faite.
  - L'Alim est assurée par une alimentation de PC ( le 5v ne sert que pour des petits lecteurs MP3)
  - Eventuellement, je peux rajouter des cartes d'extension si le besoin de broches se fait sentir (en I2c).
 J'ai prévu quatre boutons : 2(incrémentation et decrémentation) pour sélectionner différents programmes signalés par 8 leds.
 1 bouton de validation et 1 bouton que j'appelle programmation ( j'ai imaginé pouvoir changer directement quelques variables sans passer par l'ordinateur).
  - Un Afficheur 4*20 en I2c permet d'afficher les indications et messages dont j'aurai besoin.
Avant de commencer mes cartes, j'aurai aimé avoir vos avis, voir si c'est réaliste .
 J'ai dessiné un mini sur mes cartes mais ne vaut-il pas mieux mettre un nano qui a la liaison USB ( j'en ai vu un chez Electrodragon pas très cher mais le micro-controleur n'ait pas le même que sur la carte Arduino uno,est-ce gênant?)
  J'ai testé mes boutons sur une entrée analogique, ça a l'air de bien marcher. J'ai testé aussi l'afficheur avec une bibliothèque,
l'affichage scintille... J'ai vu sur des sites qu'il faut mettre des résistances de rappel au +, je vais essayer.
  Voilà, j'arrête là mon bavardage...
Je n'arrive pas à passer mon fichier image, j'ai un message qui me dit qu'il est trop gros, pourtant il ne fait que 106k, désolé....
 
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le mai 18, 2015, 01:35:47 pm
Voilà le croquis
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le décembre 28, 2015, 10:58:50 pm
Bonjour,
Je sais que Jean Luc est très pris, aussi, j'espère que quelqu'un d'autre pourra répondre à mon questionnement...
Voilà, je travaille sur les "ScheduleTable". J'ai bien compris comment tout cela marchait pour des sorties digitales.
Pour les sorties PWM, on crée la Table principale(nbre d'actions,nbre de périodes), puis on crée des Tables filles pour la montée et la descente de la PWM. Pour définir le nbre de périodes, il divise la durée de montée ou de descente souhaitée par 255 ( surement la valeur max de la PWM).
On a donc:
ScheduleTable greenLEDPWMIncreaseCycle(1,28);    // 1 action, period duration = 7200 / 255 = 28
ScheduleTable greenLEDPWMDecreaseCycle(1,42);// 1 action, period duration = 10800 / 255 =42
mais, après, dans ces fonctions, il démarre ses Tables avec 255 périodes imposées. Pouquoi?
Voilà, si quelqu'un peut m'éclairer.
A part cette incompréhension, c'est un plaisir de se servir de ces tables . J'ai vu qu'on peut démarrer les Tables ailleurs que dans le setup(), il faut que j'essaye de les démarrer avec des boutons ( on pourra ainsi choisir différents choix d'animation). 
 
Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le janvier 01, 2016, 07:50:11 pm
Bonsoir et meilleurs vœux pour 2016.

Le but est de passer de 0 à 255 sur une durée de T. On calcule donc l'intervalle de temps entre deux augmentations (ou diminutions) de 1. C'est T/255. En effectuant ceci 255 fois, on passe de 0 à 255 (ou l'inverse) et ça dure T. C'est pourquoi la ScheduleTable est lancée pour 255 cycles.
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le janvier 06, 2016, 07:17:19 pm
Tout d'abord merci pour tes vœux. A mon tour, je souhaite à toute l'équipe une Bonne et Chaleureuse Année 2016 avec beaucoup de joie à manipuler les Arduinos et les petits trains.
Pour les ScheduleTables, bravo et merci: C'est très pratique...
J'avais trouvé entre-temps l'explication pour les montées/descente de la PWM.
Dans un programme plus important, (mais je pense qu'il n'y aura pas de problème, il faut juste que j'essaye..), je peux démarrer les ScheduleTables dans un switch(compteur)....case:0...1....x...., le compteur étant incrémenter par un BP.
Ça me permettra d'avoir plusieurs animations lumineuses sur mon réseau.   
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le janvier 16, 2016, 12:36:34 am
Suite de mon projet et plein de problème que je ne sais pas comment résoudre, si une bonne âme pouvait me venir en aide...
Je rappelle brièvement mon projet, toujours le même: je voudrais commander l'éclairage de mon réseau par des bandeaux de ledsRGB et blanc chaud commandés eux-mêmes par un arduino+ des MOSFETS.
J'aimerai avoir plusieurs programmes ( chaude journée d'été, dans le froid de l'hiver, jour et nuit , maintenance, etc..)
Je compte utiliser les ScheduleTable et aussi une machine à état qui, dans le principe me parait simple...
J'ai testé un premier programme et rien ne marche comme je l'avais imaginer.
Je n'arrive pas à démarrer les Tables dans la machine.
La machine à états marche très mal:
La commande d'extinction des leds (for(byte i;i<7;i++){digitalWrite(leds,LOW);}) est inopérante
Je ne peux pas passer d'un programme à un autre...
Je pense avoir fait pas mal d'erreurs, si vous pouviez me mettre sur la voie
/********************************BIBLIOTHEQUE UTILE POUR GERER LES BOUTONS**********************/
#include <RBD_Timer.h> 
#include <RBD_Button.h>
/********************************BIBLIOTHEQUE POUR LE CHENILLARD*******************************/
 #include <ScheduleTable.h>
  ScheduleTable Chenillard(12,12,200);// création de la table : 12 actions, 12 périodes de 200ms.
/********************************DECLARATION DES ETATS DE LA MACHINE***************************/

enum{INITIAL, ATTENTEPROG1, PROG1, ATTENTEPROG2, PROG2, ATTENTEPROG3, PROG3, ATTENTEPROG4, PROG4,
 ATTENTEPROG5, PROG5, ATTENTEPROG6, PROG6, ATTENTEPROG7, PROG7,};
 int etat = INITIAL;
/******************************DECLARATION DES BROCHES POUR LES LEDS TEST**********************/

byte leds[] = {2,4,7,8,11,12,13};
/*******************************CONSTRUCTEUR POUR LES BOUTONS**********************************/

RBD::Button boutonIncrementation(17, false);
RBD::Button boutonValidation(16, false);
RBD::Button boutonDecrementation(15, false);
RBD::Button boutonReset(14, false);
boolean etatVal = 0;                          // Variable pour la validation
boolean ancienEtatVal = 0;                    // Précédent état de la validation
byte compteur=0;                              // Compteur des différents programmes
const byte valeurMin=0;                       // Valeur minimum du compteur
const byte valeurMax=7;                       // Valeur maximum du compteur
/******************************INITIALISATION**************************************************/

void setup() {
    Serial.begin(9600);
    for(int i=0;i<7;i++){
    pinMode(leds[i],OUTPUT);
    }
    Chenillard.at(1,Chenillard1);
    Chenillard.at(2,Chenillard2);
    Chenillard.at(3,Chenillard3);
    Chenillard.at(4,Chenillard4);
    Chenillard.at(5,Chenillard5);
    Chenillard.at(6,Chenillard6);
    Chenillard.at(7,Chenillard7);
    Chenillard.at(8,Chenillard8);
    Chenillard.at(9,Chenillard9);
    Chenillard.at(10,Chenillard10);
    Chenillard.at(11,Chenillard11);
    Chenillard.at(12,Chenillard12);
   

}
/*****************************LOOP*************************************************************/

void loop() {
/**************************TEST DES BOUTONS****************************************************/

  if(boutonIncrementation.onPressed()){if(compteur< valeurMax)compteur++;}
  if(boutonDecrementation.onPressed()){if(compteur>valeurMin)compteur--;}
  if(boutonValidation.onPressed()){etatVal=!etatVal;}
  Serial.print("compteur :   ");
  Serial.println(compteur);
  Serial.print("Validation :      ");
  Serial.println(etatVal);
/****************************MACHINE A ETAT****************************************************/
  switch (etat){
    case INITIAL:                                        // Dans cet état, il n'y a qu'un motif
         for(byte i;i<7;i++){digitalWrite(leds[i],LOW);} // qui défile sur la rangée de leds
         Chenillard.start();               // En attente du compteur pour choisir
         if(compteur==1){etat=ATTENTEPROG1;}             // le programme à jouer.
    break;
    case ATTENTEPROG1:                                   // Le programme 1 est en attente de
         for(byte i;i<7;i++){digitalWrite(leds[i],LOW);} // validation.La led 1 clignote.
         Clignote(0);
         if(etatVal!=ancienEtatVal){etat=PROG1;}
    break;
    case PROG1:                                          // Le programme est validé. la led 1
         for(byte i;i<7;i++){digitalWrite(leds[i],LOW);} // est allumée. La validation est
         digitalWrite(leds[0],HIGH);                     // remise à zéro et le programme 1 se
         etatVal=ancienEtatVal;                          // déroule.
         //programme1
         if(compteur==2){etat=ATTENTEPROG2;}
    break;
    case ATTENTEPROG2:                                   // idem pour le programme2...
         for(byte i;i<7;i++){digitalWrite(leds[i],LOW);}
         Clignote(1);
         if(etatVal!=ancienEtatVal){etat=PROG2;}
    break;
    case PROG2:
         for(byte i;i<7;i++){digitalWrite(leds[i],LOW);}
         digitalWrite(leds[1],HIGH);
         etatVal=ancienEtatVal;
         //programme2
         if(compteur==3){etat=ATTENTEPROG3;}
    break;
    case ATTENTEPROG3:                                   // idem pour le programme3...
         for(byte i;i<7;i++){digitalWrite(leds[i],LOW);}
         Clignote(2);
         if(etatVal!=ancienEtatVal){etat=PROG3;}
    break;
    case PROG3:
         for(byte i;i<7;i++){digitalWrite(leds[i],LOW);}
         digitalWrite(leds[2],HIGH);
         etatVal=ancienEtatVal;
         //programme3
         if(compteur==4){etat=ATTENTEPROG4;}
    break;
    case ATTENTEPROG4:                                   // idem pour le programme4...
         for(byte i;i<7;i++){digitalWrite(leds[i],LOW);}
         Clignote(3);
         if(etatVal!=ancienEtatVal){etat=PROG4;}
    break;
    case PROG4:
         for(byte i;i<7;i++){digitalWrite(leds[i],LOW);}
         digitalWrite(leds[3],HIGH);
         etatVal=ancienEtatVal;
         //programme4
         if(compteur==5){etat=ATTENTEPROG5;}
    break;
    case ATTENTEPROG5:                                   // idem pour le programme5...
         for(byte i;i<7;i++){digitalWrite(leds[i],LOW);}
         Clignote(4);
         if(etatVal!=ancienEtatVal){etat=PROG5;}
    break;
    case PROG5:
         for(byte i;i<7;i++){digitalWrite(leds[i],LOW);}
         digitalWrite(leds[4],HIGH);
         etatVal=ancienEtatVal;
         //programme5
         if(compteur==6){etat=ATTENTEPROG6;}
    break;
    case ATTENTEPROG6:                                   // idem pour le programme6...
         for(byte i;i<7;i++){digitalWrite(leds[i],LOW);}
         Clignote(5);
         if(etatVal!=ancienEtatVal){etat=PROG6;}
    break;
    case PROG6:
         for(byte i;i<7;i++){digitalWrite(leds[i],LOW);}
         digitalWrite(leds[5],HIGH);
         etatVal=ancienEtatVal;
         //programme6
         if(compteur==7){etat=ATTENTEPROG7;}
    break;
    case ATTENTEPROG7:                                   // idem pour le programme7...
         for(byte i;i<7;i++){digitalWrite(leds[i],LOW);}
         Clignote(6);
         if(etatVal!=ancienEtatVal){etat=PROG1;}
    break;
    case PROG7:
         for(byte i;i<7;i++){digitalWrite(leds[i],LOW);}
         digitalWrite(leds[6],HIGH);
         etatVal=ancienEtatVal;
         //programme7
         if(compteur==6){etat=ATTENTEPROG6;}
    break;
   
   
  }


}
void Clignote(byte numLed){
  //for(byte i;i<7;i++){digitalWrite(leds[i],LOW);}
  digitalWrite(leds[numLed],millis()/200%2);
}
/*                         Quand aucun programme est appelé, les leds clignotent suivant le mode chenillard:
 * allumé=x    eteint=-                               ORDRE D'ALLUMAGE DES LEDS
 *                   
 *        actions  :  0(led2)  :  1(led4)  :  2(led7)  :  3(led8)  :  4(led11)  :  5(led12)  :  6(led13)  :  périodes
 *        -----------------------------------------------------------------------------------------------------------
 *           1     :     x     :     -     :     -     :     -     :      -     :      -     :     -      :     1
 *           1     :     -     :     x     :     -     :     -     :      -     :      -     :     -      :     2
 *           1     :     -     :     -     :     x     :     -     :      -     :      -     :     -      :     3
 *           1     :     -     :     -     :     -     :     x     :      -     :      -     :     -      :     4
 *           1     :     -     :     -     :     -     :     -     :      x     :      -     :     -      :     5
 *           1     :     -     :     -     :     -     :     -     :      -     :      x     :     -      :     6
 *           1     :     -     :     -     :     -     :     -     :      -     :      -     :     x      :     7
 *           1     :     -     :     -     :     -     :     -     :      -     :      x     :     -      :     8
 *           1     :     -     :     -     :     -     :     -     :      x     :      -     :     -      :     9
 *           1     :     -     :     -     :     -     :     x     :      -     :      -     :     -      :     10
 *           1     :     -     :     -     :     x     :     -     :      -     :      -     :     -      :     11
 *           1     :     -     :     x     :     -     :     -     :      -     :      -     :     -      :     12
 */




 void Chenillard1(){digitalWrite(leds[0],HIGH);digitalWrite(leds[1],LOW);}  //Les fonctions qui définissent les actions
 void Chenillard2(){digitalWrite(leds[1],HIGH);digitalWrite(leds[0],LOW);}  //de la Table.
 void Chenillard3(){digitalWrite(leds[2],HIGH);digitalWrite(leds[1],LOW);}
 void Chenillard4(){digitalWrite(leds[3],HIGH);digitalWrite(leds[2],LOW);}
 void Chenillard5(){digitalWrite(leds[4],HIGH);digitalWrite(leds[3],LOW);}
 void Chenillard6(){digitalWrite(leds[5],HIGH);digitalWrite(leds[4],LOW);}
 void Chenillard7(){digitalWrite(leds[6],HIGH);digitalWrite(leds[5],LOW);}
 void Chenillard8(){digitalWrite(leds[5],HIGH);digitalWrite(leds[6],LOW);}
 void Chenillard9(){digitalWrite(leds[4],HIGH);digitalWrite(leds[5],LOW);}
 void Chenillard10(){digitalWrite(leds[3],HIGH);digitalWrite(leds[4],LOW);}
 void Chenillard11(){digitalWrite(leds[2],HIGH);digitalWrite(leds[3],LOW);}
 void Chenillard12(){digitalWrite(leds[1],HIGH);digitalWrite(leds[2],LOW);}
Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le janvier 16, 2016, 01:14:22 am
Bonsoir,

Rapidement (trop fatigué pour étudier en détails) il manque l'appel

ScheduleTable::update();

Dans loop()

C'est pour ça que la Schedule table ne fonctionne pas.

Je regarde le reste demain.
Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le janvier 16, 2016, 09:56:53 am
2 autres choses :

La variable ancienEtatVal n'est jamais affectée (sauf à l'initialisation). Par conséquent, une pression de bouton sur 2 sera vue

Dans tous les case, les leds sont éteintes. Par conséquent elles sont éteintes en permanence car leur allumage est très fugace.
Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le janvier 17, 2016, 11:35:10 pm
merci pour cette réponse rapide. Je m'y recolle mais c'est pas gagné....
Que c'est dur la programation....
Titre: Re : Un Arduino par module....ou pas.
Posté par: Jean-Luc le janvier 18, 2016, 10:07:49 am
Une simplification consisterait à utiliser une variable booléenne à la place des variables etatVal et ancienEtatVal. Car en fait la bibliothèque RBD_button intégre déjà cette mémorisation de son état précédent. Appelons cette variable 'ok'. Au lieu d'inverser etatVal et de retenir sa valeur précédente, il suffit d'écrire dans loop :

bool ok = boutonValidation.onPressed();

Puis à chaque fois que vous testiez la différence entre etatVal et ancienEtatVal :

if (ok) { ... }


Titre: Re : Un Arduino par module....ou pas.
Posté par: petitrain le janvier 19, 2016, 08:26:24 pm
Merci pour l'aide, surtout le if(OK){.....} je n'aurai jamais pensé l'écrire comme ça. Ça marche très bien. Par contre j'ai abandonné la machine à état, je ne m'en sortais pas. Je pensai avoir absorbé la théorie, mais, dans la pratique, ça s'avère plus difficile à mettre en œuvre . J'ai fait un switch(compteur)....avec des case:1,2,3,....et dans chaque case un clignote() de la led concernée et un if(OK){on change la valeur d'une variable programme=1,2,3... } puis un autre switch(programme) avec des case: programme1, programme2...
Il  me reste a mettre tous les programmes à écrire pour que mon éclairage du réseau voie enfin le jour.
Par contre, je n'arrive pas  à faire démarrer les ScheduleTables depuis mon switch. Je suis obligé de mettre .....start() dans le setup, et quand le programme arrive sur ScheduleTable::uptade (), là, elle se met en route. Donc, si j'en aie plusieurs, elles vont toutes se mettre en route ....