Casa domotica con Arduino: Souliss Gateway – Nodo01

Nel progetto di casa domotica con Arduino, il Nodo01 veste la funzione di Gateway per il sistema Souliss. Questo ha il compito di leggere e pilotare tutti i nodi a lui associati e interfacciarsi con la Souliss App scaricabile dallo store di Google Play.

L’hardware utilizzato per questo nodo e una scheda Arduino Mega

con a bordo un micro Atmel ATmega2560 e per la comunicazione con gli altri nodi della rete ho utilizzato uno Ethernet shield W5100

Ethernet shield

Nel seguente disegno viene illustrata la prima bozza con descritto le varie funzioni che svolgerà il Gateway e verrà costantemente aggiornata all’ingrandirsi della rete compreso l’interfacciamento della restante rete di nodi attraverso un collegamento RS485.

Nodo01
Nodo01
Hardware.

L’hardware necessario, come appena descritto, è composto dalla scheda Arduino Mega e dalla Ethernet shield ed è sufficiente montarle tra loro come in figura qui sotto, poi va collegata alla rete LAN del Router Adsl o Switch che sia, con un cavo Ethernet ed alimentata.

mega + ethernet
mega + ethernet
 Software.

Come iniziare e cosa avere installato su pc per programmare e sviluppare il progetto?
La prima cosa da fare è installare il software per programmare Arduino e lo trovate a questo link. Il mio consiglio ad oggi la versione da me provata e funzionante è la 1.6.3.
Secondo si deve installare la libreria di Souliss nel pacchetto di arduino e lo trovate a questo link e cliccate sul pulsante Download.

Ora scompattare il file scaricato(zip) e mettete tutti i file nella cartella ..\Arduino\libraries\Souliss\.

Ora si è pronti per programmare ed eseguire i vari test; oltre alle schede da me usate ci sono altre soluzioni possibili e la lista di hardware disponibili per Souliss la potete trovare in questa lista.

 Di seguito il listato, in continuo aggiornamento, con la spiegazione del codice:


/**************************************************************************
*
* Progetto : Nodo01 Eth - Gateway - Arduino Mega 2560 + Ethernet W5100
* Autore : DromegaWeb
* Data : Gennaio 2015 - Inizio - esito OK
* 21 Marzo 2015 - Introdotto SpeakEasy - esito OK
* 02 maggio 2015 - Aggiornato ad arduino 1.6.3
*
****************************************************************************/

// Configure the framework
#include "bconf/StandardArduino.h" // Uso un Arduino standard
#include "conf/ethW5100.h" // Uso connessione Ethernet Wiznet W5100
#include "conf/Gateway.h" // uso il nodo come Gateway Souliss

#include <SPI.h>
#include "Souliss.h"

// -------------INIZIO definizione della configurazione di rete --DromegaWeb------------------------------------
uint8_t ip_address_Gw[4] = {192, 168, 2, 11}; // indirizzo Gateway souliss su Ethernet Arduino Mega
uint8_t ip_address_E2[4] = {192, 168, 2, 12}; // indirizzo su Ethernet Nodo02
uint8_t ip_address_E3[4] = {192, 168, 2, 13}; // indirizzo su Ethernet Nodo03
uint8_t subnet_mask[4] = {255, 255, 255, 0};
uint8_t ip_gateway_Router[4] = {192, 168, 2, 10}; // indirizzo Gateway router

#define Gateway_address 11 // indirizzo ip Gateway Souliss
#define E2_address 12 // indirizzo ip su Ethernet Nodo02
#define E3_address 13 // indirizzo ip su Ethernet Nodo03
#define myvNet_address ip_address_Gw[3] // ultimo byte dell' IP address (11) è anche l'indirizzo vNet
#define myvNet_subnet 0xFF00
#define myvNet_supern 0x0000
#define myvNet_supern_E2 Nodo02_address_Gateway_RS485_01
#define myvNet_supern_E3 Nodo03_address_Gateway_RS485_02

#define Nodo02_address_Gateway_RS485_01 0xCE01 // Indirizzo Nodo02 bridge01 della Seriale RS485
#define Nodo04_address_peer01_Gw_01 0xCE02 // Indirizzo Nodo04 peer01 su bridge01 remota Seriale RS485
#define Nodo05_address_peer02_Gw_01 0xCE03 // Indirizzo Nodo05 peer02 su bridge01 remota Seriale RS485

#define Nodo03_address_Gateway_RS485_02 0xCE11 // Indirizzo Nodo03 bridge02 della Seriale RS485
#define Nodo06_address_peer01_Gw_02 0xCE12 // Indirizzo Nodo06 peer01 su bridge02 remota Seriale RS485
#define Nodo07_address_peer02_Gw_02 0xCE13 // Indirizzo Nodo07 peer02 su bridge02 remota Seriale RS485
#define Nodo08_address_peer03_Gw_02 0xCE14 // Indirizzo Nodo08 peer03 su bridge02 remota Seriale RS485

// -------------FINE definizione della configurazione di rete --DromegaWeb------------------------------------

// Indirizzo MAC per Scheda Ethernet Nodo01
#define MAC_INSKETCH const uint8_t MAC_ADDRESS[] = { 0x1A, 0xA6, 0x49, 0x6B, 0xBF, 0xBA}; 

#define LED_O_N1 0 // This is the memory slot for the logic that handle the light
#define LED_1_N1 1
#define LED_2_N1 2
#define LED_3_N1 3
#define LED_4_N1 4
#define LED_5_N1 5

void setup()
{
 Initialize();
 // Set parametri network
 Souliss_SetIPAddress(ip_address_Gw, subnet_mask, ip_gateway_Router); // Questo nodo sarà --> 192.168.2.11
 SetAsGateway(myvNet_address); // Questo nodo è Gateway Souliss app
 SetAsPeerNode(E2_address, 1); // definisco Nodo02 --- Eth + brige01 RS485
 SetAsPeerNode(Nodo04_address_peer01_Gw_01, 2); // definisco Nodo04 peer01 su bridge01
 SetAsPeerNode(Nodo05_address_peer02_Gw_01, 3); // definisco Nodo05 peer02 su bridge01

 // Set the typical
 Set_T11(LED_O_N1);
 Set_T11(LED_1_N1);
 Set_T11(LED_2_N1);
 Set_T11(LED_3_N1);
 Set_T12(LED_4_N1);
 Set_T12(LED_5_N1);

 // Define inputs, outputs pins
 pinMode(2, INPUT); // Hardware pulldown required
 pinMode(3, INPUT);
 pinMode(4, INPUT);
 pinMode(5, INPUT);
 pinMode(6, INPUT);
 pinMode(7, INPUT);

 pinMode(8, OUTPUT); // Power the LED
 pinMode(9, OUTPUT);
 pinMode(10, OUTPUT);
 pinMode(11, OUTPUT);
 pinMode(12, OUTPUT);
 pinMode(13, OUTPUT);
}

void loop()
{
 EXECUTEFAST() {
 UPDATEFAST();

 FAST_30ms() {
 // Usa PinX per cambiare lo stato
 DigIn(2, Souliss_T1n_ToggleCmd, LED_O_N1);
 DigIn(3, Souliss_T1n_ToggleCmd, LED_1_N1);
 DigIn(4, Souliss_T1n_ToggleCmd, LED_2_N1);
 DigIn(5, Souliss_T1n_ToggleCmd, LED_3_N1);
 DigIn(6, Souliss_T1n_ToggleCmd, LED_4_N1);
 DigIn(7, Souliss_T1n_ToggleCmd, LED_5_N1);

 // Esegue la logica che gestisce i LED
 Logic_T11( LED_O_N1);
 Logic_T11( LED_1_N1);
 Logic_T11( LED_2_N1);
 Logic_T11( LED_3_N1);
 Logic_T12( LED_4_N1);
 Logic_T12( LED_5_N1);

 // Usa PinX per alimentare e accendere i LED
 DigOut(8, Souliss_T1n_Coil, LED_O_N1);
 DigOut(9, Souliss_T1n_Coil, LED_1_N1);
 DigOut(10, Souliss_T1n_Coil, LED_2_N1);
 DigOut(11, Souliss_T1n_Coil, LED_3_N1);
 DigOut(12, Souliss_T1n_Coil, LED_4_N1);
 DigOut(13, Souliss_T1n_Coil, LED_5_N1);
 }
 FAST_GatewayComms(); //Qui elaboriamo tutte le comunicazioni con altri nodi la Souliss App

 }
 EXECUTESLOW() {
 UPDATESLOW();
 SLOW_10s() { // Gestiamo il timer luce con un tempo di base di 10 secondi
 Timer_T11( LED_O_N1);
 Timer_T11( LED_1_N1);
 Timer_T11( LED_2_N1);
 Timer_T11( LED_3_N1);
 Timer_T12( LED_4_N1);
 Timer_T12( LED_5_N1);
 }
 }
}

Spiegazione del codice in breve:

Setup

012 – Stabilisce che l’hardware usato è la scheda di Arduino

013 – Comunica al compilatore che lo shield montato su Arduino è in scheda Ethernet

014 – Definisce questo nodo come il nodo gateway del sistema Souliss con il quale si interfaccia la Souliss App sullo smartphone o tablet. Questo settaggio nella rete Souliss deve comparite una sola volta in quanto la Souliss App si aggancia ad un solo gateway.

016-017 – Libreria Souliss da inserire sempre.
020 – Definisco l’indirizzo IP del Nodo01, Arduino Gateway, questo nodo per intenderci.
021 – Definisco l’indirizzo IP del Nodo02 altra scheda arduino con modulo shield Ethernet.
022 – Definisco l’indirizzo IP del Nodo03 altra scheda arduino con modulo shield Ethernet.
023 – Definizione della subnet mask, tipico parametri presente in tutte le reti dati ethernet.
024 – Definisco l’indirizzo IP del Router o modem router che funge da gateway sulla propria rete per l’accesso a internet.
026-033 – Definizione indirizzi vNet.
035 – Definisco l’indirizzo del ponte per la prima linea di RS485 sul Nodo02
036 – Definisco l’indirizzo del peer Nodo04 per la prima linea di RS485
037 – Definisco l’indirizzo del peer Nodo05 per la prima linea di RS485
039 – Definisco l’indirizzo del ponte per la seconda linea di RS485 sul Nodo03
040 – Definisco l’indirizzo del peer Nodo06 per la seconda linea di RS485
041 – Definisco l’indirizzo del peer Nodo07 per la seconda linea di RS485
042 – Definisco l’indirizzo del peer Nodo08 per la seconda linea di RS485
047 – Definisco il MAC nello sketch.
049-054 – Definisco i 6 LED come slot
058 – inizializza la mappa di memoria degli slot Souliss
060 – Setta l’indirizzo IP del Nodo01, Arduino Gateway.
061 – Setto questo nodo come Gateway di Souliss App, da fare solo su questo nodo della rete( va settato solo una volta.)

062-063 – In queste righe vengono settati i nodi peer di tutta le rete Souliss, in questo caso sono presenti solo i 3 nodi (Nodo02,Nodo04 e Nodo05) quelli in uso ora, in futuro verranno aggiunti anche gli altri quando pronti.

067-072 – Dei vari slot viene settato il tipico.

075-080 – Vengono definiti gli ingressi.

082-087 – Vengono definite le uscite.

Loop

La base del ciclo di sistema per i vari nodi è la seguente:

void loop()
{
EXECUTEFAST() {
UPDATEFAST();

FAST_30ms() {
-------------Definire intrusioni di in e out per Soulis---------------
}
FAST_50ms() {
-------------Definire intrusioni di in e out per Soulis---------------
}

}
EXECUTESLOW() {
UPDATESLOW();
SLOW_10s() {  // Gestiamo il timer degli slot
-------------Definire timer---------------
}
}
}

Questo è il ciclo che viene ripetuto all’infinto del nostro nodo e sono presenti nei “FAST_XXms()”  le istruzioni che vengono ripetute con maggiore frequenza e nei “SLOW_xxs()” le istruzioni che vengono ripetute con un lasso di tempo più lungo settabile anche una volta al giorno, secondo quanto descritto nel file SpeakEasy.h.

Quindi:

097-102 – La funzione DigIn rileva il cambiamento di stato dell’ingresso (2,3,4,5,6,7 di Arduino) e cambia lo stato dello SLOT (LED_0_N1, LED_1_N1, LED_2_N1, LED_3_N1, LED_4_N1, LED_5_N1).

105-110 – Esegue la logica inerente allo stato dello SLOT e al tipico.

113-118 – La funzione DigOut setta il relativo pin di Arduino (8, 9 ,10, 11, 12, 13) a livello logico alto o basso in relazione allo sto dello slot, in parole povere accende o spegne il LED connesso tra GND e il pin di Arduino.

120 – In questa dichiarazione vengono gestite parecchie cose:

– Elabora più canali di comunicazione gestiti in round-robin, i dati di uscita sono situati nella mappa di memoria e sono pronti per essere letti dall’interfaccia utente.

– Recupera i dati dei canali di comunicazione

– Ottenere le definizioni dei tipici dai dispositivi remoti in caso di riavvio del gateway

123-131 – Vengono gestite le temporizzazioni (timer).

 

 

 

Casa domotica con Arduino: Souliss in sviluppo

– Lato pratico –

Dopo una breve presentazione del progetto, descritto per lo più come schema a blocchi, ora attraverso la pubblicazione di un paio di foto illustro la parte reale del progetto

sou
In questa foto sono presenti in alto un Access Point della D-link per il WiFi con indirizzo statico 192.168.2.20, sotto quest’ultimo un vecchio ModemRouter della Trust con IP Statico 192.168.2.10, utilizzato solo come switch con server DHCP e funziona da gateway della rete lan.

Sopra al AP D-link ci sono due PIR di test per i tipici T41 e T42 di prossima integrazione nel progetto con due funzioni diverse, quelli dedicati al sistema di allarme e quelli dedicate all’automatismo di luci, irrigazione e preallarme.
sou2

Nella seconda foto il cuore del sistema con il Nodo01 e Nodo02 su piattaforma ethernet e con Nodo04 e Nodo05 in standalone a 16Mhz con RS485 in peer dal Nodo02 configurato come bridge_RS485.

Pubblicherò qualche schema per essere più chiaro con i collegamenti.

La casa domotica con Arduino: Souliss

Schema di base: Souliss la casa domotica

Con l’idea di automatizzare determinate parti della casa, ho creato a grandi linee uno schema ed ho svolto una ricerca in rete per identificare una soluzione economica che ricoprisse tutte le mie necessità.
Immediatamente la soluzione, secondo me più valida, è stata la Souliss Framework per Arduino, in quanto open source con licenza GNU General Public License versione 3.
Souliss è un framework per soluzioni domotiche, SmartHome e Internet of Things, utilizzando svariate schede con base Arduino e la possibilità di un’interfaccia Android. E’ possibile controllare dispostivi elettrici con pulsanti o interfacce grafiche su smartphone e tablet, gestisce e programmi le azioni da effettuare con molte opzioni.
Nella figura qui sotto è visualizzata a blocchi l’idea del mio progetto.

Schema PR_Souliss

Souliss, come descritto nel GibHub di appartenenza, è progettato per essere leggero e scalabile ed è installato su più nodi sfruttando diversi mezzi di comunicazione come Ethrnet, RS485, Wi-Fi, ZigBee.

Si può iniziare prendendo spunto dalla sua wiki sul sito di appartenenza.

Come riportato nello schema il nodo principale è Nodo01 ossia il gateway di Souliss dove fanno capo tutte  le informazioni provenienti dai vari nodi. Questo è connesso via LAN al router con IP statico.Nei prossimi articoli pubblicherò l’esploso di ogni nodo elencando l’hardware utilizzato e il software dedicato a ogni singolo nodo; il primo preso in esame sarà il gateway.

Cosa è un puntatore

Un puntatore è un tipo di dato, una variabile che contiene l’indirizzo
in memoria di un’altra variabile. Si possono avere puntatori a qualsiasi tipo
di variabile.
La dichiarazione di un puntatore include il tipo dell’oggetto a cui il
puntatore punta.
In C ogni variabile ha due tipi di valori: una locazione e un valore
contenuto in quella locazione.

L’ operatore & (operatore unario, o monadico) fornisce l’indirizzo di una
variabile.
L’ operatore * (operatore indiretto, o non referenziato) da’ il contenuto
dell’oggetto a cui punta un puntatore.

Per dichiarare un puntatore ad una variabile, l’istruzione e’:

int *pointer;

Nota: e’ obbligatorio associare un puntatore ad un tipo particolare; per
esempio, non e’ possibile assegnare l’indirizzo di uno short int ad un
long int.

Consideriamo gli effetti del seguente codice:

int *pointer; /* dichiara pointer come un puntatore a int */
int x=1,y=2;

(1) pointer= &x; /* assegna a pointer l’indirizzo di x */
(2) y=*pointer; /* assegna a y il contenuto di pointer */
(3) x=pointer /* assegna ad x l’indirizzo contenuto in pointer */
(4) *pointer=3; /* assegna al contenuto di pointer il valore 3 */

Vale la pena considerare cosa succede al “livello macchina” in memoria per
capire completamente come funzionano i puntatori.
Supponiamo che la variabile x si trovi nella locazione di memoria 100, y nella
200 e pointer nella 1000 (ricordiamo che pointer e’ una variabile a tutti gli
effetti, e cosi’ il suo valore necessita di essere memorizzato da qualche
parte; e’ la caratteristica del valore dei puntatori che risulta nuova).

L’istruzione (1) fa si che pointer punti alla locazione di memoria 100
(quella di x).
La (2) fa si che y assuma valore 1 (il valore di x).
La (3) fa si che x assuma valore 100 (cioe’ il valore di pointer).
La (4) fa si che il valore del contenuto di pointer sia 3 (quindi x=3).

Notate che le assegnazioni x=1 e y=2 ovviamente caricano questi valori nelle
variabili; pointer e’ dichiarato come puntatore ad un intero e vi e’
assegnato l’indirizzo di x (&x), cosi’ pointer verra’ caricato con il valore
100.
Successivamente, y prende l’assegnazione del contenuto di pointer. In questo
esempio, pointer punta attualmente alla locazione di memoria 100 (la locazione
di x). Cosi’ ad y viene assegnato il valore di x (che’ e’ 1).
Abbiamo gia’ visto che il C non e’ molto meticoloso riguardo all’assegnazione
di valori di tipo differente. Cosi’ e’ perfettamente legale (sebbene non sia
comune a tutti) assegnare il valore corrente di pointer ad x; in questo
momento il valore di pointer e’ 100.
Alla fine possiamo assegnare un valore al contenuto di pointer (*ip).

Quindi in merito ai puntatori possiamo avre tre possibili valori:
pointer contenuto o valore della variabile pointer
(indirizzo della locazione di memoria a cui punta)
&pointer indirizzo fisico della locazione di memoria del puntatore
*pointer contenuto della locazione di memoria a cui punta

NB. Quando un puntatore viene dichiarato non punta a nulla!
Per poterlo utilizzare deve puntare a qualcosa!
E’ infatti un errore comune non assegnare un indirizzo di memoria a un
puntatore prima di usarlo.
Cosi’:

int *ip;

*ip=100;

generera’ un errore (crash di programma).
L’utilizzo corretto e’ il seguente:

int *ip;
int x;

ip=&x;
*ip=100;

Un metodo comune per ovviare al problema dell’assegnazione dell’indirizzo
e’ quello di utilizzare la funzione di libreria standard malloc(), che
permette un’allocazione dinamica della memoria; e’ definita come
char *malloc(int number_of_bytes).

Ad esempio:

int *p;
p = (int *) malloc(100);
oppure:
p= (int *) malloc(100*sizeof(int))

Si possono fare operazioni aritmetiche intere con i puntatori:

float *flp, *flq;
*flp=*flp+10;
++*flp;
(*flp)++;
flq=flp;

Nota: un puntatore ad una variabile di qualsiasi tipo e’ un indirizzo in
memoria (il quale e’ un indirizzo intero). Un puntatore per definizione
NON e’ un intero.

La ragione per cui associamo un puntatore ad un tipo di dato e’ quella per
cui e’ possibile riconoscere quanti bytes contiene il dato. Quando si
incrementa un puntatore si cresce il puntatore di un “blocco” di
memoria.
Cosi’ per un puntatore a char ++ch_ptr aggiunge 1 byte all’indirizzo,
per un intero o un float ++ip aggiunge 4 byte all’indirizzo.

Consideriamo una variabile float (fl) ed un puntatore ad un float (flp);
ricordiamo che ad un float corrispondono 4 bytes.
Assumiamo che flp punti ad fl; se poi incrementiamo il puntatore (++flp),
questo si sposta dalla posizione a cui puntava originariamente di 4 bytes in
avanti, e puntera’ quindi al float successivo. D’altra parte, se aggiungiamo
2 al puntatore (flp+2), questo si sposta di due posizioni float, cioe’ di 8
bytes.

Differenze tra connettore SMA e RP-SMA

Connettori d’antenna FPV per miltirotori e Aerei RC

Differenze tra SMA e RP-SMA
Differenze tra SMA e RP-SMA

Quando si cambia l’antenna per un trasmettitore e ricevitore FPV una delle domande che sorge potrebbe essere:”Quale è la differenza tra il connettore SMA e il connettore RP-SMA?”
C’è molta confusione attorno ai tipi di connettori e qualcuno ha trovato difficile ottenere la giusta informazione intorno i diversi tipi. Anche i venditori online a volte si sbagliano pubblicando foto errate del prodotto, come si vedrà più avanti.

Differenza tra connettori RP-SMA e SMA

Gli SMA (acronimo di Sub-Miniature versione A) sono connettori coassiali RF sviluppati nel 1960. RP-SMA (acronimo di – reverse polarity – polarità inversa SMA) è una variante della specifica del connettore SMA che inverte il tipo di interfaccia.

Ecco alcune immagini di confronto tra connettori SMA e  RP-SMA.

Femmina SMASMA femminaMaschio SMASMA maschio
Femmina RP-SMArp-sma femminaMaschio RP-SMArp-sma maschio

Il connettore RP-SMA femmina ha un corpo di contatto femmina e il pin interno maschio mentre il connettore RP-SMA maschio è al  contrario in entrambi gli aspetti, corpo maschio con contatto interno  femmina.
Il connettore SMA femmina ha un corpo femmina e un contatto interno femmina e il maschio SMA è l’opposto.

La storia interessante dei connettori RP-SMA

Siccome i connettori RP-SMA non erano facilmente disponibili, sono stati ampiamente utilizzati dai produttori di apparecchiature Wi-Fi per conformarsi alle normative locali, come quelli della FCC, dove tali apparecchiature devono essere progettate e commercializzare in modo da impedire ai consumatori di variare il guadagno delle antenne collegate violando quindi la conformità.La FCC ha ritenuto che la RP-SMA era accettabile nella prevenzione di cambiare l’antenna da parte del consumatore in quanto di difficile reperibilità da parte dell’utente; ma nel 2000 la FCC li considerava come prontamente disponibili, anche se ritarda la sua decisione in merito all’utilizzo a tempo indeterminato. Ad oggi 2014 i principali produttori stanno ancora utilizzando connettori RP-SMA sulle loro apparecchiature Wi-Fi.