miércoles, 21 de mayo de 2014

Proyecto RPi





Este post es creado como parte del Proyecto Final de Introducción al Raspberry Pi.



Que busca el proyecto:

  • Complementar el bot de twitter @Rpi_Twiteando con acciones propias del mundo real. Dando inicio a una serie de proyectos de domotica.
  • Twittear y dar alertas pushover de Temperatura y humedad (Oficina y Cuarto 1)
  • Encender abanicos en rack cuando la temperatura sea critica 29ºC
  • Encender luces de rack cuando la luz sea muy baja

Hardware


Software



Instalar (indispensable)

Wiring PI

cd ~
sudo apt-get install git-core build-essential
git clone git://git.drogon.net/wiringPi
cd wiringPi
./build

ttytter

cd ~ apt-get install curlwget http://www.floodgap.com/software/ttytter/dist2/2.0.00.txtmv 2.0.00.txt ttytterchmod a+x ttyttermv ttytter /usr/bin/
Ejecutar ttytter y seguir los pasos
ttytter

Festival

aptitude install festivalwget http://forja.guadalinex.org/frs/download.php/154/festvox-sflpc16k_1.0-1_all.debdpkg -i festvox-sflpc16k_1.0-1_all.deb
Ejemplo 
echo Hola, $USERNAME | festival --tts


Conexiones


Sensor de Humedad




WiringPi
RPI
DAT
7
7
VCC 3,3v
-
1
GND
-
6

Sensor de humedad y temperatura DTH11



Para poder usar el modulo DTH11 con el raspberry pi necesite compilar este script que encontré en esta web 

Creamos el archivo: 
nano dth11.c
Y escribimos el siguiente código:
Nota: este código esta el repositorio github que publicaremos adelante.
------------------------------------------ 
CODIGO DESDE AQUI - Archivo dth11.c
------------------------------------------
 
 //Incluimos librerias necesarias
#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

//Definimos constantes
#define MAX_TIME 85
#define DHT11PIN 7
#define ATTEMPTS 5

//Definimos un vector global
int dht11_val[5]={0,0,0,0,0};

/////////////////////////////////////////////////////////////
//Funcion principal para leer los valores del sensor.
int dht11_read_val(){
 uint8_t lststate=HIGH;
 uint8_t counter=0;
 uint8_t j=0,i;
 for(i=0;i<5;i++){
  dht11_val[i]=0;
 }
 pinMode(DHT11PIN,OUTPUT);
 digitalWrite(DHT11PIN,LOW);
 delay(18);
 digitalWrite(DHT11PIN,HIGH);
 delayMicroseconds(40);
 pinMode(DHT11PIN,INPUT);
 for(i=0;i<MAX_TIME;i++){
  counter=0;
  while(digitalRead(DHT11PIN)==lststate){
   counter++;
   delayMicroseconds(1);
   if(counter==255){
    break;
   }
  }
  lststate=digitalRead(DHT11PIN);
  if(counter==255){
   break;
  }
  //Las 3 primeras transiciones son ignoradas
  if((i>=4)&&(i%2==0)){
   dht11_val[j/8]<<=1;
   if(counter>16){
    dht11_val[j/8]|=1;
   }
   j++;
  }
 }
  
 // Hacemos una suma de comprobacion para ver si el dato es correcto. Si es asi, lo mostramos
 if((j>=40)&&(dht11_val[4]==((dht11_val[0]+dht11_val[1]+dht11_val[2]+dht11_val[3])& 0xFF))){
  printf("%d.%d,%d.%d\n",dht11_val[0],dht11_val[1],dht11_val[2],dht11_val[3]);
  return 1;
 }else{
  return 0;
 }
}

////////////////////////////////////////////////////////////////
//Empieza nuestro programa principal.
int main(void){
 //Establecemos el numero de intentos que vamos a realizar
 //la constante ATTEMPTS esta definida arriba
 int attempts=ATTEMPTS;
 
 //Si la libreria wiringPi, ve el GPIO no esta listo, salimos de la aplicacion
 if(wiringPiSetup()==-1){
  exit(1);
 }
 
 while(attempts){
  //Intentamos leer el valor del gpio, llamando a la funcion
  int success = dht11_read_val();
  
  //Si leemos con exito, salimos del while, y se acaba el programa
  if (success){
   break;
  }
  
  //Si no lee con exito, restamos 1, al numero de intentos
  attempts--;
  
  //Esperamos medio segundo antes del siguiente intento.
  delay(500);
 }
 return 0;
}
 
------------------------------------------ 
CODIGO HASTA AQUI-------- FIN DE ARCHIVO dth11.c
------------------------------------------ 

Luego compilamos
Nota: ojo que aunque esta en C usa la librebria wiringPI
gcc -o dth11 dth11.c -L /usr/local/lib -l wiringPi

el resultado lo ponemos a disposición de todos los usuarios

cp dth11 /usr/bin

Relay



WiringPi
RPI
VCC 5v
-
2
CH1
4
16
CH2
6
22
GND
-
9

Relay de 5v y Canales


Para el relay cree fan.sh en la carpeta /opt/ que tiene la siguiente estructura
Nota: este código esta el repositorio github que publicaremos adelante.
#!/bin/bash
if [ $1 -eq 1 ] ; then
    gpio mode 6 out
    gpio write 6 1
else
    gpio write 6 0
    gpio reset
fi

Esto para controlar cuando se enciende o se apagar el abanico
ej
/opt/fan.sh 1 // enciende del abanico


 Foto celda



WiringPi
RPI
VCC 3,3v
-
17
DATA
5
18
GND
-
25

Para poder hacer que la foto celta funcione bien se necesita un capacitor 1uF que se coloca en medio del GND y el cable de datos.   Y una resistencia de 220Ohm entre el positivo y la foto celda.

Basado en la web de adafruit

El código fuente es el siguiente:
Notaeste código esta el repositorio github que publicaremos adelante.
#!/usr/bin/env python
# Archivo luz.py
import RPi.GPIO as GPIO, time, os
DEBUG = 1
GPIO.setmode(GPIO.BCM)
on = 0
MAX=5200
PIN=23
GPIO.setup(PIN,GPIO.OUT)
def RCtime (RCpin):
        reading = 0
        GPIO.setup(RCpin, GPIO.OUT)
        GPIO.output(RCpin, GPIO.LOW)
        time.sleep(0.1)
GPIO.setup(RCpin, GPIO.IN)        # This takes about 1 millisecond per loop cycle        while (GPIO.input(RCpin) == GPIO.LOW):                reading += 1        return reading
while True:        print RCtime(24)     # Read RC timing using pin #18        luz = RCtime(24)        if luz > MAX:                GPIO.output(PIN,True)                on = 1
      if luz < MAX and on == 1:                GPIO.output(PIN,False)                       on = 0

               

Sensor TMP36, Kit RF 433Mhz y Arduino UNO


TMP36


Arduino
RPI
1
5V
-
2
A0
-
3
GND
-

Transmiter 433Mhz



Arduino
RPI
ATAD
D10

VCC
5V
-
GND
GND
-

arduino uno transmiter 433mhz tmp36




Para el arduino Uno se debe descargar e instalar la siguiente librería  me base en el blog para realizar esta parte del proyecto.

El código del arduino es
Nota: este código esta el repositorio github que publicaremos adelante.
#include <RCSwitch.h>

#include <rcswitch .h="">
RCSwitch mySwitch = RCSwitch();
long envio = 0;
// Declaracion de variables
float tempC;
int tempPin = 0; // Definimos la entrada en pin A0
void setup()
{
// Abre puerto serial y lo configura a 9600 bps
Serial.begin(9600);
mySwitch.enableTransmit(10);
}
void loop()
{
// Lee el valor desde el sensor * 0.00482814
tempC = (analogRead(tempPin)* 5.0) / 1024;
tempC = ((tempC - 0.5) * 100.0) + 4; // mas x es para calibrar mas o menos la temperatura
mySwitch.send(tempC, 8);
// Espera cinco segundo para repetir el loop
delay(5000);
}



Reciver 433Mhz



WiringPi
RPI
VCC 5v
-
4
DATA1
0
11
DATA 2
-
-
GND
-
6


reciver 433mhz raspberry pi


Baje el software c++ y wiringPI basado en este blog

realizando las siguientes acciones

mkdir -p /usr/src/rasp433/
cd /usr/src/rasp433/
wget https://www.dropbox.com/s/faw6y1lzguhgxvx/rpi.zip
unzip rpi.zip
gcc rfreceive.cpp RCSwitch.cpp -o rfreceive -lwiringPi
gcc rftester.cpp RCSwitch.cpp -o rftester -lwiringPi


y modifique el código de rfreceive.cpp para que solo devolviera un numer de la siguiente manera:
Notaeste código esta el repositorio github que publicaremos adelante.
/*
rfreceive.cpp
by Sarrailh Remi
Description : This code receives RF codes and trigger actions

Modificado por @bettocr
*/
#include "RCSwitch.h"
#include <stdlib.h>
#include <stdio.h>
RCSwitch mySwitch;
int pin; //Pin of the RF receiver
int codereceived; // Code received
char buffer[200]; // Buffer for the command
int dato;
int salir;
int main(int argc, char *argv[]) {
if(argc == 2) { //Verify if there is an argument
pin = atoi(argv[1]); //Convert first argument to INT
// printf("PIN SELECTED :%i\n",pin);
}
else {
printf("No PIN Selected\n");
printf("Usage: rfreceive PIN\n");
printf("Example: rfreceive 0\n");
exit(1);
}
if(wiringPiSetup() == -1) { //Initialize WiringPI
printf("Wiring PI is not installed\n"); //If WiringPI is not installed give indications
printf("You can install it with theses command:\n");
printf("apt-get install git-core\n");
printf("git clone git://git.drogon.net/wiringPi\n");
printf("cd wiringPi\n");
printf("git pull origin\n");
printf("./build\n");
exit(1);
}
mySwitch = RCSwitch(); //Settings RCSwitch (with first argument as pin)
mySwitch.enableReceive(pin);
dato = 0;
salir =1;
while(salir) { //Infinite loop
if (mySwitch.available()) { //If Data is detected.
dato = mySwitch.getReceivedValue();
if(dato > 0){
printf("%i", dato );
salir = 0;
}
}
mySwitch.resetAvailable();
}
}

ALERTAS


Para las alertas a pushover cree un script /opt/aviso.sh
Que recibe 2 parámetros el titulo del mensaje y el mensajes
Notaeste código esta el repositorio github que publicaremos adelante.
#!/usr/bin/env sh
URL="https://api.pushover.net/1/messages.json"
API_KEY="Su-api-key"
USER_KEY="Su-user-key"
DEVICE="all"
SOUND="magic"
PRIORITY="0"
TITLE="${1}"
MESSAGE="${2}"
curl \
-F "token=${API_KEY}" \
-F "user=${USER_KEY}" \
-F "device=${DEVICE}" \
-F "title=${TITLE}" \
-F "message=${MESSAGE}" \
-F "sound=${SOUND}" \
-F "priority=${PRIORITY}" \
"${URL}" > /dev/null 2>&1
ttytter -status="Send an Alert Message by pushover"

Y las alertas se muestran asi:


  

 



Control de temperatura oficina

Notaeste código esta el repositorio github que publicaremos adelante.
#!/bin/bash
TEMP=`/usr/bin/dth11 | awk -F ",*" '{ print $2}'`
HUME=`/usr/bin/dth11 | awk -F ",*" '{ print $1}'`
TMP=`cat /tmp/dht11.txt` #temperatura anterior
FAN=`cat /tmp/fan` #abanico encendido
FECHA=`date`
DIF1=`echo "$TMP-$TEMP" | bc`
DIF=${DIF1/\.*}
TEMP1=${TEMP/\.*}
TMP1=${TMP/\.*}
DATO=${#TEMP1}
TMAX=28 #temperatura maxiama
logger -i "TEMP "$TEMP" TEMP1 "$TEMP1" TMP "$TMP1" DATO "$DATO" DIF "$DIF" DIF1 "$DIF1" fan "$FAN
if [ $DATO -ne 0 ] && [ $TEMP1 == $TMP1 ] ; then
logger -i "DTH11 funciono"
# echo $FECHA" "$TEMP" "$HUME >> /home/pi/prueba.txt
else
if [ $DATO -ne 0 ] ; then
echo $FECHA" "$TEMP" "$HUME >> /home/pi/prueba.txt
echo $TEMP > /tmp/dht11.txt
echo "Temperatura: "$TEMP" grados centigrados, Humedad: "$HUME"%, Temperatura anterior: "$TMP" grados centigrados " |iconv -f utf-8 -t iso-8859-1| festival --tts
logger -i "DTH11 funciono"
if [ $DIF -le -2 ] || [ $DIF -ge 2 ] ; then
/opt/aviso.sh "Temperatura Oficina" "Aumento de mas de 2 Grados en la oficina. "$TEMP" Grados Centigrados"
ttytter -status="Office temperature "$TEMP"ºC, Humidity "$HUME"%"
logger -i "mensaje"
fi
if [ $TEMP1 -ge $TMAX ] && [ $FAN -eq 0 ] ; then
sudo /opt/fan.sh 1
echo 1 > /tmp/fan
/opt/aviso.sh "Temperatura Oficina" "La Temperatura oficina "$TEMP" Grados he encendio los abanidos del rack"
logger -i "Aabanicos encendidos"
fi
if [ $TEMP1 -lt $TMAX ] ; then
sudo /opt/fan.sh 0
echo 0 > /tmp/fan
logger -i "Abanicos Apagados"
/opt/aviso.sh "Temperatura Oficinia" "apaga los abanicos"
fi
fi
fi

Tweet

temperatura cuarto 1

Notaeste código esta el repositorio github que publicaremos adelante.
#!/bin/bash
TEMP=`cat /tmp/RFtemp0.txt`
TMP=`cat /tmp/cuarto1.txt`
FECHA=`date`
DIF=`echo $TMP-$TEMP | bc`
DATO=${#TEMP}
DATO1=${#TMP}
TMAX=29 #temperatura maxiama
TMIN=15
logger -i "Cuarto 1 TEMP "$TEMP" TMP "$TMP" DATO "$DATO" DIF "$DIF
if [ $DATO -ne 0 ] && [ $DATO1 -ne 0 ] ; then
if [ $TEMP == $TMP ] ; then
logger -i "Cuarto 1 sin cambios"$TEMP" "$TMP
# echo $FECHA" "$TEMP" "$HUME >> /home/pi/prueba.txt
else

echo $FECHA" Cuarto 1 "$TEMP" " >> /home/pi/prueba.txt
echo $TEMP > /tmp/cuarto1.txt
echo "Temperatura Cuarto uno: "$TEMP" grados "" Temperatura anterior: "$TMP" grados " |iconv -f utf-8 -t iso-8859-1| festival --tts
logger -i "Cuarto 1 con cambios"
if [ $DIF -le -2 ] || [ $DIF -ge 2 ] ; then
/opt/aviso.sh "Temperatura Oficina" "Aumento de mas de 2 Grados en la oficina. "$TEMP" Grados Centigrados"
#ttytter -status="Room1 temperature "$TEMP"º"
logger -i "mensaje pushover y twitter"
fi
if [ $TEMP -ge $TMAX ] && [ $FAN -eq 0 ] ; then
/opt/aviso.sh "Temperatura Cuarto 1 "$TEMP" Grados"
logger -i "Esta muy caliente "$TEMP
fi
if [ $TEMP -le $TMIN ] ; then
/opt/aviso.sh "Temperatura Cuarto 1 "$TEMP" Grados"
logger -i "Esta muy frio "$TEMP
fi
fi

Tweet





Crontab

* * * * * /opt/temp.sh
* * * * * /usr/bin/rfrecivetxt 0 > /tmp/RFtemp0.txt
* * * * * /opt/temp-cuartos.sh  


Otros Archivos a crear

touch /tmp/dht11.txt
touch /tmp/fan
touch /tmp/RFtemp0.txt
touch /tmp/cuarto1.txt


Dificultades del proyecto 

  • La mayor dificultad que encontré fue la parte electrónica ya que no conozco mucho a varios entre ellos la comunidad Arduino Costa Rica que respondieron siempre mis preguntas.

Mejoras al proyecto

  • Cambiar el arduino por un attiny85, para reducir tamaño. creando un emisor de temperatura para cada cuarto.
  • Colocar cada uno de estos emisores en un cuarto y otro fuera de la casa.
  • Probar encendido y apagado de abanicos y luces se pueden hacer con estos mismo dispositivos.
  • Actualmente el sistemas mantiene un load de un 4.17, en otros RPi parte de Rpi_twiteando tienen un pico de 5.53 y un minimo de 0.53 de load, por lo que hay que buscar que hace que el load este alto.
  • Cuando el Arduino se apaga o pierde conexion la radio frecuencia, el rfreceive sobre carga el sistema.

Costo del Proyecto


Componente
Unidades
Precio Unitario
Precio total
Raspberry Pi
1
$42
$42
Arduino UNO
1
$30
$30
SD 4Gb
1
$13
$13
Relay 2Chs 5v
1
$9,95
$9,95
TMP36
1
$1,95
$1,95
DTH11
1
$3,70
$3,70
Kit RF 433
1
$1,90
$1,90












Total
$102,5
Nota: Precios en dolares comprados a diferentes proveedores como dx.com y crcibernetica.com, no contempla gastos de envíos y otras cosas requeridas como cables, protoboard, abanicos, fuentes de alimentacion entre otros.