Está en la página 1de 50

lOMoARcPSD|4807011

$ sudo dd bs=4M if=/path/of/raspbian-image.img of=/dev/mmcblk0


$ sudo apt-get -y install nmap
$ sudo nmap -sn ip.of.red.0/24
$ ssh pi@your.rpi.ip.address
$ scp your_archivo pi@your.rpi.ip.address:"/home/pi"

Materiales
MicroSD
Cable ethernet
Fuente de 5V 2amp
Raspberry pi
PC
Software Putty
Cable HDMI(opcional)
Teclado(opcional)
Mouse(opcional)
Usb Wifi(opcional)

Instalación de SO
1. SO Raspbian, descargarlo de la página oficial de Raspberry Pi desde aquí
2. una memoría microSD de al menos 4Gb (recomiendo que sea de clase 10)
3. software para grabar el SO en la memoria microSD, en este caso optaremos por
Win32DiskImager

El usuario por defecto es pi y la contraseña raspberry

Primera conexión:
Formaremos una red local entre el Rpi y la PC para poder acceder a esta sin necesidad de
una pantalla y teclado ni demás conectores.Los materiales que se necesitaremos son:
Despues de grabar la memoría microSD con Raspbian, lo insertamos en la pc y vamos a
editar el archivo cmdline.txt:

pi@raspberrypi:~ $ nano boot/cmdline.txt


dwc_otg.lpm_enable=0 console=ttyAMA0,115200 <...> rootwait ip=your.rpi.ip.address

Luego insertamos la memoria en el raspberry pi, y alimentamos la raspberry pi, en paralelo


cambiamos la configuración de ethernet en nuestra PC con la siguiente configuración:

ip address: your.rpi.ip.another_address
netmask: 255.255.255.0
gateway: your.rpi.ip.address

Y conectamos la Rpi con la PC mediante el cable ethernet, y abrimos el programa Putty y


colocaremos la ip del raspberry pi, aceptamos la llave SSH y colocamos el usuario:pi y la
contraseña:raspberry cuando nos pidan. Luego de esto configuramos una mejor conexión
ya sea cableada o inalámbrica.

Desde https://www.raspberrypi.org/documentation/remote-access/ssh/ :

As of the November 2016 release, Raspbian has the SSH server disabled by default.
You will have to enable it manually. This is done using raspi-config: Enter sudo raspi-
config in the terminal, first select Interfacing options, then navigate to ssh, press Enter
and select Enable or disable ssh server. For headless setup, SSH can be enabled by
placing a file named 'ssh', without any extension, onto the boot partition of the SD card.

RASPBIAN JESSIE LITE

Segun un aviso de la actualización, se removio el acceso ssh por defecto por lo que no se
podrá seguir el manual para versiones posteriores a Noviembre del 2016.

En los foros nos muestra una solución para la version Lite de raspbian. Primero debemos
ingresar al archivo cmdline.txt añadir lo siguiente:

ip=192.168.1.200::192.168.1.1:255.255.255.0:rpi:eth0:off

Esta estructuta tiene la forma:

ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>

Despues de esto para habilitar la conexión ssh solo es necesario crear un archivo vacio
llamado ssh.
En el caso de nuestra computadora debemos configurarlo como:

$ ip address: 192.168.1.xxx
$ netmask: 255.255.255.0
$ gateway: 192.168.1.1

Nota: La creación del archivo ssh o ssh.txt habilta el protócolo ssh en RASPBIAN JESSIE
WITH PIXEL pero la configuración de ip estática genera que el boot no se complete.

Cableada(IP Dinámica)
No editamos nada pero necesitaremos un software que escanee la red como Advanced IP
Scanner donde buscaremos la red que tenga como fabricante a Raspberry Pi Foundation.

Cableada(IP Estática)
Editamos el archivo interfaces:

pi@raspberrypi:~ $ sudo nano /etc/networks/interfaces

y cambiamos a:

auto eth0
#iface eth0 inet dhcp
iface eth0 inet static
address 192.168.1.11
netmask 255.255.255.0
gateway 192.168.1.1 #dirección ip del router

Inalámbrica
Editamos el archivo wpa_supplicant.conf:&nbsp:

pi@raspberrypi:~ $ sudo nano /etc/wpa_supplicant/wpa_supplicant.conf

y cambiamos a:

network={
ssid="Your ssid"
psk="your wifi password"
}

Descargado por Isra Chango (fran.chango@gmail.com)


En ambos casos reiniciar la Rpi y conectarse ahora por el nuevo IP a través del cliente
SSH, en nuestro caso Putty(en el caso de una red inalámbrica averigue su IP con Advanced
IP Scanner )

Si la Raspberry Pi tiene acceso a internet comprobamos si esta bien configurado con el


siguiente comando:

pi@raspberrypi:~ $ ping -c 3 8.8.8.8


PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=45 time=173 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=45 time=180 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=45 time=172 ms
--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 172.677/175.469/180.461/3.554 ms

Y sino tendremos que configurar el DNS, para ello editamos el archivo /etc/resolv.conf

pi@raspberrypi:~ $ sudo nano /etc/resolv.conf


nameserver 8.8.8.8
nameserver 8.8.4.4

Con ello ya deberiamos poder acceder a internet, comprobamos ello con el comando
anteriormente descrito

Introducción al S.O. GNU-Linux


Linux, es un kernel, es decir, el núcleo de un Sistema Operativo, mientras que GNU/Linux,
el Sistema Operativo que utiliza el Kernel Linux como núcleo, creado, difundido y promovido
a través del Proyecto GNU, por la Free Software Foundation, organización sin fines de
lucro, fundada por Richard Stallman, principal precursor del Software Libre.

El Kernel Linux, parte fundamental del Sistema Operativo, fue desarrollado por Linus
Torvals, utilizando como modelo a UNIX. Una de las diferencias fundamentales entre los
núcleos Linux y UNIX, es que el primero, es Software Libre, mientras que el segundo no lo
es.

Por otra parte, mientras existe un único Kernel Linux (con versiones diferentes), existen
decenas y hasta cientos de distribuciones GNU/Linux, es decir, diferentes Sistemas
Operativos basados en el Kernel Linux, entre las cuales se destacan: Debian, Ubuntu,
Lbuntu, Fedora, Gentoo, Slackware, CentOS, ArchLinux, Asturix, entre otros cientos.
Un sistema Linux reside bajo un árbol jerárquico de directorios muy similar a la estructura
del sistema de archivos de plataformas Unix.

Originariamente, en los inicios de Linux, este árbol de directorios no seguía un estándar


cien por cien, es decir, podíamos encontrar diferencias en él de una distribución a otra.

Todo esto hizo pensar a la comunidad que, posteriormente, desarrollarían el proyecto FHS
(Filesystem Hierarchy Standard) en 1993.

Los Objetivos de FHS son:

Presentar un sistema de archivos coherente y estandarizado.


Facilidad para que el software prediga la localización de archivos y directorios
instalados.
Facilidad para que los usuarios prediga la localización de archivos y directorios
instalados.
Especificar los archivos y directorios mínimos requeridos.

Este estandár esta enfocado a:

Fabricantes de software independiente y creadores de sistemas operativos, para que


establezcan una estructura de ficheros lo más compatible posible.
Usuarios comunes, para que entiendan el significado y el contendido de cada uno de
los elementos del sistema de archivos

Otro concepto muy importante es que en Linux todo es un archivo.

Organización de Archivos

El directorio raiz (/)


Todo surge a partir del directorio raíz (/).

El contenido de este directorio debe ser el adecuado para reiniciar, restaurar, recuperar y/o
reparar el sistema, es decir, debe proporcionar métodos, herramientas y utilidades
necesarias para cumplir estas especificaciones.

Contenido del directorio raíz:

/bin

En este directorio se ubica el código binario o compilado de los programas y comandos que
pueden utilizar todos los usuarios del sistema.

La denominación es clara, bin de BINARY (binario en castellano).

Descargado por Isra Chango (fran.chango@gmail.com)


No debe haber subdirectorios en /bin.

/boot

Este directorio contiene todo lo necesario para que funcione el proceso de arranque del
sistema.

/boot almacena los datos que se utilizan antes de que el kernel comience a ejecutar
programas en modo usuario.

El núcleo del sistema operativo (normalmente se guarda en el disco duro como un fichero
imagen llamado vmlinuz-versión _ núcleo) se debe situar en este directorio o, en el
directorio raíz.

El núcleo tiene la capacidad de crear dos entornos o modos de ejecución totalmente


separados.

Uno de ellos está reservado para el propio kernel, denominado el modo núcleo; y el otro
está reservado para el resto de programas, llamado el modo usuario.

Realmente se crean dos entornos totalmente separados, es decir, cada uno tiene su propia
zona de memoria y procesos independientes.

Démonos cuenta que esta técnica ofrece mucha seguridad y estabilidad al sistema.

Cuando un proceso del modo usuario necesita recursos del modo kernel (por ejemplo,
acceder a la memoria USB) se hacen uso de las famosas llamadas al sistema (interface que
ofrece el núcleo para la comunicación del modo usuario con el modo kernel).

/dev

Este directorio almacena las definiciones de todos los dispositivos. Como se ha


mencionado, cada dispositivo tiene asociado un archivo especial.

Por ejemplo, el contenido de la sexta partición del disco duro será /dev/hda5.

El fichero asociado al ratón tipo PS/2 será /dev/psaux.

Además, es importante saber que los dispositivos pueden ser de bloque o de carácter.

Normalmente los dispositivos de bloque son los que almacenan datos y, los de carácter los
que transfieren datos.

En definitiva, la estructura de este directorio es algo complejo. Podríamos dedicar otro


artículo entero para poder explicar en profundidad el contenido y funcionamiento especifico
del directorio /dev. De momento nos vasta con saber que Linux lo utiliza para asociar
dispositivos (devices) con ficheros.
NOTA: El subdirectorio /dev/null es como un agujero negro. Esto es así, puesto que
cualquier dato que se almacena aquí, desaparece. Es muy útil para redireccionar los errores
por ejemplo:

/etc

El directorio /etc contiene archivos necesarios para configuración del sistema.

Archivos que son propios del ordenador y que se utilizan para controlar el funcionamiento
diversos programas.

Deben ser ficheros estáticos y nunca pueden ser archivos binarios y/o ejecutables.

Algunos subdirectorios contenidos en /etc:

X11. Subdirectorio para la configuración del sistema de ventanas. Es opcional.

SGML. Subdirectorio para la configuración de SGML. Es opcional.

Xml. Subdirectorio para la configuración de XML. Es opcional.

X11 Sistema de ventanas graficas originario de UNIX en su versión 11. Este sistema
tiene la peculiaridad de ser totalmente independiente del sistema operativo. Es una
estructura cliente-servidor.

XML - eXtensible Markup Language (lenguaje de marcas extensible). Es un


metalenguaje de etiquetas.

SGML - Standard Generalized Markup Language (Lenguaje de Marcación


Generalizado). Sistema para la organización y etiquetado de documentos.

En definitiva, /etc mantiene los archivos de configuración del sistema para un ordenador
específico.

/home

Directorio que contiene los subdirectorios que son directorios origen para cada uno de los
usuarios del sistema.

Cada subdirectorio /home/user de cada usuario proporciona el lugar para almacenar sus
ficheros, así como los archivos de configuración propios de cada uno.

Es importante saber que también algunos servicios, y no solo usuarios, crean aquí su
directorio origen, por ejemplo: el servicio de transferencia de ficheros (FTP).

El administrador tiene su propio directorio home, que es /root.

/lib
El directorio /lib contiene librerías compartidas (similar a las dlls para los usuarios de
Windows) necesarias para arrancar el sistema y para los ficheros ejecutables contenidos
en, por ejemplo, /bin.

Normalmente las librerías son ficheros binarios escritos en lenguaje C.

También contiene módulos del kernel esenciales que permiten el funcionamiento de muchos
elementos Hardware. Se ubicarán normalmente en /lib/modules/versión-del-kernel/.

En el apartado /usr/include se explica que son y como funcionan las librerías y los archivos
cabecera.

/media

Este directorio contiene los subdirectorios que se utilizan como puntos del montaje para los
medios de almacenamiento, tales como disquetes, CD-ROM y memorias USBs.

/mnt

Este directorio contiene sistemas de archivos externos que hayan sido montados.

Las entidades que aparecen dentro de /mnt representan recursos externos a los que se
puede acceder a través de este directorio.

/opt

En este directorio (/opt de options, u opciones en castellano) se suelen instalar


complementos o add-ons de los programas.

Las aplicaciones crean un subdirectorio dentro de /opt denominado con el mismo nombre
del programa.

/root

Este directorio es el directorio /home del administrador del sistema (root).

/sbin

Los programas y comandos que se utilizan para la administración del sistema se almacenan
en /sbin, /usr/sbin y /usr/local/sbin.

/sbin únicamente contiene los ejecutables esenciales para el arranque, recuperación y


reparación del sistema.

Todos estos directorios (/sbin, /usr/sbin y /usr/local/sbin) se utilizan con fines


administrativos, por tanto, sólo puede ejecutar su contenido el administrador.
/srv

Contiene los archivos de datos específicos para cada servicio instalado en el sistema.

/tmp

En este directorio se guardan los archivos temporales.

El directorio /usr
Es la segunda sección más grande o estructura jerár quica (después del directorio raíz) del
sistema de ficheros.

Este directorio está pensado para almacenar datos que se puedan compartir con otros
hosts.

Estos datos además deben ser inalterables, es decir, sólo de lectura.

Normalmente, este directorio tiene su partición propia.

Comúnmente, se almacena aquí el software instalado en el sistema.

Estructura de /usr

/usr/bin

Éste es el directorio primario de comandos ejecutables del sistema.

/usr/bin alberga los archivos ejecutables vinculados al software instalado en el sistema.

/usr/include

Linux está escrito en lenguaje C.

En C es posible utilizar funciones que ya estén predefinidas (como otros muchos lenguajes
de programación) para incluirlas en el programa que estemos haciendo. Esta técnica se
denomina programación modular.

Estas funciones se llaman comúnmente archivos cabecera (.h de header) y contienen las
declaraciones externas de una librería.

La manera de incluir estos archivos cabecera en nuestro programa, es haciendo uso de la


directiva include; de ahí la denominación del subdirectorio.

Todos estos ficheros cabecera (que necesite el software instalado en el sistema) se


almacenan en este subdirectorio.
*Una librería no es más que un programa compilado, donde originariamente se implemento
el código fuente de las funciones que la componen.

La declaración pública del conjunto de funciones de la librería reside en los archivos


cabecera.

Vemos parte de su contenido:

/usr/lib

Este directorio incluye librerías compartidas y ficheros binarios pensados para no ser
ejecutados directamente por los usuarios del sistema.

/usr/local/

/usr/local/ es para uso del administrador del sistema cuando instala software localmente.
Puede usarse para programas y datos que son compartibles entre un grupo de máquinas

Este subdirectorio tiene una estructura similar a la del directorio /usr.

/usr/sbin

Este directorio contiene comandos y programas no esenciales usados exclusivamente por


el administrador de sistema.

Como se ha comentado, los comandos necesarios para la reparación, recuperación y otras


funciones esenciales del sistema, se almacenan en /sbin.

/usr/src

Por lo general, en /usr/src (src de source o, fuente en castellano) se guarda el código fuente
del Kernel del sistema.

Para comprobar si tenemos en nuestra distribución los fuentes del kernel instalados,
deberíamos ver un enlace simbólico llamado linux.

El directorio /var
Este directorio va ha contener ficheros de datos variables y temporales, así como archivos
spool (ficheros almacenados en fila en espera a ejecutarse, como por ejemplo colas de
impresión).

Todos los log del sistema y los generados por los servicios instalados, se ubican dentro de
la estructura jerárquica de /var. Esto quiere decir que el tamaño global de este directorio va
ha crecer constantemente.

La utilidad de /var radica en poder detectar problemas para prevenirlos y solucionarlos.


Es aconsejable montar en una nueva partición este directorio. Si no se pudiera, es preferible
ubicar /var fuera de la partición raíz y de la partición /usr.

Distribución de algunos subdirectorios de /var

/var/cache

Subdirectorio pensado para albergar datos de aplicaciones en cache (usados en un espacio


breve de tiempo).

El sistema de paquetes de Debian (apt-get), mantiene y almacena todos los paquetes que
nos hemos instalado con el gestor de paquetes Apt-get. Por ejemplo, si ejecutamos:

pi@raspberry:# sudo apt-get install nmap

Debian se bajará de algún repositorio especificado en /etc/apt/sources.list el archivo


nmap_version.deb, lo almacenará en /var/cache/apt y lo instalará desde esta ruta.

Posteriormente lo podemos borrar. Por defecto Debian almacena aquí todo los paquetes
que nos hemos instalado con su gestor de paquetes Apt-get.

/var/lib

Encontramos aquí información sobre el estado variable de las aplicaciones.

/var/lock

Aquí se almacenan los ficheros que están bloqueados por el sistema.

/var/log

En /var/log se guardan los mensajes de registro generados por el sistema operativo y por
diversos servicios.

Por ejemplo:

En /var/log/messages son los logs generados por el kernel, en /var/log/httpd/access_log


encontramos quien (desde que ip) está accediendo a nuestro servidor Web y, en
/var/log/wtmp encontraremos todos los accesos y salidas en el sistema.

/var/mail

Linux enviará aquí los archivos de correos de cada usuario del sistema.

/var/run
/var/run contiene archivos con información del sistema que lo describen desde que se
arrancó. Generalmente, se borrará todos los archivos que cuelgan de este subdirectorio al
comenzar el proceso de arranque.

Estos archivos con información del sistema son los llamados archivos identificados de
procesos ó PID, que guardan el identificador del proceso (Process ID).

Podemos ver aquí los archivos PID en un instante determinado en mi máquina:

/var/spool

/var/spool contiene ficheros almacenados en forma de fila de trabajos, para un


procesamiento posterior.

Un ejemplo claro puede ser los trabajos que guarda la impresora para, posteriormente,
ejecutarlos por un orden de llegada y/o prioridad.

/var/tmp

Algunos datos temporales se almacenan aquí y que, posiblemente, pueden aparecer en


nuestra distribución GNU/Linux para no saturar el directorio /tmp.

Existen otra serie de directorios que no especifica el estándar FSH, pero que son
importantes.

Directorio /lost+found. Perdidos y encontrados

Las herramientas y utilidades para restaurar y/o reparar el sistema de archivos almacenan
los datos en este directorio.

Es un espacio temporal donde se guardan los datos que se recuperan después de una
caída del sistema.

Fijémonos que, normalmente en cada partición que creemos existirá un /lost+found en el


nivel superior.

Por último, decir que este directorio existe sólo en distribuciones que tengan como sistemas
de archivos ext2 o ext3.

Directorio /proc

/proc es un sistema de archivos virtual. Se genera y actualiza dinámicamente, es decir,

no se mantiene en el disco duro, se mantiene el la memoria RAM. Es el sistema quien lo


crea y lo destruye.
Este directorio contiene información sobre los procesos, el núcleo e información relativa al
sistema.

Comandos en GNU-Linux
Algunos de los miles de comandos de linux!!!

Comando Función Uso

man manual $ man man

ls listing $ ls /home/pi

cd change directory $ cd ..

mv move $ mv carpeta1 carpeta2

rm remove $ rm archivo.txt

rmdir remove directory $ rmdir carpeta

mkdir make directory $ mkdir carpeta

cp copy $ cp archivo1.txt archivo2.txt

find find $ find archivo.txt

locate locate $ locate archivo.txt

Uso del editor Nano

$ nano name_of_file

raspi-config
La herramienta Raspi-config le ayuda a configurar su Raspberry Pi; varios ajustes se
pueden cambiar con esta herramienta sin tener que conocer los comandos correctos para
su uso.

$ sudo raspi-config

Descargado por Isra Chango (fran.chango@gmail.com)


Escritorio Remoto: VNC
$ sudo apt-get install tightvncserver
$ vncserver :1 -geometry 1280x800 -depth 16 -pixelformat rgb565

Para windows descargar desde aquí

Para linux instalar:

pi@raspberrypi:~ $ sudo apt-get -y install

ingresar con your.rpi.ip.address:1

Editor remoto: Sublime


Usar la terminal para editar no es amigable, por ello recurrimos a esta gran utilidad.

Instalar sublime
1. Instalar sublime desde aquí
2. Instalar Package Control Ejecutar View/Console y pegar
import urllib2,os,hashlib; h = '2915d1851351e5ee549c20394736b442' + '8bc59f460fa15
48d1514676163dafc88'; pf = 'Package Control.sublime-package'; ipp = sublime.instal
led_packages_path(); os.makedirs( ipp ) if not os.path.exists(ipp) else None;
urll ib2.install_opener( urllib2.build_opener( urllib2.ProxyHandler()) ); by =
urllib2. urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh
= hashli b.sha256(by).hexdigest(); open( os.path.join( ipp, pf), 'wb' ).write(by)
if dh == h else None; print('Error validating download (got %s instead of %s),
please try m anual install' % (dh, h) if dh != h else 'Please restart Sublime
Text to finish in stallation')

3. Ejecutar ctrl-shift-p, escribir install y seleccionar rsub

Instalar rmate

pi@raspberrypi:~ $ sudo wget -O /usr/local/bin/rsub https://raw.github.com/aurora/rmat


e/master/rmate
pi@raspberrypi:~ $ sudo chmod +x /usr/local/bin/rsub

Configurar Putty
1. Ejecutar como administrador putty
2. Seleccionar Connection/SSH/tunnels
3. Colocar en Source port: 52698, en Destination:127.0.0.1:52698 y seleccionar
Remote

USO

pi@raspberrypi:~ $ rsub your_file

Resumen

pi@raspberrypi:~ $ sudo apt-get update


pi@raspberrypi:~ $ sudo apt-get upgrade
pi@raspberrypi:~ $ sudo apt-get install -y tree
pi@raspberrypi:~ $ sudo apt-get install -y mlocate
pi@raspberrypi:~ $ sudo updatedb
lOMoARcPSD|4807011

GPIO

Manejo de los GPIO's

Instalación

$ sudo apt-get -y update


$ sudo apt-get -y upgrade
$ sudo apt-get -y install python-dev
$ sudo apt-get -y install python-rpi.gpio

Datasheet
Descargado por Isra Chango (fran.chango@gmail.com)
Uso de GPIO con Python
LED
Un led es un componente electrónico cuya función principal es convertir la energía
eléctrica en una fuente luminosa, la palabra led proviene del acrónimo ingles Light
Emmiting Diode o diodo emisor de luz.

Blink

#!/usr/bin/python
import RPi.GPIO as GPIO
import time
led = 18 #GPIO18 delay = 1 #one second
GPIO.setwarnings(False) #disable warnings
GPIO.setmode(GPIO.BCM) # mode BCM or Board
GPIO.setup(led, GPIO.OUT) # input or output
while True:
GPIO.output(led, True)
time.sleep(delay)
GPIO.output(led, False)
time.sleep(delay)
PWM

#!/usr/bin/python
import RPi.GPIO as GPIO
import time
led = 18 #GPIO18
GPIO.setwarnings(False) #disable warnings
GPIO.setmode(GPIO.BCM) # mode BCM or Board
GPIO.setup(led, GPIO.OUT) # input or output
pwm_led = GPIO.PWM(led, 500)
pwm_led.start(100)
while True:
duty_s = raw_input("Enter Brightness (0 to 100): ")
duty = int(duty_s)
pwm_led.ChangeDutyCycle(duty)

Pulsador
Los pulsadores (PUSHBUTTONS), son interruptores que al ser accionados de forma
manual cambian de estado y al soltarlo regresan a su estado inicial

Descargado por Isra Chango (fran.chango@gmail.com)


#!/usr/bin/python
import RPi.GPIO as GPIO
import time
led = 18 #GPIO18
delay = 0.2 #0.2 seconds
GPIO.setwarnings(False) #disable warnings
GPIO.setmode(GPIO.BCM) # mode BCM or Board
GPIO.setup(led, GPIO.IN, pull_up_down=GPIO.PUD_UP) # input or output
while True:
input_state = GPIO.input(led)
if input_state == False:
print("Button Pressed")
time.sleep(delay)
Pulsador II

#!/usr/bin/python
import RPi.GPIO as GPIO
import time
led = 18 #GPIO18
switch = 23
GPIO.setwarnings(False) #disable warnings
GPIO.setmode(GPIO.BCM) # mode BCM or Board
GPIO.setup(led, GPIO.OUT) # input or output
GPIO.setup(switch, GPIO.IN, pull_up_down=GPIO.PUD_UP)
led_state = False
old_input_state = True
while True:
new_input_state = GPIO.input(switch)
if new_input_state == False and old_input_state == True:
led_state = not led_state
old_input_state = new_input_state
GPIO.output(led, led_state)

Ultrasonido

Descargado por Isra Chango (fran.chango@gmail.com)


Los sensores de ultrasonidos o sensores ultrasónicos son detectores de proximidad
que trabajan libres de roces mecánicos y que detectan objetos a distancias que van
desde pocos centímetros hasta varios metros. El sensor emite un sonido y mide el
tiempo que la señal tarda en regresar. Estos reflejan en un objeto, el sensor recibe el
eco producido y lo convierte en señales eléctricas, las cuales son elaboradas en el
aparato de valoración

import RPi.GPIO as GPIO


import time
GPIO.setmode(GPIO.BCM)
TRIG = 23
ECHO = 24
print "Distance Measurement In Progress"
GPIO.setup(TRIG,GPIO.OUT)
GPIO.setup(ECHO,GPIO.IN)
GPIO.output(TRIG, False)
print "Waiting For Sensor To Settle"
time.sleep(2)
GPIO.output(TRIG, True)
time.sleep(0.00001)
GPIO.output(TRIG, False)
while GPIO.input(ECHO)==0:
pulse_start = time.time()
while GPIO.input(ECHO)==1:
pulse_end = time.time()
pulse_duration = pulse_end - pulse_start
distance = pulse_duration * 17150
distance = round(distance, 2)
print "Distance:",distance,"cm"
GPIO.cleanup()
Servomotor
Un servomotor (también llamado servo) es un dispositivo similar a un motor de
corriente continua que tiene la capacidad de ubicarse en cualquier posición dentro de
su rango de operación, y mantenerse estable en dicha posición.
from Tkinter import *
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT)
pwm = GPIO.PWM(18, 100)
pwm.start(5)
class App:
def init (self, master):
frame = Frame(master)
frame.pack()
scale = Scale(frame, from_=0, to=180, orient=HORIZONTAL, command=self.update)
scale.grid(row=0)
def update(self, angle):
duty = float(angle) / 10.0 + 2.5
pwm.ChangeDutyCycle(duty)

root = Tk()
root.wm_title('Servo Control')
app = App(root)
root.geometry("200x50+0+0")
root.mainloop()

DHT22

Instalación
$ sudo apt-get -y update
$ sudo apt-get -y install python-pip
$ sudo pip install adafruit_python_dht

import Adafruit_DHT
import time

while True:
humidity, temperature = Adafruit_DHT.read_retry(Adafruit_DHT.DHT22, 4)
if humidity is not None and temperature is not None:
print('Temp={0:0.1f}* Humidity={1:0.1f}%'.format(temperature, humidity))
else:
print('Failed to get reading. Try again!')

time.sleep(1)

Resumen
sudo apt-get -y update
sudo apt-get -y upgrade
sudo apt-get install -y python-dev
sudo apt-get install -y python-rpi.gpio
sudo apt-get install -y python-pip
sudo pip install adafruit_python_dht
lOMoARcPSD|4807011

Servidores y Bases de Datos con


Raspberry

Control de la Raspberry pi a través de una


página web.
El proyecto que se implementará consiste en el monitoreo de sensores y control de
actuadores mediante la interfaz de una página web.

En la siguiente imagen se muestra un esquema simple de la aplicación, esta se compondrá


de todas principales:

1. Aplicación WEB: Esta se encarga de mostrar los datos guardados en la base de


datos.

2. Servicio o Demonio: Este se encarga de leer los datos que proporciona los sensores y
guardarlo en la base de datos.

Esta arquitectura tiene como cualidad de ser simple y escalable.


Aplicación WEB:
Para esta parte implementaremos un servicio restful.

Usaremos como framework django , para implementar con facilidad el servicio restful
añadiremos django rest framework .

Como primer paso instalaremos un entorno virtual llamado virtualenv

pi@raspberrypi:~ $ sudo apt-get install -y python-pip


pi@raspberrypi:~ $ sudo pip install virtualenv

Teniendo instalado virtualenv, creamos un entorno de trabajo que llamaremos rpi-env:

pi@raspberrypi:~ $ mkdir ~/projects


pi@raspberrypi:~ $ cd ~/projects
pi@raspberrypi:~/projects $ virtualenv rpi-env

Lo activamos con:

Descargado por Isra Chango (fran.chango@gmail.com)


pi@raspberrypi:~/projects $ source rpi-env/bin/activate

Teniendo todo lo anterior instalamos django y django-rest-framework:

(rpi-env) pi@raspberrypi:~/projects $ pip install django


(rpi-env) pi@raspberrypi:~/projects $ pip install djangorestframework

Creamos un proyecto llamado DomoProject y una aplicación llamada Domo:

(rpi-env) pi@raspberrypi:~/projects $ django-admin.py startproject DomoProject .


(rpi-env) pi@raspberrypi:~/projects $ ./manage.py startapp Domo
(rpi-env) pi@raspberrypi:~/projects $ ./manage.py migrate

Para verificar que vamos por buen camino ejecutamos el siguiente comando para visualizar
la estructura de carpetas generadas:

(rpi-env) pi@raspberrypi:~/projects $ tree | head -22

Debiendo obtener lo siguiente:

.
├── db.sqlite3
├── Domo
│ ├── admin.py
│ ├── apps.py
│ ├── init .py
│ ├── migrations
│ │ └── init .py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── DomoProject
│ ├── init .py
│ ├── init .pyc
│ ├── settings.py
│ ├── settings.pyc
│ ├── urls.py
│ ├── urls.pyc
│ └── wsgi.py
├── manage.py
└── rpi-env
├── bin

Vamos a hacer una pequeña prueba para ello editamos el archivo settings.py y añadimos la
ip del raspberry(en mi caso '192.168.2.9') en la linea ALLOWED_HOSTS = []
(rpi-env) pi@raspberrypi:~/projects $ nano DomoProject/settings.py
ALLOWED_HOSTS = ['192.168.2.9']

Y luego lanzamos el servidor de desarrollo:

(rpi-env) pi@raspberrypi:~/projects $ ./manage.py runserver 0.0.0.0:8000

Ingresamos desde nuestra pc a un buscador y colocamos la ip del raspberry seguido del


puerto 8000, en mi caso http://192.168.2.9:8000/ y deberiamos obtener algo similar a lo que
muestra la siguiente imagen:

Para apagar el servidor apretamos Ctrl+C

Lo primero que haremos es crear un modelo de la base de datos, para ello usaremos la
ORM de django, editamos el archivo models.py que se encuentra dentro de la carpeta
Domo. Hacemos los mismo con serializers.py

(rpi-env) pi@raspberrypi:~/projects $ nano Domo/models.py

Domo/models.py
from future import unicode_literals

from django.db import models

class Sensor(models.Model):
date_created = models.DateTimeField(auto_now=True)
temperature = models.FloatField()
humidity = models.FloatField()

(rpi-env) pi@raspberrypi:~/projects $ nano Domo/serializers.py

Domo/serializers.py

from rest_framework import serializers

from Domo.models import Sensor

class SensorSerializer(serializers.ModelSerializer):
class Meta:
model = Sensor
fields = ('date_created', 'temperature', 'humidity')

(rpi-env) pi@raspberrypi:~/projects $ nano Domo/views.py

Domo/views.py

from django.shortcuts import render


from rest_framework import viewsets

from Domo.models import Sensor


from Domo.serializers import SensorSerializer

class SensorViewSet(viewsets.ModelViewSet):
queryset = Sensor.objects.all().order_by('-id')[:40]
serializer_class = SensorSerializer

def home(request):
return render(request, 'index.html')

(rpi-env) pi@raspberrypi:~/projects $ nano Domo/urls.py


Domo/urls.py

from rest_framework import routers

from Domo.views import SensorViewSet

router = routers.DefaultRouter()
router.register(r'sensors', SensorViewSet)

urlpatterns = router.urls

(rpi-env) pi@raspberrypi:~/projects $ nano Domo/admin.py

Domo/admin.py

from django.contrib import admin

from Domo.models import Sensor

@admin.register(Sensor)
class SensorAdmin(admin.ModelAdmin):
list_display = ('date_created', 'temperature', 'humidity')

Luego añadimos la aplicación Domo al proyecto:

(rpi-env) pi@raspberrypi:~/projects $ nano DomoProject/settings.py

DomoProject/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',

'rest_framework',

'Domo',
]

....

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')], # modificamos esta parte
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

...

STATIC_ROOT = os.path.join(BASE_DIR, "static/")

(rpi-env) pi@raspberrypi:~/projects $ nano DomoProject/urls.py

DomoProject/urls.py
"""DomoProject URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.10/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url, include
from django.contrib import admin

from Domo.views import home

urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/', include('Domo.urls', namespace='core')),
url(r'^$', home),
]

(rpi-env) pi@raspberrypi:~/projects $ mkdir templates


(rpi-env) pi@raspberrypi:~/projects $ nano templates/index.html

templates/index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Proyecto</title>
</head>

<body>
<div id="header">
<h2 style="text-align: center">Proyecto</h2>
</div>
<div id="content">
<div class="demo-container">
<div id="placeholder" style="margin:0 auto;"></div>
<br>
<div style="width:1000px;margin:0 auto;">
Actualizar: <input type="checkbox" id="myCheck" checked>
<br>
Time : <input type="number" id="interval" value="1000">
<br>
<label id="lblLast"></label>
</div>
</div>
</div>
</body>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>

<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
var temperature = {
x: [],
y: [],
fill: 'tonexty',
type: 'scatter',
name: 'Temperatura'
};

var humidity = {
x: [],
y: [],
fill: 'tonexty',
type: 'scatter',
name: 'Humedad',
yaxis: 'y2'
};

var layout = {
title: 'Sensores',
showlegend: true,
legend: {
x: 0,
y: 1,
traceorder: 'normal',
font: {
family: 'sans-serif',
size: 12,
color: '#000'
},
bgcolor: '#E2E2E2',
},
yaxis: {
title: '°C',
range: [0, 100]
},
yaxis2: {
title: '%',
side: 'right',
overlaying: 'y',
range: [0, 100]
}
};

var data = [humidity, temperature];

var updateInterval = 1000;


// Load all posts on page load
function GetData() {
$.ajax({
url: "/api/sensors/", // the endpoint
type: "GET", // http method
// handle a successful response
success: function (data) {
temperature['x'] = [];
temperature['y'] = [];

humidity['x'] = [];
humidity['y'] = [];

$.each(data, function (index, value) {


temperature['x'].push(new Date(value['date_created']));
temperature['y'].push(value['temperature']);

humidity['x'].push(new Date(value['date_created']));
humidity['y'].push(value['humidity']);
});
},
// handle a non-successful response
error: function (xhr, errmsg, err) {

}
});

};

function update() {
GetData();

if (document.getElementById("myCheck").checked) {
Plotly.newPlot('placeholder', data, layout);
document.getElementById('lblLast').innerHTML = "Temperatura Actual: "
+
temperature['y'][0] + "<br>Humedad Actual: " + humidity['y'][0];
}
var interval = Number(document.getElementById("interval").value);
if (!isNaN(interval)) {
updateInterval = interval;
}
setTimeout(update, updateInterval);
}

update();
})
;
</script>
</html>

(rpi-env) pi@raspberrypi:~/projects $ ./manage.py makemigrations


(rpi-env) pi@raspberrypi:~/projects $ ./manage.py migrate
(rpi-env) pi@raspberrypi:~/projects $ ./manage.py collectstatic
(rpi-env) pi@raspberrypi:~/projects $ ./manage.py runserver 0.0.0.0:8000

Ahora instalamos el servidor Apache:

(rpi-env) pi@raspberrypi:~/projects $ sudo apt-get install -y apache2 libapache2-mod-w


sgi

Despues de instalamos editamos el archivo 000-default.conf ubicado en


/etc/apache2/sites-available , añadiendo lo siguiente antes de < /VirtualHost >
(rpi-env) pi@raspberrypi:~/projects $ sudo nano /etc/apache2/sites-available/000-defau
lt.conf

Alias /static /home/pi/projects/static


<Directory /home/pi/projects/static>
Require all granted
</Directory>
<Directory /home/pi/projects/DomoProject>
<Files wsgi.py>
Require all granted
</Files>
</Directory>

WSGIDaemonProcess projects python-path=/home/pi/projects python-home=/home/pi/projects


/rpi-env
WSGIProcessGroup projects
WSGIScriptAlias / /home/pi/projects/DomoProject/wsgi.py

Luego le damos permisos a las carpetas y archivos.

(rpi-env) pi@raspberrypi:~/projects $ sudo chmod 664 ~/projects/db.sqlite3


(rpi-env) pi@raspberrypi:~/projects $ sudo chown www-data ~/projects/db.sqlite3
(rpi-env) pi@raspberrypi:~/projects $ sudo chown www-data ~/projects
(rpi-env) pi@raspberrypi:~/projects $ sudo service apache2 restart

Ahora podremos ingresar directamente a la ip sin necesidad de indicar el puerto ni ejecutar


ningun comando ya que se esta ejecutando el servidor de producción.

Servicio o Demonio
Creamos un archivo llamado myservice.py

(rpi-env) pi@raspberrypi:~/projects $ mkdir myservice


(rpi-env) pi@raspberrypi:~/projects $ nano myservice/myservice.py

myservice.py

#!/usr/bin/env python
import logging
import logging.handlers
import argparse
import sys
from datetime import datetime
import sqlite3
import Adafruit_DHT
def getSensors():
humidity, temperature = Adafruit_DHT.read_retry(Adafruit_DHT.DHT22, 4)
t = datetime.utcnow()
return t, temperature, humidity
# Deafults
LOG_FILENAME = "/tmp/myservice.log"
LOG_LEVEL = logging.INFO # Could be e.g. "DEBUG" or "WARNING"

# Define and parse command line arguments


parser = argparse.ArgumentParser(description="My simple Python service")
parser.add_argument("-l", "--log", help="file to write log to (default '" + LOG_FILENA
ME + "')")

# If the log file is specified on the command line then override the default
args = parser.parse_args()
if args.log:
LOG_FILENAME = args.log

# Configure logging to log to a file, making a new file at midnight and keeping the la
st 3 day's data
# Give the logger a unique name (good practice)
logger = logging.getLogger( name )
# Set the log level to LOG_LEVEL
logger.setLevel(LOG_LEVEL)
# Make a handler that writes to a file, making a new file at midnight and keeping 3 ba
ckups
handler = logging.handlers.TimedRotatingFileHandler(LOG_FILENAME, when="midnight", bac
kupCount=3)
# Format each log message like this
formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s')
# Attach the formatter to the handler
handler.setFormatter(formatter)
# Attach the handler to the logger
logger.addHandler(handler)

# Make a class we can use to capture stdout and sterr in the log
class MyLogger(object):
def init (self, logger, level):
"""Needs a logger and a logger level."""
self.logger = logger
self.level = level

def write(self, message):


# Only log if there is a message (not just a new line)
if message.rstrip() != "":
self.logger.log(self.level, message.rstrip())

# Replace stdout with logging to file at INFO level


sys.stdout = MyLogger(logger, logging.INFO)
# Replace stderr with logging to file at ERROR level
sys.stderr = MyLogger(logger, logging.ERROR)
conn = sqlite3.connect('/home/pi/projects/db.sqlite3')
curs = conn.cursor()

while True:
curs.execute("INSERT INTO Domo_sensor(date_created, temperature, humidity) VALUES(
(?), (?), (?))", getSensors())
conn.commit()
conn.close()

(rpi-env) pi@raspberrypi:~/projects $ nano myservice.sh

myservice.sh

#!/bin/sh

### BEGIN INIT INFO


# Provides: myservice
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Put a short description of the service here
# Description: Put a long description of the service here
### END INIT INFO

# Change the next 3 lines to suit where you install your script and what you want to c
all it
DIR=/usr/local/bin/myservice
DAEMON=$DIR/myservice.py
DAEMON_NAME=myservice

# Add any command line options for your daemon here


DAEMON_OPTS=""

# This next line determines what user the script runs as.
# Root generally not recommended but necessary if you are using the Raspberry Pi GPIO
from Python.
DAEMON_USER=root

# The process ID of the script when it runs is stored here:


PIDFILE=/var/run/$DAEMON_NAME.pid

. /lib/lsb/init-functions

do_start () {
log_daemon_msg "Starting system $DAEMON_NAME daemon"
start-stop-daemon --start --background --pidfile $PIDFILE --make-pidfile --user $D
AEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS
log_end_msg $?
}
do_stop () {
log_daemon_msg "Stopping system $DAEMON_NAME daemon"
start-stop-daemon --stop --pidfile $PIDFILE --retry 10
log_end_msg $?
}

case "$1" in

start|stop)
do_${1}
;;

restart|reload|force-reload)
do_stop
do_start
;;

status)
status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $?
;;

*)
echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}"
exit 1
;;

esac
exit 0

(rpi-env) pi@raspberrypi:~/projects $ sudo chmod 755 myservice/myservice.py


(rpi-env) pi@raspberrypi:~/projects $ sudo chmod +x myservice.sh
(rpi-env) pi@raspberrypi:~/projects $ sudo cp myservice.sh /etc/init.d
(rpi-env) pi@raspberrypi:~/projects $ sudo update-rc.d myservice.sh defaults
(rpi-env) pi@raspberrypi:~/projects $ sudo cp -rf myservice/ /usr/local/bin/
(rpi-env) pi@raspberrypi:~/projects $ sudo service myservice start
Salida:

Clientes
Python

GET method:

import requests
import datetime

url = 'http://192.168.2.9/api/sensors/'

response = requests.get(url)
assert response.status_code == 200

for data in response.json():


date = datetime.datetime.strptime(data['date_created'][:-1], "%Y-%m-%dT%H:%M:%S.%f"
)
humidity = data['humidity']
temperature = data['temperature']
print("Fecha: {}, Humedad: {}, Temperatura: {}".format(date, humidity, temperature
))

POST method:
import requests
import datetime
import json
import time

url = 'http://192.168.2.9/api/sensors/'

for i in range(100):
date = datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ')

headers = {'Content-type': 'application/json'}


response = requests.post(url, data =json.dumps({'date_created': date,'temperature'
: 11.1, 'humidity': 10.1}), headers=headers)
assert response.status_code == 201
time.sleep(0.1)

Resumen
Para los alumnos del curso es necesario ejecutar los siguientes comandos:

sudo apt-get install -y update


sudo apt-get install -y upgrade
sudo apt-get install -y install python-dev
sudo apt-get install -y python-rpi.gpio
sudo apt-get install -y python-pip
sudo pip install adafruit_python_dht
sudo pip install virtualenv
mkdir ~/projects
cd ~/projects
virtualenv rpi-env
source rpi-env/bin/activate
pip install django
pip install djangorestframework
sudo apt-get install -y apache2 libapache2-mod-wsgi

Fuente
https://www.digitalocean.com/community/tutorials/how-to-serve-django-applications-
with-apache-and-mod_wsgi-on-ubuntu-14-04
http://blog.scphillips.com/posts/2013/07/getting-a-python-script-to-run-in-the-
background-as-a-service-on-boot/
lOMoARcPSD|4807011

Configuración de motion
Creamos un directorio para guardar las imagenes:

pi@raspberrypi:~ $ mkdir /home/pi/Monitor


pi@raspberrypi:~ $ sudo chgrp motion /home/pi/Monitor
pi@raspberrypi:~ $ sudo chmod g+rwx /home/pi/Monitor
pi@raspberrypi:~ $ sudo chmod -R g+w /home/pi/Monitor/

Instalamos la librería motion.

pi@raspberrypi:~ $ sudo apt-get install -y motion

Editamos el archivo motion.conf, buscando los siguientes campos y los cambiamos a lo


siguientes valores:

pi@raspberrypi:~ $ sudo nano /etc/motion/motion.conf

stream_localhost off
webcontrol_localhost off
framerate 60
target_dir /home/pi/Monitor

Editamos el archivo /etc/default/motion y cambiamos de no a yes

pi@raspberrypi:~ $ sudo nano /etc/default/motion

start_motion_daemon=yes

Despues ejecutamos lo siguiente:

pi@raspberrypi:~ $ sudo service motion stop


pi@raspberrypi:~ $ sudo service motion start

Y Accedemos a la imagen de la cámara a traves de la url desde nuestro buscador:


http://{your-rpi-address}:8081/

Obteniendo lo siguiente:
Las imagenes y videos pueden llenar el almacenamiento, por ello configuramos que pasada
los 15 minutos despues de cada hora borre todos excepto las 20 ultimas imagenes:

pi@raspberrypi:~ $ sudo crontab -e

15 * * * * (date; ls /home/pi/Monitor/*.jpg | head -n -20 | xargs rm -v) >> /tmp/image


s_deleted 2>&1

Configurando el Servidor
Implementamos el servidor para que provea y guarde los datos, para ellos creamos el
modelo Motor que contiene 2 atributos: date_created que guarda la fecha de creación del
comando y status que contiene el comando respectivo. Además de los serializers y vistas
respectivas.

Domo/models.py
from future import unicode_literals

from django.db import models

STATUS_CHOICES = (
('F', 'Forward'),
('B', 'Backward'),
('L', 'Left'),
('R', 'Right'),
('S', 'Stop')
)

# Create your models here.

class Motor(models.Model):
date_created = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=1, choices=STATUS_CHOICES, default='S')

Domo/serializers.py:

from rest_framework import serializers

from Domo.models import Motor

class MotorSerializer(serializers.ModelSerializer):
class Meta:
model = Motor
fields = ('date_created', 'status')

Domo/views.py:

from django.shortcuts import render


from rest_framework import viewsets

# Create your views here.


from Domo.models import Motor
from Domo.serializers import MotorSerializer

class MotorViewSet(viewsets.ModelViewSet):
queryset = Motor.objects.all()
serializer_class = MotorSerializer

Domo/admin.py
from django.contrib import admin
from Domo.models import Motor

# Register your models here.


@admin.register(Motor)
class MotorAdmin(admin.ModelAdmin):
list_display = ('date_created', 'status')

Domo/urls.py

from rest_framework import routers


from Domo.views import MotorViewSet

router = routers.DefaultRouter()
router.register(r'motors', MotorViewSet)

urlpatterns = router.urls

Creamos el archivo index.html donde implementamos las peticiones mediante javascript


utilizando ajax.

templates/index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Proyecto</title>
</head>

<body>

<div style="text-align:center;margin:auto;">
<button onclick="forward()">Avanzar</button>
</div>

<div style="text-align:center;margin:auto;">
<button onclick="backward()">Retroceder</button>
</div>

<div style="text-align:center;margin:auto;">
<button onclick="left()">Izquierda</button>
</div>

<div style="text-align:center;margin:auto;">
<button onclick="right()">Derecha</button>
</div>

<div style="text-align:center;margin:auto;">
<button onclick="stop()">Parar</button>
</div>

<img id="ip_link" src="" target="_blank" />

</body>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>

<script type="text/javascript">

var ip = location.host;
document.getElementById("ip_link").src = "http://"+ip+":8081";

// Load all posts on page load


function move(state) {
$.ajax({
url: "/api/motors/", // the endpoint
type: "POST", // http method
// handle a successful response
success: function (data) {

},
data: {
'date_created': new Date(),
'status': state
},
// handle a non-successful response
error: function (xhr, errmsg, err) {

}
});

};

function forward(){
move('F');
};

function backward(){
move('B');
};

function left(){
move('L');
};

function right(){
move('R');
};

function stop(){
move('S');
};
</script>
</html>

Obteniendo algo similar a la siguiente imagen:

Luego implementamos la clase Car que se encarga de manejar los movimientos del
vehículo.

Car.py

import RPi.GPIO as GPIO


import time

class Car:
def init (self, motorL, motorR):
"""
Manejar los motores
:param pins:
[in1, in2, in3, in4]
"""
GPIO.setmode(GPIO.BCM)
self._pinsA = motorL
self._pinsB = motorR

for pin in (self._pinsA + self._pinsB):


GPIO.setup(pin, GPIO.OUT)

def motorOn(self, pins):


GPIO.output(pins[0], False)
GPIO.output(pins[1], True)
def motorOff(self, pins):
GPIO.output(pins[0], False)
GPIO.output(pins[1], False)

def motorReverse(self, pins):


GPIO.output(pins[0], True)
GPIO.output(pins[1], False)

def forward(self):
self.stop()
self.motorOn(self._pinsA)
self.motorOn(self._pinsB)
time.sleep(0.2)
self.stop()

def backward(self):
self.stop()
self.motorReverse(self._pinsA)
self.motorReverse(self._pinsB)
time.sleep(0.2)
self.stop()

def left(self):
self.stop()
self.motorOn(self._pinsB)
self.motorReverse(self._pinsA)
time.sleep(0.2)
self.stop()

def right(self):
self.stop()
self.motorOn(self._pinsA)
self.motorReverse(self._pinsB)
time.sleep(0.2)
self.stop()

def stop(self):
self.motorOff(self._pinsA)
self.motorOff(self._pinsB)

def exit (self, exc_type, exc_val, exc_tb):


GPIO.cleanup()

Ahora creamos la clase Data que se encarga de obtener los datos, filtrar el último y verificar
si este ha sido creado en menos de 1 segundo. Si cumple lo anterior obtenemos el
comando status y realizamos la tarea respectiva.

main.py
from datetime import datetime, timedelta
from Car import Car
import requests

class Data:
def init (self, url, timeout=1):
self.url = url
self.before = None
self.timeout = timeout

def load(self):
response = requests.get(self.url)
assert response.status_code == 200
data = response.json()[-1]
date = datetime.strptime(data['date_created'][:-1], "%Y-%m-%dT%H:%M:%S.%f")
if self.before == date:
return
self.before = date
u = datetime.utcnow()
diff = u - date
if diff < timedelta(seconds=self.timeout):
return data['status']

if name == ' main ':


data = Data(url='http://192.168.2.10/api/motors/')
motorL = [17, 27]
motorR = [23, 24]

car = Car(motorL, motorR)

while True:
resp = data.load()
if resp == 'F':
car.forward()
elif resp == 'B':
car.backward()
elif resp == 'L':
car.left()
elif resp == 'R':
car.right()
elif resp == 'S':
car.stop()

También podría gustarte