Differenze tra le versioni di "Tavolo zero (renzo)"

Da raspibo.
Jump to navigation Jump to search
m
 
Riga 14: Riga 14:
  
 
''Novità! c'è una mailing list! [http://liste.raspibo.org/wws/info/tavolozero tavolozero at liste.raspibo.org]''
 
''Novità! c'è una mailing list! [http://liste.raspibo.org/wws/info/tavolozero tavolozero at liste.raspibo.org]''
 +
 +
=== Immagini della Rete Logica Umana realizzata il 24/10/2017 ===
 +
 +
[[Rete_Logica_Umana]]
  
 
=== Non-Corso di Python ===
 
=== Non-Corso di Python ===

Versione attuale delle 14:04, 27 ott 2017

{{#if: | }} {{#if: http://liste.raspibo.org/wws/info/tavolozero Vuoi partecipare o solamente essere informato? Iscriviti alla mailing list| }} {{#if: | }}
Gruppo
[[File:{{{icona}}}]] }}Tavolo Zero
partiamo da zero!
[ social network]
Vuoi partecipare o solamente essere informato? Iscriviti alla mailing list mailing list
[ code repository]
Iscritti
tutti, anche tu!

Benvenuti al tavolo zero.

Zero come "qui si parte da zero".

Non sapete qualcosa? Benevenuti al tavolo zero.

E' come un Coder Dojo dove si fanno esperimenti di Making, ci sono esempi/tutorial ma poi fate cio' che volete... ma fate voi!

Novità! c'è una mailing list! tavolozero at liste.raspibo.org

Immagini della Rete Logica Umana realizzata il 24/10/2017

Rete_Logica_Umana

Non-Corso di Python

Esercizi non-corso Python

Attività per la sera del 12 novembre

Esercizi proposti da Renzo:

0- installare VNC

1- accendere 'sto solito led (in bash, C e python)

2- creare un termostato o un crepuscolare.

per partecipare al gioco occorre:

  • un portatile
  • un cavo di rete (*)
  • un raspberry pi con alimentatore
  • una SD card possibilmente con rasbian precaricato
  • una breadboard (*)
  • un cavo di collegamento raspi-breadboard (*)
  • una resistenza da circa 270 ohm (*)
  • un transistor BC547 (*)
  • una resistenza da circa 1Kohm (*)
  • un diodo 1N4007 (*)
  • un relais (*)
  • un termometro ds18b10 (*)
  • un sensore di luminosita' (*)

Almeno una istanza di ogni oggetto contrassegnato con (*) la portero' io


(aggiungete please ulteriori esercizi proposti da voi)


Devo inserire qui gli esercizi ?


Unità UNO: [Misure ADC su JeeNode]

Obiettivi:    
  • Usare il JeeNode come ADC (Analog to Digital Converter);
  • Verificare la corrispondenza tra Tensione in uscita da un Trimmer e valore Digitale;
  • Trasferire i dati letti da JeeNode su RaspberryPi attraverso la porta USB;
Prerequisiti:  
Strumenti : 
  • Un Pc con l'IDE di Arduino Installato
  • Un JeeNode (o un Arduino)
  • Un Trimmer o un Potenziometro;
Primo Passo: 

Caricare su JeeNode (o su Arduino) con l'IDE il seguente programma:

const int PinPot = 14;  // AIO1 di JeeNode | 14 è la numerazione Arduino
float Vbit = 3.3/1024;  // il convertitore (Jee) lavora a 10 bit e a 3.3 Volt
int ValPot=0;           // variabile che legge la tensione su AIO1
void setup() {                
 Serial.begin(9600);
 while(!Serial);
 pinMode(PinPot, INPUT);  
}
void loop() {
   ValPot=analogRead(PinPot);  // legge valore ADC dal pin 14
   /* Mostra valore digitale e tensione
      su Monitor Arduino | più esattamente spedisce su USB */
   Serial.print("Valore Digitale: ");
   Serial.print(ValPot);
   Serial.print(" | Tensione=");
   Serial.println(ValPot*Vbit);
   // attende 2 secondi 
   delay(2000);
}
Secondo passo:

Realizzare sulla Port1 del JeeNode il seguente circuito con un trimmer da 10 kohm


Jee Trimmer.png


Provare il programma aprendo il monitor seriale di Arduino. Si dovrebbe notare quanto segue: Ruotando il trimmer se questo giunge ad un estremo, AIO1=GND si leggerà 0 digitale e 0 di tensione e ruotando in direzione opposta cresce fino all'altro estremo AIO=3.3volt, e si leggerà 1023 per una tensione di 3.3 Volt.

Esiste una proporzionalità diretta tra tensione sul pin AIO1 e valore digitale letto:

3.3(Volt) : 1024  =   Vx(volt) : N_Dig  segue → Vx= 3.3 * N_Dig/1024

Jee Trimmer sch.png


Terzo Passo:

Collegare con un Cavetto il JeeNode (così programmato) ad una delle porte USB di RASPY. Eseguire i seguenti comandi per installare il software (pyton-serial) se necessario su Raspy:

pi@raspy$ sudo apt-get -u install python-serial

Scrivere con un editor qualsiasi il seguente programma python e salvarlo:

pi@raspy$ nano ardu_adc.py
import serial
arduino=serial.Serial('/dev/ttyUSB0')
while 1:
    print arduino.readline()

Eseguire il programma:

pi@raspy$ python ardu_adc.py

Se non ci sono errori e la USB è la /dev/ttyUSB0, sul monitor compariranno i valori che in precedenza mostrava il monitor di Arduino con il trimmer agli estremi.


Jee Trimmer raspy.png


E' evidente che manipolando opportunamente i valori ricevuti si potranno memorizzare o pubblicare i dati di qualsiasi misura.

Nota: Il codice caricato su JeeNode è a tutti gli effetti un codice Arduino e di conseguenza si potrebbe ottenere lo stesso risultato usando un Arduino al posto di JeeNode.

Unità DUE: [Misura ADC e Allarme LED su JeeNode]

Obiettivi: 	
  • Usare tutte le potenzialità di JeeNode in particolare la libreria JeeLib.
  • Conoscere la corrispondenza tra i PIN Arduino e i PIN JeeNode.
  • Collegare un Trimmer e un LED di allarme al JeeNode
Prerequisiti: 
  • Come nell'unità UNO;
  • Conoscenza di base di Linux RaspberryPi (download, unzip file, copia);
Strumenti : 
  • Un Pc con l'IDE di Arduino Installato
  • Un JeeNode
  • Un Trimmer, un LED, un resistore da 330 ohm
Primo Passo:

Scaricare la libreria JeeLib in formato tar.gz se si usa IDE in linux o in formato zip se si usa IDE in windows. Scompattare, Rinominare JeeLib e Copiare la libreria nella directory ../Libraries di Arduino. Se tutto Ok nella cartella Esempi dell'IDE di Arduino dovrebbe comparire la libreria JeeLib ed i relitivi esempi. Per vedere la corrispondenza dei Pin Arduino e JeeNode vedi:

Secondo Passo:

Scrivere e Caricare il primo codice per JeeNode usando le funzioni di JeeLib.

// inclusione della libreria
#include <JeeLib.h>
// (*) Definisce un oggetto Port di identificatore 'Uno'. 
// Il parametro '1' indica che ci riferiamo alla PORT1 di JeeNode
// per le altre porte analogamente Port Mia (3) - indica la PORT3.
Port Uno (1); 
void setup() {
 Serial.begin(9600);
 while(!Serial);
 Uno.mode(OUTPUT);    // (*)attiva in output la prota DIO1 
 Uno.mode2(INPUT);    // (*)attiva in input la prota AIO1 
}
void loop() {
 word val;
 val = Uno.anaRead();      // (*) legge il valore analogico su AIO1
 Serial.print("\nValore digitale:");
 Serial.println(val);
 if ( val>512 ) {
   Uno.digiWrite(HIGH);   // (*) pone ALTO il pin DIO1
   delay(500);
   Uno.digiWrite(LOW);    // (*) pone BASSO il pin DIO1
   delay(500);
 }
 delay(1000);
}

Nota: tutte le righe con (*) usano funzioni di JeeLib

Terzo Passo:

Realizzare sul JeeNode il seguente circuito:


Jee Trimmer led.png


La Port1 ha le seguenti connessioni:

AIO1 → pin centrale del Trimmer 10k
DIO1 → terminale positivo del LED
GND  → resistore da 470 ohm collegato al terminale negativo del LED

La Port2 (ha la sola funzione di alimentare il Trimmer):

+    → alimentazione +3.3v del trimmer
GND  → massa del trimmer 
Quarto Passo:

Aprire il Monitor seriale di Arduino, dovrebbe comparire la scritta ciclica con valori digitali compresi tra 0 e 1023 a seconda della rotazione del trimmer:


Jee Trimmer led ser.png


Se la vite del Trimmer è oltre la metà corsa, segue che il valore Digitale vale più di 512 quindi il LED Lampeggia (Allarme). Se invece il valore digitale è minore di 512 il LED non si accende.

Unità TRE: [Misurare la Temperatura Ambiente con un NTC]

Obiettivi:	
  • Usare un PIN ADC di JeeNode per misurare una temperatura.
  • Conoscere il funzionamento di un sensore NTC
  • Trasferire i dati via USB su un monitor di Raspy
  • Avviare lettura di T con Comando “trigger” inviato da Raspy (o PC) verso JeeNode
  • Memorizzare le misure su un File in Raspy o su PC linux
Prerequisiti: 
  • Come nell'unità Due.
Strumenti :
  • Un Pc con l'IDE di Arduino Installato
  • Un JeeNode
  • Un sensore NTC, un resistore con R simile alla R nominale di NTC
Primo Passo:

Un sensore NTC (Negative Temperature Coefficient) è una resistenza molto sensibile alla variazione di temperatura. In particolare la resistenza ha un coefficiente negativo nel senso che la resistenza Diminuisce al Crescere della temperatura. La diminuzione di resistenza non è lineare ma decresce in modo esponenziale.


Jee NTC graph.png


Ne consegue che non è possibile usare una semplice proporzione 'Tensione:Valore Digitale' per determinare la temperatura. I “manuali” consigliano di usare l'equazione di Stheinart per determinare la temperatura:


Jee NTC form.png


Vediamo come:

  • T è la temperatura in Kalvin misurata dal sensore
  • To è la temperatura ambiente nominale in Kalvin 25° = 298,5;
  • B è la costante caratteristica del Sensore NTC (Riportata nei fogli dati del sensore, di norma varia tra 3000 e 4000);
  • Ro è la resistenza di NTC a 25°;
  • Rt la resistenza di NTC all'istante t.
Secondo Passo:

Realizzare il seguente Circuito con il sensore NTC:


Jee NTC sch.png


Nel circuito Ro=5100, Ri=4700 ohm, B=4000, To=298,5 → 25°


Jee NTC ele.png


Il Pin ADC misura il valore digitale della caduta di tensione Vi ai capi di Ri indicata in figura con Dvi. Così la tensione Vcc corrisponde a Dvcc=1023 e la Vt corrisponde a Dvt=1023-Dvi. Si può scrivere la legge di ohm del partitore in figura usando i valori digitali al posto delle tensioni in volt.

Vt/Vi=(1023-Dvi)/Dvi; 
dividendo Num e Den del 1° membro per I che attraversa il circuito si ottiene  
Rt/Ri=(1023-Dvi)/Dvi=1023/Dv1-1. 
Quindi Rt = Ri*(1023/Dvi -1)

Per realizzare l'algoritmo che calcola T si eseguiranno i seguenti passi:

calcolo  Rt = Ri*(1023/Dvi -1)	// che coincide con   Rt 
calcolo   T = ln(Rt/Ro)	// T attuale è ln(Rt/Ro)
calcolo   T = T/B		// T attuale ln(Rt/Ro)/B
calcolo   T = 1/To +T		// T attuale è 1/T
finalmente T=1/T - 273.15;
Terzo Passo:

Codifica e Upload del firmware nel JeeNode:

#include <JeeLib.h>
// Ro Resistenza nominale di NTC
#define NTC_NOMINALE 5100      
// B coefficiente NTC 
#define NTC_B 4000
// Ri Resistenza in Serie Inserita
#define NTC_SERIE 4700
// Numero di misure per calcolare la media Dvi
#define N_MISURE 5
// Utilizzo la Port1 AIO1
Port NTC (1);
void setup(void) {
  Serial.begin(9600);
  while(!Serial);
  NTC.mode2(INPUT);    // AIO1 è posto in INPUT
}
void loop(void) {
  uint8_t i;
  float Dvi=0;
  float Rt=0;
  // legge N campioni ed esegue la media
  for (i=0; i< N_MISURE; i++) {
    Dvi += NTC.anaRead();	   // esecuzione ADC
    delay(10);
  }
  Dvi=Dvi/N_MISURE;
  Serial.print("Dvi: "); 
  Serial.println(Dvi);
  // Determino Rt
  Rt = NTC_SERIE*(1023 / Dvi - 1);
  Serial.print("Rt "); 
  Serial.println(Rt);
  // determino T
  float T;
  T=log(Rt/NTC_NOMINALE);          // ln(R/Ro)
  T = T/NTC_B;                     // 1/B * ln(R/Ro)
  T = T + 1.0 / (298.15);          // (1/To) + 1/B * ln(R/Ro)
  T = 1.0 / T - 273.15;            // Inverto e sottraggo Kalvin
  Serial.print("Temperatura "); 
  Serial.print(T,1);
  Serial.println(" *C");
  delay(3000);
}

Se si esegue il programma sul monitor dell'IDE di Arduino comparirà qualcosa di simile a:


Jee NTC ser.png


Quarto PASSO:

Modifichiamo il programma e facciamo inviare, via seriale, da Raspy verso JeeNode un Carattere di 'Trigger' che avvia l'esecuzione della misurazione di T. Quindi da JeeNode inviamo a Raspy solo la temperatura T Misurata. Questo è il nuovo programma JeeNode avviato con un “trigger” Seriale.

#include <JeeLib.h>
// Stesso codice precedente
// fino a loop()
// .... 
void loop(void) {
  uint8_t i;
  float Dvi=0;
  float Rt=0;
  int N=Serial.available();	      // (*)
  // se arrivano uno o più caratteri di 'trigger'
  // da Monitor seriale o da RASPY 
  // vengono avviate le misure
  if (N>0) {				// (*)														
   while (N>0) {Serial.read();N--;}	// (*) svuota il buffer
   delay(500);                         // (*)
   // legge N campioni ed esegue la media
   for (i=0; i< N_MISURE; i++) {
     Dvi += NTC.anaRead();
     delay(10);
  }
  Dvi=Dvi/N_MISURE;
  // Determino Rt
  Rt = NTC_SERIE*(1023 / Dvi - 1);
  // determino T
  float T;
  T=log(Rt/NTC_NOMINALE);          // ln(R/Ro)
  T = T/NTC_B;                     // 1/B * ln(R/Ro)
  T = T + 1.0 / (298.15);          // (1/To) + 1/B * ln(R/Ro)
  T = 1.0 / T - 273.15;            // Inverto e sottraggo Kalvin
  // stringa in cui memorizzo il risultato
  char buf[10];                    // (*)
  // trasforma il float in una string
  dtostrf(T,6,1,buf);              // (*)
  Serial.print(buf);               // (*)
 }
 delay(500);
}

Nota: le righe con (*) sono state modificate o inserite. Si può provare il programma dal monitor seriale di Arduino: Se nel campo di Invio si inserisce un carattere qualsiasi e si preme Invia (trigger) si ottiene la misura di T come segue:


Jee NTC ser2.png


Quinto Passo:

Collegare con un Cavetto il JeeNode (così programmato) ad una delle porte USB di RASPY.

Scrivere con un editor qualsiasi il seguente programma python e salvarlo:

pi@raspy$ nano Jee_Raspy_adc_Dati.py
import time
from datetime import date
import serial
# intervallo di tempo tra le misure in secondi 
DSEC=60
# porta USB su cui avviene lo scambio tra Raspy e JeeNode
ser=serial.Serial('/dev/ttyUSB0', 9600, timeout=2)
TH=time.time()
print "Ogni",DSEC,"secondi Misuro T"
while 1:
   # calcolo l'intervallo di tempo trascorso DT dall'avvio
   T1=time.time()
   DT=T1-TH
   # Memorizzo il tempo attuale
   Tattuale=time.strftime("%H:%M:%S")
   oggi=date.today()
   if (DT>=DSEC):	# se sono trascorsi DSEC effettua la misura
     TH=T1;
     # segnale di 'trigger' inviato da Raspi a JeeNode	
     ser.write("A")
     # legge su USB la misuta di 7 caratteri
     Temp=float(ser.read(7))
     # mostra a video i dati Temperatura – Data - Ora
     print (Temp);
     print oggi.strftime("%d/%m/%Y")
     print (Tattuale)
     print(' ')

Eseguire il programma:

pi@raspy$ python Jee_Raspy_adc_Dati.py

Se non ci sono errori e la USB è la /dev/ttyUSB0, sul monitor compariranno i valori .


Jee NTC raspy.png


Sesto Passo:

Modificare il programma python per memorizzare i dati su un file di Raspy di nome 'DATI.txt'. Modificare il precedente programma python e salvarlo (le righe con (*) sono aggiunte al precedente programma):

pi@raspy$ nano Jee_Raspy_adc_File.py
import time
from datetime import date
import serial
# file in cui memorizzo dati
nome_file="DATI.txt"                 #(*)
#intervallo di tempo tra le misure in secondi
DSEC=60
#porta USB su cui avviene lo scabio tra Raspy e JeeNode
ser=serial.Serial('/dev/ttyUSB0', 9600)
TH=time.time()
print "Ogni",DSEC,"secondi misuro T")
# apre il file cancellando i dati precedenti
out_file=open(nome_file,"w")        #(*)
while 1:
  # calcolo l'intervallo di tempo trascorso DT dall'avvio
  T1=time.time()
  DT=T1-TH
  # Memorizzo il tempo attuale
  Tattuale=time.strftime("%H:%M:%S")
  oggi=date.today()
  if (DT>=DSEC):  # se e' trascorso DSEC effettua la misura
      TH=T1;
      # apre il file in modalita' append
      out_file=open(nome_file,"a")     #(*)
      # segnale di 'trigger' inviato da Raspi a JeeNode
      ser.write("A")
      # legge su USB la misura di 7 caratteri
      Temp=float(ser.read(7))
      Temp="%4.1f *C" % Temp
      # mostra sul monitor
      print (Temp);
      print oggi.strftime("%d/%m/%Y")
      print (Tattuale)
      print(' ')
      # appende nel file
      out_file.write(oggi.strftime("%d/%m/%Y"))   #(*)
      out_file.write(", ")                        #(*)
      out_file.write(Tattuale)                    #(*)
      out_file.write(", ")                        #(*)
      out_file.write(Temp)                        #(*)
      out_file.write("\n")                        #(*)
      out_file.close()                            #(*)

Per vedere il file generato eseguire il comando :

pi@raspy  cat DATI.txt     

a video comparirà:


Jee NTC raspy file.png


Unità QUATTRO: [Trasmettere da un JeeNode Locale ad un JeeNode Remoto]

Obiettivi:	
  • Usare i comandi JeeNode di trasmissione wireless
  • Conoscere le variabili che memorizzano lo stato delle Porte JeeNode
  • Visualizzare i valori caratteristici dei pin DIO, e AIO delle varie porte
Prerequisiti: 
  • Come nell'unità Due.
Strumenti : 
  • Un Pc con l'IDE di Arduino Installato
  • DUE JeeNode (uno alimentato a Pile)
  • Opzionale un LED.
Primo PASSO:

Breve premessa teorica → informazioni essenziali:

  • Un JeeNode ha 4 Port (1..4);
  • Ciascuna Port ha 2 PIN (importanti)
  • un Pin DIO (Digital Input Output) e
  • un Pin AIO (Analog Input Output).

Remoto JeeNode pinout.png


Schematicamente (non esaustivo): I Pin DIO sono utilizzabili in Due modalità (principali):

INPUT Digitale o OUTPUT Digitale che possono assumere solo DUE stati logici ALTO o BASSO.
I Pin AIO sono utilizzabili in Due modalità (principali):  
INPUT Analogico oppure OUTPUT Digitale.

In Input Analogico vengono usati come ADC (Analog to Digital Converter), in questo caso non ha senso parlare di livelli, infatti l'input del Pin AIO proviene da una tensione esterna che sarà convertita in un numero ad essa proporzionale da 0 a 1023 (ADC a 10 bit). In Output Digitale assumeranno solo i valori ALTO e BASSO

Trasmissione wireless da un JeeNode LOCALE a un secondo JeeNode REMOTO: La JeeLib consente di definire sul JeeNode (Locale) un RemoteNode (che si riferisce al JeeNode Remoto) e su questo si possono definire gli stati delle RemotePort (sul JeeNode Remote). Dal JeeNode Locale posso 'Modificare' lo stato del JeeNode Remoto trasmettendo lo stato desiderato per le varie porte Remote.

Secondo PASSO:

Vediamo i codici dei due JeeNode che consentono al Locale di modificare lo stato del Remoto. (per ora non Viceversa)

// NODO LOCALE
#include <JeeLib.h>
//Definisco il JeeNodo 'remoto' a cui inviero' i dati 
// Nodo 5 Gruppo 10
RemoteNode remoto (5, RF12_868MHZ,10);
// Definisco le 4 Port di 'remoto'
RemotePort Uno (remoto, 1);
RemotePort Due (remoto, 2);
RemotePort Tre (remoto, 3);
RemotePort Qua (remoto, 4);
void setup() {
   // inizializzo la radio di questo JeeNode
   // Nodo 2, Gruppo 10
   rf12_initialize(3, RF12_868MHZ,10);
   // MODE dei PIN AIO 
   // in bit = 1010 = OUT-IN–OUT-IN
   Qua.mode2(OUTPUT);  //AIO4 output Digitale
   Tre.mode2(INPUT);   //AIO3  input Analogico
   Due.mode2(OUTPUT);  //AIO2 output Digitale
   Uno.mode2(INPUT);   //AIO1 input Analogico
   //MODE dei Pin DIO  in bit = 1111
   Qua.mode(OUTPUT);  // DIO4 output Digitale
   Tre.mode(OUTPUT);  // DIO3 output Digitale
   Due.mode(OUTPUT);  // DIO2 output Digitale
   Uno.mode(OUTPUT);  // DIO1 output Digitale
   // Byte di stato ->  modes=1010 1111
   // Livello di AIO4 AIO2 in bit = 1010
   Qua.digiWrite2(HIGH);  // Livello AIO4=ALTO
   Due.digiWrite2(HIGH);  // Livello AIO2=ALTO
   // Livello dei PIN DIO in bit = 1110
   Qua.digiWrite(HIGH);  // Livello DIO4=ALTO
   Tre.digiWrite(HIGH);  // Livello DIO3=ALTO
   Due.digiWrite(HIGH);  // Livello DIO2=ALTO
   Uno.digiWrite(LOW);   // Livello DIO1=BASSO
   // Byte di stato ->  digiIO=1010 1110
   // Byte di stato -> flags=1100 0000, 
   // il primo bit a UNO indica che si desidera
   // modificare il MODE dei pin
   // il secondo Bit a UNO indica che sono stati 
   // modificati i livelli digitali delle Porte
}
void loop() {
   // ogni 4 sec invia a JeeNode Remoto lo stato 
   // che definisce un JeeNode. Questo è 
   //  una struttura dati di 13 Byte 
   // flags=1Byte, modes=1Byte, digiIO=1Byte,
   // anaOut[0], [1]=2Byte, anaIn[0]..[3]=8Byte.
   Delay(4000);
   // Trasmissione dello stato desiderato a Remoto
   remoto.poll(80);
}

// NODO REMOTO
#include <JeeLib.h>
// E' lo stato che sarà ricevuto 
RemoteNode::Data state;
// Porte locali di Remoto
Port Uno (1), Due (2), Tre (3), Qua (4);
void setup() {
   Serial.begin(9600);
   // questo JeeNode è il 5 e riceve dal gruppo 10
   rf12_initialize(5, RF12_868MHZ,10);
}
void loop() {
   if (rf12_recvDone() && rf12_crc == 0 && rf12_len == sizeof state) {
       memcpy(&state, (void*) rf12_data, sizeof state);
       // dal programma del Node trasmittente ricevo i 
       // MODES a cui settare DIO1..4   modes= xxxx 1111
       Qua.mode(state.modes & 0x08);  // DIO4 
       Tre.mode(state.modes & 0x04);   // DIO3 
       Due.mode(state.modes & 0x02);  // DIO2
       Uno.mode(state.modes & 0x01);  
       // MODES di AIO4 e AIO2   modes= 1010 xxxx
       Qua.mode2(state.modes & 0x80); //AIO4 
       Due.mode2(state.modes & 0x20);  // AIO2 
       // Livelli a cui portare DIO4 ..1    digiIO= xxxx 1110
       Qua.digiWrite(state.digiIO & 0x08);
       Tre.digiWrite(state.digiIO & 0x04);
       Due.digiWrite(state.digiIO & 0x02);
       Uno.digiWrite(state.digiIO & 0x01);
       // Livelli a cui portare AIO4 e AIO2 
       // usate come Out Digitali
       // digiIO= 1010 xxxx   AIO3 e AIO1
       // non sono stati settati perche' Input
       Qua.digiWrite2(state.digiIO & 0x80);
       Due.digiWrite2(state.digiIO & 0x20);
       // Stampa di controllo dei dati ricevuti
       Serial.print ("Byte Ricevuti (RemoteNode:Data) ");
       Serial.println (sizeof state);
       Serial.print ("1 flags: ");
       Serial.println (state.flags,BIN);
       Serial.print ("2 mode (0/1): ");
       Serial.println (state.modes,BIN);
       Serial.print ("3 digiIO (0/1): ");
       Serial.println (state.digiIO,BIN);
       state.flags = 0;      
       if (RF12_WANTS_ACK)
           rf12_sendStart(RF12_ACK_REPLY, 0, 0);
   }  
}

Dopo la compilazione, aprendo il monitor seriale del Nodo Remoto, si dovrebbe vedere la seguente stampa ciclica che mostra come saranno settati i pin delle Porte remote (dei 13 Byte trasmessi analizziamo solo i Tre byte sottostanti):


Remoto JeeNode ser.png


  • flags 1100 0000
il primo bit a 1 indica che si desidera modificare il Mode di alcune porte
il secondo bit a 1 che si desidera modificare il Livello Logico di alcune porte

(non analizziamo il significato degli altri bit)

  • mode 1010 1111
i primi 4 bit a sinistra indicano rispettivamente il Modes di AIO4 .. AIO1
i 4 bit successivi indicano rispettivamente i Modes di DIO4 .. DIO1
  • digitIO 1010 1110
i primi 4 bit a sinistra indicano rispettivamente i Livelli Digitali di AIO4 .. AIO1
i 4 bit successivi indicano rispettivamente i Livelli Digitali di DIO4 .. DIO1

Usando un LED (con resistore di caduta) inserito, sul JeeNode Remoto (alimentato con pile), inserendo in successione il terninale positivo nei diversi Pin, si dovrebbe verificare l'accensione solo in quei Pin in cui digiIO = 1 (Alto) e mode = 1 (OUT) ovvero AIO4, AIO2, DIO4, DIO3, DIO2 (accesi) AIO3, AIO1, DIO1 (spento)


Remoto JeeNode sch.png


Unità CINQUE: [Rice/Trasmettere tra due JeeNode]

Obiettivi:	
  • Usare i comandi JeeNode di trasmissione wireless;
  • Usare una modalità di ricetrasmissione interattiva tra due nodi;
  • Apprendere come si scambiano DATI, diversi dal semplice STATO delle porte
Prerequisiti: 
  • quelli dell'Unità QUATTRO.
Strumenti: 
  • Un Pc con l'IDE di Arduino Installato
  • DUE JeeNode (uno alimentabile con Pile)
  • Un LED con resistore.
Premessa:

Per realizzare una rice-trasmissione interattiva tra Nodo Locale e Remoto, immaginiamo di voler accendere o spegnere a richiesta un LED Remoto con un comando inviato dal Node Locale. E di avere immediatamente il riscontro dello stato del led remoto sul Monitor Seriale del JeeNode Locale.

  • Azioni da NODO Locale:
Se da monitor seriale invio il carattere 'A' il LED remoto si Accende; 
Se invio 'S' si spegne; 
Altri caratteri  Accendono o Spengono il LED in modo RANDOM.
Immediatamente il monitor seriale mostra lo stato del led Remoto.
  • Azioni sul Nodo Remoto:
Vedo il LED acceso o spento a seconda del comando Inviato.
Primo Passo:

Realizzare il seguente circuito sul JeeNode Remoto per evidenziare i comandi inviati sul led:


Remoto RT sch.png


Secondo Passo:

Programmo il Node Locale come Trasmettitore e Ricevitore. Trasmette lo stato del LED remoto e Riceve una stringa Led Acceso/Spento.

/*==================================
Codice del JeeNode LOCALE
*=================================*/
#include <JeeLib.h>
// Definisco il Nodo 'Remoto' a cui inviero' i cambi di stato
RemoteNode remoto (5, RF12_868MHZ,10);
// Stringa che sarà ricevuta da Locale
typedef struct {char Ri[15];} CC;
// definisco la porta di 'remoto' usata per Accendere IL LED
RemotePort UNO (remoto, 1);
void setup() {
   Serial.begin(9600);
   while(!Serial);
   rf12_initialize(3, RF12_868MHZ,10);
   UNO.mode(OUTPUT);    // DIO1 output Digitale
   UNO.digiWrite(LOW);  // Livello iniziale DIO1=BASSO
}
char Input;
boolean OK=false;
void loop() {
  // se arriva un 'Trigger' da seriale lo leggo
  if (Serial.available()>0){
      Input=Serial.read(); 
      while(Serial.read()>0);    // consuma i caratteri in più da seriale  
      Serial.print(Input);
      // Modifica gli stati di Remoto a seconda del carattere 'Input' ricevuto
      switch (Input) {
       case 'A' : {UNO.digiWrite(HIGH);  remoto.poll(20);}break; // ACCENDE
       case 'S' : {UNO.digiWrite(LOW);  remoto.poll(20);}break;  // SPEGNE
       default :{ UNO.digiWrite(random(0,2));remoto.poll(20);}break; // Fa a CASO
      } 
      OK=true;
  }
  // Se ha cambiato lo stato Remoto riceve la risposta e la mostra sul monitor
  if (OK && rf12_recvDone() && rf12_crc == 0 && rf12_len == sizeof (CC)) {
       CC* data = (CC*) rf12_data;
       Serial.print("  ");
       Serial.println(data->Ri);
       OK=false;
   }
}

Si noti che Locale modifica lo stato di remoto (Trasmette un cambio di STATO) ma (Riceve una Stringa con un messaggio). Viceversa per Remoto.

/*==================================
Codice del JeeNode REMOTO
*=================================*/
#include <JeeLib.h>
// stato inviato da Locale a Remoto
RemoteNode::Data state;
// Messaggio inviato da Remoto a Locale
struct {char Ri[15];} CC;
// Porta locale  usata per il LED
Port Uno (1);
void setup() {
   rf12_initialize(5, RF12_868MHZ,10);
}
boolean OK=false;
void loop() {
    // Riceve da Locale lo stato delle Porte
   if (OK==false && rf12_recvDone() && rf12_crc == 0 && rf12_len == sizeof state) {
       memcpy(&state, (void*) rf12_data, sizeof state);
       Uno.mode(state.modes & 0x01);		// Cambia MODE
       Uno.digiWrite(state.digiIO & 0x01);	// Cambia Livello LOGICO
       state.flags = 0;      
       if (RF12_WANTS_ACK)
         rf12_sendStart(RF12_ACK_REPLY, 0, 0);
       OK=true;
   }
   // Se ha Ricevuto un cambio di Stato rispedisce un messaggio a Locale
   if (OK){
       if (Uno.digiRead()==HIGH) { sprintf(CC.Ri,"%s","LED Acceso!");}
       else { sprintf(CC.Ri,"%s","LED Spento");}
       // Trasmette Messaggio a Nodo Locale
       rf12_sendNow(0, &CC, sizeof CC);
       rf12_sendWait(0);
       OK=false;
   }   
}

Remoto RT ser.png


Se uso il monitor seriale di Arduino sul Nodo Locale e immetto:

'A' il led si accende e ricevo il messaggio 'LED Acceso'. 
'B' il led si spegne e ricevo il messaggio 'LED Spento'. 
'x' il led è Acceso o Spento in modo CASUALE, ma il messaggio restituito è 'Corretto'

Unità SEI: [Pubblicare Misure di temperatura (NTC) sul Web]

Obiettivi:	
  • Usare una modalità di ricetrasmissione interattiva tra due JeeNode;
  • Salvare i dati su File di Raspy;
  • Pubblicare i dati sul Web
Prerequisiti: 
  • quelli dell'Unità CINQUE.
Strumenti : 
  • Un Pc con l'IDE di Arduino Installato
  • DUE JeeNode (uno alimentabile con Pile)
  • Un sensore NTC con Led e resistore.
Premessa:

Lo schema del progetto seguente è dedotto dal sito JeeLabs, con le seguenti varianti:

  • Il sensore non è un LDR ma un Termistore NTC.
  • Il codice è stato realizzato ex novo;
  • La pubblicazione sul Web avviene usando Google Drive.

Ecco come si presenta lo schema del progetto finale:


Remoto Pro Progetto.png


  • Il JeeNode Remoto Misura la temperatura e la trasmette al JeeNode Locale
  • Il Nodo Locale è collegato a RaspberryPi attraverso la porta USB
  • Raspberry in rete locale è accessibile da ogni dispositivo (PC o altro) in rete locale
  • I dati sono trasmessi da Raspy, usando le funzionalità di Google Drive, ad un foglio Dati
  • Con un Browser le misure sono accessibili ad ogni PC in rete, ad un tablet o a un smatphone in WIFI da qualsiasi località.
Primo Passo:

Il circuito realizzato sul JeeNode Remoro è il seguente:


Remoto Pro sch.png


Il LED ha la funzione di lampeggiare tutte le volte che avviene una misura di Temperatura. Più esattamente NTC e LED sono stati assemblati su una millefori come nella foto:


Remoto Pro foto.png


Secondo Passo:

Quello che segue è il software caricato sul JeeNode Locale e su quello Remoto:

/*==================LOCALE===========================*/
// Programma JeeNode LOCALE
#include <JeeLib.h>
// tipo dei dati in arrivo da remoto
typedef struct {int16_t tntc;} dati;
// Il segnale di Trigger arriva su Remoto DIO1
RemoteNode trig (2, RF12_868MHZ,10);
RemotePort UNO (trig, 1);
void setup() {
   Serial.begin(9600);
   while(!Serial);
   rf12_initialize(1, RF12_868MHZ,10);
}
boolean OK=false;
void loop() {
 // se arriva un Trig da seriale mandalo a DIO1 remoto
  if ( Serial.available()>0 && !OK){
      while(Serial.read()>0);    // consuma i caratteri da seriale
      UNO.mode(OUTPUT);
      UNO.digiWrite(HIGH);
      trig.poll(20);
      OK=true;
  }
  float T=0;
  // Se ricevi le misure mostrale (inviale su Serale)
  if ( OK && rf12_recvDone() && rf12_crc==0 && rf12_len==sizeof (dati)) {
     dati* Misure=(dati*)rf12_data;
      char buf[12];
      T=(float)(Misure->tntc)/100;
      dtostrf(T,6,1,buf);
      Serial.print(buf);
      OK=false;
    } 

/*======================REMOTO ===========================*/

 // Programma JeeNode REMOTO
 #include <JeeLib.h>
 #include <avr/sleep.h>
 // stato è lo stato dei PIN trasmesso
 RemoteNode::Data stato;
 // struttura dati da spedire a Nodo Locale
 struct {int16_t tntc;} dati;
 // PIN DIO1 sul quale invio il Trigger (che accende il LED)
 // PIN AIO1 sui quale metto il Sersore NTC
 Port UNO (1);
 MilliTimer timer;
 //=================LOW POWER===========
 static void lowPower (byte mode) {
     // prepare to go into power down mode
     set_sleep_mode(mode);
     // disable the ADC
     byte prrSave = PRR, adcsraSave = ADCSRA;
     ADCSRA &= ~ bit(ADEN);
     PRR |=  bit(PRADC);
     // zzzzz...
     sleep_mode();
     // re-enable the ADC
     PRR = prrSave;
     ADCSRA = adcsraSave;
 }
 // ============MISURE ===================
 // Ro Resistenza nominale di NTC
 #define NTC_NOMINALE 5100      
 // B coefficiente NTC 
 #define NTC_B 4000
 // Ri Resistenza in Serie Inserita
 #define NTC_SERIE 4700
 // Numero di misure per calcolare la media Dvi
 #define N_MISURE 5
 void misure(){
   uint8_t i;
   float Dvi=0;
   float Rt=0;
   // legge N campioni ed esegue la media
     for (i=0; i< N_MISURE; i++) {
       Dvi += UNO.anaRead();
       delay(10);
     }
     Dvi=Dvi/N_MISURE;
     // Determino Rt
     Rt = NTC_SERIE*(1023 / Dvi - 1);
     // determino T
     float T;
     T=log(Rt/NTC_NOMINALE);          // ln(R/Ro)
     T = T/NTC_B;                     // 1/B * ln(R/Ro)
     T = T + 1.0 / (298.15);          // (1/To) + 1/B * ln(R/Ro)
     T = 1.0 / T - 273.15;            // Inverto e sottraggo Kalvin
     dati.tntc=(int16_t)(T*100); 	     // Invio un intero
   }
 void setup() {
     // nodo 2 trasmette e riceve nel gruppo 10
     rf12_initialize(2, RF12_868MHZ,10);
     // Pin del LED DIO1
     UNO.mode(OUTPUT);
     // Pin analogico con NTC AIO1
     UNO.mode2(INPUT);
 }
 boolean OK_trig=false;
 void loop() {
     misure();
     if (!OK_trig && rf12_recvDone() && rf12_crc==0 && rf12_len==sizeof stato) {
        memcpy(&stato, (void*) rf12_data, sizeof stato);
        if (stato.flags & 0x80) {UNO.mode(stato.modes & 0x01);}
        if (stato.flags & 0x40) {UNO.digiWrite(stato.digiIO & 0x01);OK_trig=true;}
        else OK_trig=false; 
        delay(300);
     }
     if (OK_trig){
         // Trigger Ricevuto
         rf12_sleep(RF12_WAKEUP);  // Riaccende la Trasmittente
         MilliTimer aspetta;
         // attende l'uscita da lowpower
         while(!aspetta.poll(5)) {
           rf12_recvDone();
           lowPower(SLEEP_MODE_IDLE);
         }
         // spedisce i dati misurati al nodo LOCALE
         rf12_sendStart(0, &dati, sizeof dati);
         rf12_sendWait(0);
         // spengo la trasmittente
         rf12_sleep(RF12_SLEEP);
         while (!aspetta.poll(1000)) lowPower(SLEEP_MODE_IDLE);
         // Il PIN con LED mi serve per verifica sul Nodo remoto
         UNO.digiWrite(0);
         delay(300);
         OK_trig=false;
     }   
 }

Il software può essere provato anche, attivando il Nodo remoto con la pila, e aprendo il Monitor seriale di Arduino collegato con il JeeNode Locale. All'invio di un carattere di “Trigger” dovrebbe essere mostrata la Misura di temperatura.


Terzo Passo:

Eseguire in Download, scompattarre e caricare la libreria gspread che consente di comunicare con Google Docs. Codificare e salvare, con un editor a piacere, il codice python 'new_NTC_Docs_01.py” per Raspberry :

pi@raspy$ nano new_NTC_Docs_01.py
#Programma Python
import re
import sys
import time
import datetime
from datetime import date
import serial
#Libreria GOOGLE che contiene le API Python per comunicare con Google DOCS
import gspread
# FISSO l'intervallo tra le misure in secondi
DSEC=60
# Memorizza (conserva) l'ultima misura effettuata
HTntc=0.0
#porta USB su cui avviene lo scambio Raspy JeeNode
ser=serial.Serial('/dev/ttyUSB0',timeout=1)
# ===========================================================================
# Google Inserimento Account per accedere a Google DOCS
# ===========================================================================
email       = 'e-mail address'
password    = 'passwd'
spreadsheet = 'MIO_DATI'
#================================================================
# Lettura Ora attuale,
#================================================================
TH=time.time()
print "Le misure avvengono a intervalli di",DSEC," sec."
while 1:
       # cacolo l'intervallo di tempo DT
       T1=time.time()
       DT=T1-TH
       # memorizzo tempo attuale
       Tattuale=time.strftime("%H:%M:%S")
       oggi=date.today()
       # se dal tempo di Start sono trascorsi DSEC
       # esegue la misura
       if (DT>=DSEC):
               TH=T1
               # invio il 'trigger' da Raspy a JeeNode Locale
               ser.write("A")
               ser.flushOutput()
               # leggo da USB la misure NTC
               try:
                 Tntc=float(ser.read(7))
                 Tntc="%6.1f *C" % Tntc
                 HTntc=Tntc
               except :
                 # se fallisce la lettura seriale NON interrompo
                 # ma registro la temperatura precedente
                 AA=ser.readline()
                 print "Lettura Fallita",AA
               # mostra sempre su monitor T, Data e Ora
               print (HTntc)
               print (oggi.strftime("%d/%m/%Y"))
               print (Tattuale)
               # =============================================================$
               # Apertura accesso ai file DOCS
               # =============================================================$
               try:
                 gc = gspread.login(email, password)
                 print "Login su google docs OK!"
               except:
                 print "Login Non effettuato.  Controlla l'indirizzo email e/o$
                 sys.exit()
               #==============================================================
               # Apertura del tuo Worksheet remoto               						  #==============================================================
               try:
                 worksheet = gc.open(spreadsheet).sheet1
                 print "Ho aperto il foglio remoto",spreadsheet
               except:
                 print "Apertura del foglio remoto NON riuscita”
                 sys.exit()
               #=================================================
               # Scrivo Temperature, Data e Ora nello spreadsheet
               #=================================================
               try:
                 values=[oggi.strftime("%d/%m/%Y"),Tattuale,HTntc]
                 worksheet.append_row(values)
               except:
                 print "Non spedisce i dati.  Verifica la connessione."
                 sys.exit()
               print "Tutto OK! Scrivo una riga su %s" % spreadsheet
               print('-')
Quarto Passo:

Creare su Google DOCS, dopo essersi accreditati con Login e Password, un Foglio dati come il seguente di nome 'MIO_DATI' (con la sola prima riga di intestazioni):


Remoto Pro Foglio.png


Quinto Passo:
  • Attivare il Nodo Remoto con la Pila e posarlo nel locale in cui misurare la temperatura;
  • Collegare il Nodo Locale alla porta USB di Raspberry
  • Da Pc collegato con RaspberryPi avviare il programma Python con il seguente comando
pi@raspy$ python new_NTC_Docs_01.py

Dopo 60 secondi (il tempo fissato nel programma python) avrete un output simile al seguente


Remoto Pro Raspy.png


I dati arriveranno al foglio di Google DOCS remoto e li potrete consultare con il Browser da qualsiasi dispositivo collegato in Rete. Verificando su Google un output simile al seguente


Remoto Pro Foglio1.png