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.


Comentarios

Entradas populares de este blog

Mi Experiencia con BoxCorreos

Lo que nadie dice de actualizar OJS

OJS problemas con los pdf no los abre o descarga