Homeduino : E/S pour la Domotique via Box

Bonjour à tous,

Alors je vais vous présenter l'un de mes petit projet.
Il n'est pas très compliqué mais je suis sûr qu'il pourra servir à certain.

Préambule :
Je remercie avant tout, tous les personnes qui ont pu contribuer à l'avancement de mes projets. :slight_smile:
Je pense particulièrement à Skywodd pour son blog (Skywodd | Skyduino - Le DIY à la française) très riche :grin: . Mais aussi le site http://www.sonelec-musique.com/ qui regorge de montages élec super bien expliqués. Merci aussi à ceux qui publient leur réal ça aide bien au début. J'en oubli sûrement...

Description :
Donc mon projet est relativement simple. L'objectif est d'avoir des Entrées/Sorties pour la domotique le moins cher possible et le plus flexible possible. Si en plus c'est pas trop prise de tête et que ça demande pas un gros investissement (coût et temps) super ! Donc avec tout ça je me suis dirigé vers une solution Arduino.
Je ne veux pas tirer des câbles partout mais je ne suis pas fan non plus des radio fréquences.
Donc pour moi l'idéal est la communication via les prises ethernet.
Voilà donc pour faire simple : Arduino Uno(ou Mega) + Shield Ethernet !

J'ai donc une box domotique (Zibase) avec laquelle je commande ou lis mon arduino via des commandes http. L'arduino renvoie toujours un xml avec les infos importantes. L'arduino est aussi capable de commaner via pushingbox ou directement la zibase. (non utilisé encore dans ce programme)

Dans mon cas présent j'ai installé des spots sur tout le tour de la maison [en cours pas fini l'avant]. Je veux pouvoir commandé l'allumage de chaque spot indépendamment. J'utilise donc une carte Relais à 16 Relais. (sainsmart)
Avec une Uno ça condamne bcp de ports donc j'ai choisi d'utiliser 2 74HC595 pour les relais.

La commande indépendante des spots me permet de faire des chenillard extérieur !!! Un vrai sapin de noel la maison. ça permet aussi de faire un retour d'état de l'alarme en cas d'alerte.

Par rapport à la situation géographique de l'installation, j'en profite pour mesurer la température du ballon d'eau chaude de la chaudière fuel. Mais aussi pour détecter lorsque le brûleur de la chaudière est en fonctionnement. Pour cela je détecte la présence de 230V au brûleur.
L'objectif final est savoir par jour la conso en fuel et donc le coût. (Les infos brutes sont envoyé sur un MySQL ensuite c'est tout un site en php qui s'occupe de faire les calculs et qui affiche les graphiques via highcharts )

Je ne suis pas développeur. Je suis ingénieur, j'ai des bases un peu partout mais un peu quoi !
Donc mon code est très certainement à optimiser.

C'est d'ailleurs aussi ça qui est important dans le partage donnant/donnant.

Perspectives :
Etant sur un Arduino Uno ça limite quand même pas mal le prog. Je ferai une présentation d'un autre de mes projet identique : La gestion de mon portail/sonnette/Boite au Lettres/Autres. Sauf que j'ai mis un ici un Mega qui me laisse bcp plus de marge.

Pour celui ci, à court terme je doit rajouter un inter poussoir (déjà présent dans la maison) pour commander les spots sans passer par la box domotique. (Telephone, Telco ou Scénarios)

Sur le long terme, je prévoit chez moi de recâbler l’ensemble des éclairages. Tout câbler en étoile sur des relais (via des interrupteurs surement). Idem tout les inter en poussoir câblés sur l'arduino. Ensuite la programmation permettra de faire ce qu'on veux avec les inter. Une gestion multi-clic est aussi envisageable.

Détails techniques :

  • Entrés :
  • Etat brûleur via un montage élec (je détaillerai plus tard) (redresseur, résistance, diode, optocoupleur)
  • Température avec DS18B20 moulé/câblé (Recommendations For You - DealeXtreme)
  • Sorties :
  • Led verte (Elle clignote en permanence via le code) pour savoir si le code est planté
  • 16 Relais via 3 fils avec les 74HC595

Le code :

Cette dernière version du code est en bêta car je teste une simplification pour les chenillard. Avant j'avais fait une fonction par chenillard en faisant des boucles for bien faites. La j'ai choisi de passer par des tableau avec l'etat direct des spots. C'est plus flexible et moins prise de tête.

Par contre j'ai bien gagné sur le poids du programe (74% de l'Uno) mais par contre j'ai perdu sur la RAM dispo. Je pense que je ne gère pas bien du tout les tableau chenillards (hisoitre de const et pointeurs ?)
Bref il y a une optimisation à faire.

Skywodd je sais qu'il faut pas utiliser des 'String' mais j'ai pas réussi à les remplacer par des char, ça compile pas. J'ai pas réussi a débuger.

Les commandes http :
http://192.168.0.01/?SpotsExAr/All/On
http://192.168.0.01/?SpotsExAr/All/Off
http://192.168.0.01/?SpotsExAr/All/ProgOn/DR
http://192.168.0.01/?SpotsExAr/All/ProgOn/DL
http://192.168.0.01/?SpotsExAr/All/ProgOn/GR
http://192.168.0.01/?SpotsExAr/All/ProgOn/GL
http://192.168.0.01/?SpotsExAr/All/ProgOff/DR
http://192.168.0.01/?SpotsExAr/All/ProgOff/DL
http://192.168.0.01/?SpotsExAr/All/ProgOff/GR
http://192.168.0.01/?SpotsExAr/All/ProgOff/GL
http://192.168.0.01/?SpotsExAr/All/C1
http://192.168.0.01/?SpotsExAr/All/C2
http://192.168.0.01/?SpotsExAr/All/C3
http://192.168.0.01/?SpotsExAr/All/C4
http://192.168.0.01/?SpotsExAr/All/C5
http://192.168.0.01/?SpotsExAr/All/C6
http://192.168.0.01/?SpotsExAr/PorteEntree/On
http://192.168.0.01/?SpotsExAr/PorteEntree/Off
http://192.168.0.01/?razEtat
http://192.168.0.01/?alerte=1
http://192.168.0.01/?alerte=0
http://192.168.0.01/?info
http://192.168.0.01/?freeMemory

Exemple de retour :

<doc ar="arduinoEclairageMaisonExterieur">
<temperatureEau>43.50</temperatureEau>
<tempEauforzibase>435.00</tempEauforzibase>
<SpotState1>0</SpotState1>
<SpotState2>0</SpotState2>
<SpotState3>0</SpotState3>
<SpotState4>0</SpotState4>
<SpotState5>0</SpotState5>
<SpotState6>0</SpotState6>
<SpotState7>0</SpotState7>
<SpotState8>0</SpotState8>
<SpotState9>0</SpotState9>
<SpotState10>0</SpotState10>
<SpotState11>0</SpotState11>
<SpotState12>0</SpotState12>
<SpotState13>0</SpotState13>
<SpotState14>0</SpotState14>
<SpotState15>0</SpotState15>
<SpotState16>0</SpotState16>
<etatBruleur>0</etatBruleur>
<freeMemory>1307</freeMemory>
<etat>OK</etat>
</doc>

Changelog
V2.2 22/01/32014
-Finalisation Alerte
-bugs dans Play corrigés
V2.3 22/01/2014
-modif taille tableau Play
-modif fonction Play avec pointeur (aucune amélioration mémoire :/)
-chenillards en PROGMEM (là un bon gain de mémoire)
V2.4 27/01/2014
-Rajout Chenillard
-Fonction carnaval
-Temperature interne
V2.5 01/02/2014
-Rajout fction repetion sur MySQL echoué
-Modif de la fction repetition sur Psuhingbox
-Modif des tempos pour sauvegarder les relais et les ampoules.
V2.6 19/03/2014
-Rajout timer pour envoie EtatBruleur (periode 5min)

V3 21/07/2014
-Rajout fonction spots On/Off Forcé
-Modif Off si déjà Off et On si déjà On !! ( CompareAllSpots(1) renvoie 1 si un ou plus des spots est different de l'ancien état. )
-Desactivation Pushingbox & Zibase Scenario
-Alerte Corrigé
V3.1 26/09/2014
-Rajout F() sur Etat
-Modif PulseLed 'fonction'
-BugFix : MySQL lastmillis

Chenillards.h (2.97 KB)

Homeduino_3.ino (19.1 KB)

Bonjour,

Très intéressant. Je n'y connais rien en brûleur: si je comprends bien, à partir du moment où il fonctionne, le débit de carburant est toujours le même et donc il te suffit de mesurer le temps de fonctionnement pour connaître la consommation ?

Oui grosomodo le débit est le même temps qu'il fonctionne.
C'est une approx mais ça donne un bon ordre d'idée je pense.

Photos :

Mise en place de l'ensemble dans un boitier type tableau disjoncteur avec porte plexi :

Montages :

A Venir.

J'ai donc une question pour optimiser le code :

C'est sur la fonction play :

void Play(const boolean TableauSpot[][9], long delai, boolean onoff)
{
  int tailleBoucle = sizeof(TableauSpot)/sizeof(boolean);
  for(int i=0;i<=tailleBoucle;i++){
   for(int l=0;l<=15;l++){
     onoff ? SpotState[i]=TableauSpot[i][l] : SpotState[i]=!TableauSpot[i][l];
   }
   SpotsUpdate();
   delay(delai);
  }
}

Je déclare des tableau ensuite :

const boolean chenillard1[5][9]={
{1,0,0,0,0,0,0,0,1},
{1,1,0,0,0,0,0,1,1},
{1,1,1,0,0,0,1,1,1},
{1,1,1,1,0,1,1,1,1},
{1,1,1,1,1,1,1,1,1}};

Il ne vont pas changer pendant le code eux.

J'appel la fonction par :

Play(chenillard1,250,1)

Plus j'appel la fonction plus je perd de mémoire :

Actuellement j'ai :

Le croquis utilise 24 216 octets (75%) de l'espace de stockage de programmes. Le maximum est de 32 256 octets.
Les variables globales utilisent 1 168 octets (57%) de mémoire dynamique, ce qui laisse 880 octets pour les variables locales. Le maximum est de 2 048 octets.

Si j’enlève les appels de la fonction play (qui prend en paramètre un tableau) :

Le croquis utilise 23 452 octets (72%) de l'espace de stockage de programmes. Le maximum est de 32 256 octets.
Les variables globales utilisent 744 octets (36%) de mémoire dynamique, ce qui laisse 1 304 octets pour les variables locales. Le maximum est de 2 048 octets.

Quelqu'un à une explication ? Comment améliorer le truc ?
Merci :wink:

Bon j'avais quelques petites erreurs dans ma fonction play. Celle ci fonctionne :

void Play(const boolean TableauSpot[][9], long delai, boolean onoff, int tailleBoucle)
{
  //int tailleBoucle = sizeof(TableauSpot)/sizeof(boolean);
  
  for(int i=0;i<tailleBoucle;i++){
   for(int s=0;s<=8;s++){
     //onoff ? SpotState[l]=TableauSpot[i][l] : SpotState[l]=!TableauSpot[i][l];
     if(onoff){
       SpotState[s]=TableauSpot[i][s];
     }else{
       SpotState[s]=!TableauSpot[i][s];
     }
   }
   SpotsUpdate();
   delay(delai);
  }
}

Par contre j'ai du passer en paramètre la taille du tableau. A cause encore une fois d'une histoire de pointeur je pense.
Le int tailleBoucle = sizeof(TableauSpot)/sizeof(boolean); dans la fonction ne fonctionne pas.

Mon prog fonctionne bien mais actuellement il me laisse seulement 590 de Ram (freeMemory). J'aimerai trouver comment utiliser la méthode des tableau à deux dimension sans pourrir la mémoire.
Des pistes ?

PS: je met à jour les fichier du code

Ok, j'ai réussi avec les pointeurs mais ça ne libère pas ma mémoire dynamique pour autant :stuck_out_tongue_closed_eyes: :

Voici un code 'type' qui marche :

const boolean chenillard1[5][9]={ //chenillard1[][9] marche aussi
{1,0,0,0,0,0,0,0,1},
{1,1,0,0,0,0,0,1,1},
{1,1,1,0,0,0,1,1,1},
{1,1,1,1,0,1,1,1,1},
{1,1,1,1,1,1,1,1,1}};

#define sizeTab(array) (sizeof(array)/sizeof(*array))

boolean SpotState[16];

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
 Play(*chenillard1,sizeTab(chenillard1),0); 
 Play(*chenillard1,sizeTab(chenillard1),1);
}

void Play(const boolean *TableauSpot, int tailleBoucle, int state) //TableauSpot[][9]
{
  //int tailleBoucle = sizeof(TableauSpot)/sizeof(boolean);
  
  for(int i=0;i<tailleBoucle;i++){
   for(int j=0;j<=8;j++){
     SpotState[j]=*(TableauSpot+((i*8)+j));
   }
  }
}

Bon je vais m'atteler à passer par PROGMEM...

Bon j'attire pas les foules on dirait ! :cold_sweat:

Quoi qu'il en soit j'ai réussit à faire ce que je voulais avec PROGMEM.

ça doit être encore optimisable mais là j'occupe 36% de RAM du Uno, ça me va bien.

Je doit encore changer les String en char et peut-être passer les chenillards en 2 bytes plutôt que en 16 boolean qui occupent au final plus de place. Si je dit pas de conneries.

J'ai mi à jour le code.

Xiboard:
Bon j'attire pas les foules on dirait ! :cold_sweat:

bonjour
tu es dans la section realisations et projets finis avec une balise [en cours] :grin:
c'est pas le meilleur endroit pour avoir de l'aide 8)

Bah oui, c'est une réalisation ! :stuck_out_tongue:

Je vais virer le [en cours] je pense, maintenant elle est fonctionnelle et c'est seulement des évolutions qui vont suivre.

J'espère que mon partage peu servir à d'autres.

Voilà, c'est finalisé pour le moment.
Ca tourne nickel.

Je ferai un retour de mon montage de détection du 230V. (et aussi sur le topic dédié)

Bonjour,

Très intéressé par votre projet..., aimerais realiser un mini projet domotique pour l
a gestion de l ouverture de store verticaux ou californiens dans une véranda
Avec suiveur solaire ( capteurs, moteurs, sonde de température, etc...) via un bis sur
Reseaux électrique. .., voila en gros le projet peut être un complément a d'autre (s)...?
En espérant d'avoir des retour positif... bon courage a tous...
Gilbert.

Salut,
Ton chenillard et le tableau qu'il utilise semble poser soucis ... Je pense que tu peux te passer des tableaux (qui n'évoluent pas dans le programme) en codant les étapes du chenillard dans le play et en lui passant en argument un paramètre étape qui varie de 1 a 10
Ex
Si étape = 1 allumer 1 et 9
Si étape = 2 allumer 2 et 8 ( ou inverser l'état)
Si Étape 3=3 allumer 3 et 7
Si Étape =4 allumer 4 et 6
Si Étape = 5 allumer 5
Si Étape =6 éteindre 5 ... Et ainsi de suite
...
Si étape = 10, alors étape = 1 //pour recommencer
....

Salut à tous,

Après de nombreux mois d'utilisation, ça marche impec.

J'ai encore un souci mineur : Au bout de plusieurs jours d'utilisation la LED verte ne clignote plus !
Pourtant tout marche impec mais cette LED reste bloquée allumé ou éteinte. Des fois au bout d'une heure, elle a changée d'état.
Comme si la valeur fadeAmount était autre que 1 ou -1 ! Peut-être un dépassement de mémoire provoque ça ?

La détection du 220V ne marche pas super non plus, ça coïncide peut être avec ce problème.

A voir...

Millis(): type unsigned long.
"Returns the number of milliseconds since the Arduino board began running the current program. This number will overflow (go back to zero), after approximately 50 days. "

pour liberer de la ram, tes tableaux etant fixes, passe les en Flash.
mais je vois que tu l'as deja fait.

passe un lien sur les librairies utilisées.

Bug corrigé.

J'avais bêtement oublié un " lastEtatBruleur = millis(); "
Donc l'envoie MySQL se faisait en continu ! Heureusement côté MySQL un script filtrait la reception...

Mon réseau devrait bien apprecier la mise à jour !

Les librairies sont toutes standard non customisés.

Salut , en programmation peu importe le langage on evite de faire des boucles a l' interieur d' autre boucles qui surcharge la memoire et peuvent causer une saturation evec des erreurs aleatoire de ce fait .

la parade est de creer une boucle , mettre le resultat dans une variable , puis de faire la seconde boucle avec le resultat de la premiere boucle dans la variable .

n ' etant pas programmeur je ne saurais expliqué reellement le pourquoi , ni comment faire en detail , mais on trouve ce genre de reponse sur le net en cherchant bien .

En tout cas tres joli projet , et investissement personnel , tres enrichissant pour les lecteurs .

De mon coté je suis en phase de renovation de ma maison , et me pose la question cruciale ... a savoir comment organiser et mettre en place la VDI la domotique et l' electricité , l ' alarme etc ...

pour l' alarme et l ' elec et la VDI je n' aurais pas de gros probleme pour gerer cela , pour la domotique ne m ' etant jamais encore lancé dans un quelconque projet ( personnel ) je me demandais quel type de reseau electrique mettre en place , bus ou etoile ?

Et du coup quel systeme adopter sachant que je ne veux pas mettre d ' ondes dans la maison .

Si vous avez des conseils , des retours d ' experience , des liens , des remarques , des choses que vous savez qu il ne faut pas faire , des idées des suggestions , je suis preneur .