PARCO

Da raspibo.
PARCO2.jpg
PARCO1.jpg
PARCO
Poor Arduino Radioio COmunication
un trasmettitore low power "parco" nei consumi,
quasi "compatibile" bluetooth 4.0.


Indice

Da dove nasce il progetto?

Dalla necessità di avere un sistema per leggere sensori con un sistema

  • a basso consumo, alimentabile a batteria
  • con costi ridotti
  • wireless

Che cosa non si riesce a fare?

  • una trasmissione bluetooth 4 vera e propria
  • trovare board già completamente assemblate
  • tramettere più di pochi byte per volta
  • rendere sicura la comunicazione

Teoria

  • Qualche info su Bluetooth 4, anche detto bluetooth low energy.

Low energy è la parola chiave da cui ho iniziato a cercare. Purtroppo il protocollo è complesso e le periferiche costose e difficili da programmare. Altro punto a favore di ble è che sono ammessi pacchetti broadcast cioè senza necessità di accoppiare i devices. Wikipedia

  • Ho trovato questa interessante pagina che spiega come un modulo nrF2401+ possa essere utilizzato per trasmettere semplici annunci in formato bluetooth 4.0.

La potenza di questi moduli è minima, e più di questo non riescono a fare, ma è possibile usare il nome con cui si annuncia il nostro nodo per tasmettere alcuni byte. Blog dmitry.gr

  • Sui commenti in fondo alla pagina segnalata sopra, qualcuno ha anche provveduto a creare una libreria per Arduino. BTLE Arduino library
  • Per quanto riguarda arduino è necessario ridurre al minimo i consumi, quindi solo una scheda minimale come Arduino pro mini con alimentazione a 3.3V (e clock a 8Mhz) e utilizzo di sleep mode.

Codice Arduino

E' un assemblaggio di parti di codice presi dagli esempi della libreria con qualche piccolo adattamento per ridurre i consumi mandando il micro in sleep. La trasmissione avviene ogni 8 secondi circa, è adatta per sensori che misurano grandezze che hanno variazioni lente nel tempo. E' anche possibile disabilitare lo sleep se il "nodo" non ha necessità di risparmio energetico.


#include <SPI.h>
#include <RF24.h>
#include <BTLE.h>
#include <stdio.h>

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>

RF24 radio(8,7);    //pin D8 -> CE  ---- pin D7 -> CSN

BTLE btle(&radio);

char buffer[14] = "";
char fix[7] = "acqua";
int x=0;
int force;
int batt;
int trasmetti=1;

//Questa funzione mette il microcontrollore in modalità basso consumo per permettere una alimentazione a batterie
void enterSleep(void)
{
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); /* EDIT: could also use SLEEP_MODE_PWR_DOWN for lowest power consumption. */
  sleep_enable();                      // Abilita la modalità basso consumo
  sleep_mode();                        /* Now enter sleep mode. */
  /* The program will continue from here after the WDT timeout*/
  sleep_disable(); /* First thing to do is disable sleep. */
  /* Re-enable the peripherals. */
  power_all_enable();
}

//Gestione del watch dog timer, il micro viene settato per essere risvegliato dal watch dog timer ogni 8 secondi
ISR(WDT_vect)
{
  sleep_disable(); //Disable Sleep on Wakeup, quando si verifica l'interrupt del watchdog
  trasmetti=1;     //setta la variabile trasmetti ad 1 per indicare che il micro è stato risvegliato e che è necessario trasmettere
}


void setup() {
  sleep_disable();                     //Disabilita la modalità sleep durante il boot
  power_all_enable();                  //Abilita tutte le periferiche
  analogReference(INTERNAL);           //Configurazione della tensione di rifermento per la lettura dei sensori analogici
  randomSeed(analogRead(3));           //???
  Serial.begin(9600);
  while (!Serial) { 
  }
  Serial.println("Arduino BTLE");      //Notifica su porta seriale il boot, serve anche come debug per vedere quando il micro è attivo senza avere collegato il pc.

  //Settaggio variabili per modalità basso consumo
  MCUSR &= ~(1<<WDRF); /*Clear the reset flag. */
  WDTCSR |= (1<<WDCE) | (1<<WDE); /*In order to change WDE or the prescaler, we need to set WDCE (This will allow updates for 4 clock cycles). */
  WDTCSR = 1<<WDP0 | 1<<WDP3;     /* 8.0 seconds */
  /* set new watchdog timeout prescaler value */
  WDTCSR = 1<<WDP2;               /*WDT interrupt every 250 milliseconds */
  WDTCSR |= _BV(WDIE);            /*Enable the WD interrupt (note no reset). */
  //sei(); 

}

void loop() {
  if (trasmetti==1) {            //Verifica se è necessario tramettere
    btle.begin(buffer);          //inizia la trasmissione btle
    btle.advertise(0,0);
    Serial.print(" ");
    btle.hopChannel();

    //pinMode(10, OUTPUT);                         
    digitalWrite(10, HIGH);                       // per ridurre i consumi, il sensore resistivo è collegato all'uscita di un pin che viene attivato alto solo prima di iniziare la misura
    batt=analogRead(A1);                          // leggo la tensione della batteria per trasmetterla e permettere il monitoraggio della carica
    force=analogRead(A7);                         // leggo il sensore di forza resistivo 
    digitalRead(10);                              // disabilito l'alimentazione del sensore resistivo
    sprintf(buffer,"%3u%s% 4u",batt, fix,force);  // creo la stringa con i dati da trasmettere ---- ATTENZIONE il buffer ha una dimensione limitata a 13 caratteri se la stringa è più lunga non viene trasmesso nulla!!!!!
    Serial.println(buffer);                       // trasmetto la stringa su seriale, utile anche per un debug visivo quando il sensore è in posizione


    //  buffer[7]++;
    trasmetti=0;                                  // Azzeramento variabile trasmetti dopo che la trasmissione è avvenuta
    //Serial.println("enter sleep"); 
    radio.powerDown();                            // Spengo il modulo radio
    sleep_enable();                               // Enable Sleep Mode del micro
    enterSleep();                                 // Sleep
  }  
  else {
    sleep_enable();                               // Se non è ora di trasmettere ..... Enable Sleep Mode      
    enterSleep();
  }  

}

Schema

PARCO schema elettrico

Software pc

Attenzione il pc deve avere una periferica compatibile con bluetooth 4.0, i vecchi pc ne sono sprovvisti. Ho visto in vendita chiavette usb, ma non le ho testate.

L'ho scritto in python, ma sono sicuro sia migliorabile.

#!/usr/bin/python
import os 
import subprocess
parole = subprocess.check_output("/bin/hciconfig hci0 down", shell=True)
parole = subprocess.check_output("/bin/hciconfig hci0 up", shell=True)
parole = subprocess.check_output("/usr/bin/timeout -s SIGINT 60s /usr/bin/hcitool lescan --duplicates | grep dist", shell=True)
#parole="15:01:13:18:22:37 874dist.5167"
print "Parole:" + str(parole)
if parole != 2 :
 indirizzo=parole[:17]
 print "Indirizzo: "
 print indirizzo
 print "Liv batteria: "
 liv_batteria=parole[18:21]
 print liv_batteria
 int_liv_batteria=int(liv_batteria)
 str_liv_batteria=liv_batteria
 print "liv_batteria"
 print int_liv_batteria
 print "sensore:"
 int_sensore=int(parole[26:30])
 str_sensore=parole[26:30]
 print int_sensore


Ricevitore con Arduino

Basta guardare negli esempi della libreria FLOE

Debug

Per chi ha un telefonino con interfaccia bluetooth 4 è possibile fare un debug usando l'app Nrf Master di Nordic il produttore del chip radio.

Il mio nodo PARCO si chiama acqua, la batteria è carica a 943/1023 nella prima schermata e 965/1023 nella seconda.

PARCO è quel trattino rosso che si vede nella figura centrale, anche se trasmette circa ogni 8 secondi l'app non riesce a intercettare tutti i messaggi.

Nella prima figura il sensore analogico sta leggendo 0 (è un sensore di forza), nell'ultima legge 1023 perchè sto premendo sul sensore.

Nrfmaster1.png Nrfmaster2.png Nrfmaster3.png

Test sul campo

Ho testato un paio di questi sensori per diversi mesi usando batterie alcaline e la durata è estremamente interessante siamo nell'ordine di qualche mese.

E' necessario rimuovere il led di alimentazione sulla board Arduino.

Riferimenti

Strumenti personali
Namespace

Varianti
Azioni
Navigazione
Strumenti