domenica 27 gennaio 2019

Controllo del TV con Arduino con Led Infrarossi

Da qualche tempo mi sono trasferito in Grosseto e sono venuto ad abitare in una piccola mansarda nel Parco della Maremma. La mansardina è piccola ed essenziale, ma riesce sempre a nascondere alcune cose fondamentali, come per esempio il Telecomando del TV. Quando lo cerchi non lo trovi mai!
Mosso dall'esigenza di poter controllare la TV senza doversi sempre preoccupare della localizzazione dello scettro dei tempi moderni (leggi telecomando TV) mi sono messo alla ricerca tra i componenti sparsi nei miei cassetti freschi di trasloco (sigh!).
Ho trovato un sensore di gesture che non avevo ancora mai testato. Quale migliore occasione di farci amicizia!??
Il sensore in questione è APDS 9960 che riesce a discriminare ben 6 movimenti diversi, destra,
sinistra, alto, basso, vicino e lontano, sufficienti per poter regolare il volume, l'avanzamento dei programmi, la selezione del canale più ascoltato ed il Mute per escludere velocemente l' ascolto.

Quindi definite le specifiche del progetto sono passato alla ricerca di qualche tutorial in rete per capire meglio utilizzo del sensore, ho trovato questo https://learn.sparkfun.com/tutorials/apds-9960-rgb-and-gesture-sensor-hookup-guide/all  che è molto interessante e mi ha messo in condizione di poter fare subito i primi test.
Caricata la libreria specifica del sensore basta far girare il firmware di test che nella finestra seriale della IDE di Arduino possiamo già vedere riconosciuti i movimenti di UP DOWN LEFT RIGHT NEAR  e FAR.

Ho preso integralmente il firmware di test che fa proprio al mio caso e sono passato a fare dei test sulla parte Infrarossi. Qui ho già una discreta esperienza fatta durante alcuni altri progetti conclusi negli scorsi anni, quindi sono subito andato a scaricarmi la libreria IRremote direttamente dal repository della IDE di Arduino.
Nei file di esempio c'è già tutto quello che serve per poter facilmente cambiare canale ed agire sul volume del tuo televisore.
Ho montato un circuito di test per registrare il codice Infrarosso che trasmette il mio telecomando, collegando un ricevitore IR



Attraverso la lettura dei codici trasmessi dal mio telecomando ed intercettati dal sensore IR qui in foto, ho potuto registrare i codici dei 6 comandi necessari al progetto.
Ho quindi montato il  Led trasmettitore Infrarossi per controllare la correttezza dei comandi inviati al TV dal mio circuito e quando tutto finalmente funziona, mi sono dedicato a montare tutto il software assieme per ottenere la prima versione del progetto funzionante.

Guardando il risultato però non ero ancora completamente soddisfatto, perchè, anche se non sono amante delle lucine messe dappertutto, non avere nessun riscontro delle operazioni effettuate e del corretto riconoscimento del gesture, mi sembrava troppo scarno, allora mi sono deciso a mettere la mano adi nuovo nel cassetto per vedere come abbellire il mio telecomando.
Ho deciso quindi di aggiungere un display 1602 con il suo circuito I2C per evitare di non cablare in modo parallelo  il display stesso.
Naturalmente l'appetito vien mangiando, con un diusplay a disposizione è un peccato non vedere l'ora esatta, viene da sè che diventa indispensabile inserimento nel progetto di una RTC per fornire l'ora esatta al sistema e poterla quindi avere a disposizione sul display a cristalli liquidi.
Anche con l'RTC ho già fatto amicizia durante una serie di altri progetti, quindi sono partito avvantaggiato!!, nei file di esempio della libreria RTClib ci sono tutti ritagli software che sono necessari per poter programmare l'ora esatta (una tantum) e interrogare la RTC per visualizzare sul display l'ora sul display ad ogni loop del firmware.

Per quanto riguarda il firmware per la gestione del display ho utilizzato questa guida, molto utile per l'uso congiunto della interfaccia I2C con il display a cristalli liquidi 1602...https://www.instructables.com/id/Using-PCF8574-backpacks-with-LCD-modules-and-Ardui/

quindi ho istallato la seguente libreria  https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads

Questo e' il risultato del primo prototipo completo montato sulla scrivania. Nel pomeriggio (forse) provvedero' alla posa in una scatolina per mettere in uso il sistema completo. (vedremo, di solito alla catola non ci arrivo mai, ma passo subito al prossimo progetto!! vedrfemo... e vedrete, forse)

Sotto alle foto il firmware funzionante

   





















codice:
*****************************************************

//sistema di trasmissione  dei codici IR della mia TV gestito da sensore di movimento
//sono registrati alcuni movimenti che corrispondono a comendi TV definiti
//dal basso all'alto == Aumenta Volume ++   funzione alzaVolume     2FD58A7
//dal'alto al basso == Abbassa Volume --    funzione abbassaVolume  2FD7887
// da destra a sinistra == Programmi --     funzione Programmameno  2FDD827
//da sinistra a destra == Programmi ++      funzione Programmapiu   2FDF807
//da vicino a lontano veloce                funzione VolumeNO       2FD08F7
//da lontano a vicino veloce                funzione Canale 48  2FD20DF  +  2FD10EF
// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
//Sensore APDS9960 connesso ad SDA SCL 3,3Volts GND e PIN 2 interrupt
//IR LED connesso a PWM pin 3.

#include
#include "RTClib.h"
#include  
#include

LiquidCrystal_I2C  lcd(0x26,2,1,0,4,5,6,7);  // set the LCD address to 0x27 for a 16 chars and 2 line display

#include
#include
#include
IRsend irsend;
// Pins
#define APDS9960_INT    2 // Needs to be an interrupt pin
// Global Variables
SparkFun_APDS9960 apds = SparkFun_APDS9960();
int isr_flag = 0;
RTC_DS1307 rtc;

void setup() {
   lcd.begin (16,2); // for 16 x 2 LCD module
   lcd.setBacklightPin(3,POSITIVE);
   lcd.setBacklight(HIGH);
   lcd.backlight();
   // Set interrupt pin as input
  pinMode(APDS9960_INT, INPUT);

  // Initialize Serial port
  //Serial.begin(9600);
    // Initialize interrupt service routine
  attachInterrupt(0, interruptRoutine, FALLING);

  // Initialize APDS-9960 (configure I2C and initial values)
  if ( apds.init() ) {
    lcd.print(F("9960 init complete"));
        delay(1000);

  } else {
    lcd.print("Some went wrong");
        delay(1000);

  }
   lcd.clear();
  // Start running the APDS-9960 gesture sensor engine
  if ( apds.enableGestureSensor(true) ) {
    lcd.print("Gest now running");
        delay(1000);

  } else {
    lcd.print("Int APDS wrong");
        delay(1000);

  }
   lcd.clear();

      if (! rtc.begin()) {
    lcd.print("NON TROVO RTC");
    while (1);
  }
  lcd.clear();
  if (! rtc.isrunning()) {
    lcd.print("RTC NOT run!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    delay(1500);
    }else{lcd.clear(); lcd.print("RTC is OK");delay(1500);}
    lcd.clear();
    lcd.home (); // set cursor to 0,0
    lcd.print(" TecnoGeppetto");
    delay(1000);
    lcd.setCursor(1,1);
    lcd.print("telecomando TV");
//****************************************************************
    //per rimettere l'ora se rtc ha perso qualche colpo!!
   // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
//****************************************************************

   
}

void loop() {
  if( isr_flag == 1 ) {
    detachInterrupt(0);
    handleGesture();
    isr_flag = 0;
    attachInterrupt(0, interruptRoutine, FALLING);
  }
 
   DateTime now = rtc.now();
   lcd.setCursor(0,0);
   lcd.print("ORARIO: ");
   lcd.print(now.hour());
   lcd.print(":");
   lcd.print(now.minute());
   lcd.print(":");
   lcd.print(now.second());
}



void alzaVolume(){
//Qui inserire il RAW del Volume ++  2FD58A7
for (int i = 0; i < 3; i++) {
    irsend.sendNEC(0x2FD58A7, 32);
    delay(40);
  }

}

void abbassaVolume(){
//Qui inserire il RAW del Volume --  2FD7887
for (int i = 0; i < 3; i++) {
    irsend.sendNEC(0x2FD7887, 32);
    delay(40);
  }

}


void Programmapiu(){
//Qui inserire il RAW del Programmi ++  2FDD827
for (int i = 0; i < 3; i++) {
    irsend.sendNEC(0x2FDD827, 32);
    delay(40);
  }

}

void Programmameno(){
//Qui inserire il RAW del Programmi --  2FDF807
for (int i = 0; i < 3; i++) {
    irsend.sendNEC(0x2FDF807, 32);
    delay(40);
  }

}


void VolumeNO(){
//Qui inserire il RAW del VolumeNO  .. 2FD08F7
for (int i = 0; i < 3; i++) {
    irsend.sendNEC(0x2FD08F7, 32);
    delay(40);
  }

}


void Canale48(){
//Qui inserire il RAW del Canale48 :  2FD20DF  +  2FD10EF
for (int i = 0; i < 3; i++) {
    irsend.sendNEC(0x2FD20DF, 32);
    delay(40);
  }
for (int i = 0; i < 3; i++) {
    irsend.sendNEC(0x2FD10EF, 32);
    delay(40);
  } 

}
void interruptRoutine() {
  isr_flag = 1;
}

void handleGesture() {
    if ( apds.isGestureAvailable() ) {
    switch ( apds.readGesture() ) {
      case DIR_UP:
      lcd.clear();
      lcd.setCursor(0,1);
      lcd.print("LastCom= Vol +");
       alzaVolume();
        break;
      case DIR_DOWN:
      lcd.clear();
      lcd.setCursor(0,1);
      lcd.print("LastCom= Vol -");
        abbassaVolume();
        break;
      case DIR_LEFT:
      lcd.clear();
      lcd.setCursor(0,1);
      lcd.print("LastCom= Prog -");
      Programmameno();
        break;
      case DIR_RIGHT:
      lcd.clear();
      lcd.setCursor(0,1);
      lcd.print("LastCom= Prog +");
      Programmapiu();
        break;
      case DIR_NEAR:
      lcd.clear();
      lcd.setCursor(0,1);
      lcd.print("LastCom= NO Vol");
      VolumeNO();
        break;
      case DIR_FAR:
      lcd.clear();
      lcd.setCursor(0,1);
      lcd.print("LastCom= C 48");
      Canale48();
        break;
      default:
      lcd.clear();
      lcd.setCursor(0,1);
      lcd.print("LastCom= NONE !");
    }
  }
}



venerdì 21 settembre 2018

Orange Pi 2G-IoT e Raspbian - Istallazione e settaggi

Oggi mi sono dedicato alla configurazione del sistema su Orange Pi 2G-IOT, che qualche giorno fa mi è arrivata dalla fabbrica.
Dopo aver recuperato il file del sistema operativo direttamente dal sito del produttore qui ho creato la microSD, nella maniera tradizionale, come specificato qui .

Costruita la SD, l'ho inserita nella OrangePi, ho collegato la seriale per il debug e collegato la scheda alla alimentazione fornita da un alimentatore 5V 2A

Aperto una finestra di terminale con Putty su windows, mi sono messo in ascolto sulla seriale ed ho collegato l'alimentazione.

Tutto regolare, partito il sistema che arriva velocemente al login.

Si accede con root e orangepi come user e password.

Appena entrati nel sistema vieni consigliato di settare l'ambiente con il comando
sudo OrangePi_Settings
(per i miei gusti un po' troppo lungo e con troppe maiuscole, comunque....)

Il menu che appare ti invita (non ti fa fare altro!) a configurare il WiFi.

La prima volta, dopo aver aggiunto il nome del mio network interno e configurato l'accesso con la password, al reboot mi si è impallato tutto rimanendo appeso durante la fase di startup nella ricerca della scheda di rete durante il collegamento con l'access point.

Per velocizzare ho ricostruito la SD dal file originale e riproposto la medesima procedura, che al secondo tentativo sembra funzionare regolarmente
Quindi impostato nome del AP e password e fatto il reboot, adesso si logga regolarmente nel network casalingo e consente l'accesso attraverso la seriale di debug.

Sono quindi passato a collegare la OrangePi via ssh dalla rete interna.

Tutto sembra funzionare regolarmente

Utilizzare Raspberry Pi come Client WiFi e server DNS

Il sistema che vado configurando e' questo:

una Raspberry Pi che collega via WiFi un Router WiFi con server dhcp che ha accesso ad internet;
la Raspberry Pi attraverso la sua presa di rete ed uno switch di rete, condivide la connessione intenet con tutta la rete della mia mansarda.
In sostanza per ottenere la navigazione internet dalla mansarda dove abito, ho dovuto fare un link con l'appartamento sottostante dove risiede la linea telefonica ed il modem ADSL.

Come spesso succede per ottenere il risultato desiderato ho dovuto fare un mix di tutorial, l'mportante comunque e' sempre riuscire ad arrivare alla meta!Vedi le tribolazioni per il settaggio della chiavetta WiFi della Raspberry utilizzata come Client in questo post  


Comportandosi come router, la Raspberry Pi dovra' assegnare gli indirizzi ip alle macchine che la connetteranno, quindi per fare questo ho dovuto configurare il programma DNSMASQ.

Iniziamo con scaricare il software con

sudo apt-get install dnsmasq

poi si deve modificare il file /etc/dnsmasq.conf

sudo nano /etc/dnsmasq.conf

Inserendo prima della fine del file queste righe di codice:

interface=eth0
listen-address=192.168.1.1,127.0.0.1
dhcp-range=192.168.1.50,192.168.1.150,12h


In questo modo il dnsmasq assegna un numero ip variabile con un lease time di 12 ore, nel range di numeri  da 50 a 150 sulla interfaccia eth0 (la rete cablata collegata allo switch)

Poi ho attivato il port forwording tra le porte, modificando questo file

sudo nano /etc/sysctl.conf

 andando a cambiare, togliendo il #, questa riga del file di configurazione.

net.ipv4.ip_forward = 1

A questo punto diventiamo root con

sudo su

ed andiamo a modificare la trabella di routing con il comando

iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE


per controllare che tutto sia ok

iptables -t nat -L

Dovrebbe restituire questa scritta


Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- anywhere anywhere


Adesso  lo andiamo a scrivere con questo comando:

echo 1 > /proc/sys/net/ipv4/ip_forward


questa ultima istruzione deve essere data assolutamete con i privilegi di root

Per rendere permanenti questi comandi che altrimenti si resetterebbero al riavvio,viene utilizzata la tecnica di  scrivere tutto su un file e caricarlo ad ogni riavvio in quresto modo:

cd /etc/network
iptables-save > condivisione-internet.rules
touch attiva-condivisione-internet
chmod u+x attiva-condivisione-internet
nano attiva-condivisione-internet

inseriamo questo contenuto:

iptables-restore < /etc/network/condivisione-internet.rules
echo 1 > /proc/sys/net/ipv4/ip_forward

Ora modifichiamo il file /etc/network/interfaces

nano interfaces

ed aggiungere, nella configurazione dell'ingterfaccia wlan0 questa riga di codice che al boot della macchina fa leggere alla Raspberry Pi la configurazione salvata nel file prodotto sopra :

pre-up /etc/network/attiva-condivisione-internet


Se non mi sono dimenticato nulla e non ci sono errori, al reboot la Raspberry Pi si colleghera' al suo AP configurato nel wpa_supplicant e condividera' la connessione internet tramite la sua presa di rete


Di seguito i link da cui ho fatto osmosi:
https://www.lffl.org/2016/04/guida-dnsmasq-condividere-connessione-via-ethernet.html
http://vilnet.it/argo/linux-guide-trucchi-15/news/condividere-connessione-internet-terminale-321/#