Translate

lunes, 10 de marzo de 2014

Raspberry Pi y Arduino Ultrasonido por I2C "Tercera Parte"

En la tercera y última parte de este tutorial, se configura el Raspberry Pi, como maestro para recibir y transmitir datos por I2C y mostrar la distancia, medida por ultrasonido y enviada por Arduino, del proyecto que integra Arduino y Pic con Raspberry Pi midiendo y controlado variables físicas a través de WebSockets.

Instrucciones en video:


Prueba de funcionamiento:


Código Fuente en:  /charlesrct/Tornado-RasberryPi

Este código es implementado en Raspberry Pi y Arduino Leonardo.
En el circuito implementado se utiliza un Raspberry Pi Model B (configurado como maestro I2C), un LCD 16*2, un Arduino Leonardo (configurado como esclavo I2C) y el sensor de ultrasonido HC-SR04.


Clic en la imagen para ampliarla. (Creado en Fritzing)
Descargar circuito: http://fritzing.org/projects/raspberry-pi-y-arduino-ultrasonido-por-i2c

NOTA: Es importante conectar las tierras "GND" del Raspberry Pi con el Arduino. 
En el Arduino Leonardo, los pines 2 y 3 están internamente conectados con los pines SCL y SDA, por este motivo se utilizan los pines 0, 1, 4 y 5 para el LCD.

Al archivo "tutotor.py" se agregan las siguientes líneas de código:


import time
import threading

Se importan las librerías "time" y "threading" para crear un hilo que se encargue de solicitar al Arduino, el valor de la distancia medida por ultrasonido.

La librería "smbus" es utilizada para la comunicación I2C con el Arduino, configurando el Raspberry Pi como maestro y asignando la dirección 0x04 para identificar el dispositivo esclavo.

#Libreria para comunicacion I2C con arduino.
import smbus

#Configurando I2C como master
bus = smbus.SMBus(1)
#Asignamos la direccion 0x04 que es la misma direccion del Arduino
address = 0x04

La función "pinkCall", encargada de realizar las interrupciones por hardware al presionar el pulsador, se modifica para que envíe un mensaje al Arduino cada ves que se enciende o apaga el Led:

#Interrupcion por hardware
def pinkCall(channel):
    pulsador = Raspberry()
    inputValue = GPIO.input(11)
    
    if(inputValue == True):
        #Apagamos el led desde el pulsador
        GPIO.output(11, False)
        #Se envia el numero 0 al Arduino via I2C
        bus.write_byte(address, 0)
        #Se notifican todos los usuarios via Websockets
        pulsador.notifyCallbacks(0, 'El Led fue apagado por Hardware')

    if(inputValue == False):
        #Encendemos el led desde el pulsador
        GPIO.output(11, True)
        #Se envia el numero 1 al Arduino via I2C
        bus.write_byte(address, 1)
        #Se notifican todos los usuarios via Websockets
        pulsador.notifyCallbacks(1, 'El Led fue encendido por Hardware')

Se agrega la función "obDistancia" para leer el bus I2C y obtener el valor de la distancia medida por ultrasonido desde el Arduino.

Las funciones "ledON" y "ledOFF" de la clase "Raspberry" se modifican, para que se envíe un mensaje al Arduino cada ves que se enciende o apaga el Led al dar clic en los botones de la página web.

A la función "notifyCallbacks" se agrega la variable "distancia" para transmitirla vía WebSockets a los clientes conectados a la página web. 

class Raspberry(object):
 callbacks = []
 distancia = 0

 def obDistancia(self):
  distancia = bus.read_byte(address) 
  self.notifyCallbacks(-1, '-1', distancia)
  print('distancia= ', distancia)
  
 def register(self, callback):
  self.callbacks.append(callback)

 def unregister(self, callback):
  self.callbacks.remove(callback)

 def ledON(self):
  #Encendemos el Led conectado en el pin 11
  GPIO.output(11, True)
  #Se envia el numero 1 al Arduino via I2C
  bus.write_byte(address, 1)
  #Se notifican todos los usuarios via Websockets
  self.notifyCallbacks(1, "Led Encendido", -1)

 def ledOFF(self):
  #Apagamos el Led conectado en el pin 11
  GPIO.output(11, False)
  #Se envia el numero 0 al Arduino via I2C
  bus.write_byte(address, 0)
  #Se notifican todos los usuarios via Websockets
  self.notifyCallbacks(0, "Led Apagado", -1)

 def notifyCallbacks(self, ledStdo, estado, distancia):
  for callback in self.callbacks:
   callback(ledStdo, estado, distancia)

Con la clase "CuentaDistancia" se crea un hilo para medir la distancia por ultrasonido cada segundo, mientras se continua ejecutando el resto del programa.

class CuentaDistancia(threading.Thread):
 def run(self):
  d = Raspberry()
  n = 50
  while True:
   d.obDistancia()
   time.sleep(1)

th = CuentaDistancia()
th.daemon = True
th.start()

La clase "RenderHandler" se le adiciona la variable "distancia" para que pueda ser visualizada y actualizada en la interfaz web.

class RenderHandler(tornado.web.RequestHandler):

 def get(self):
  session = uuid4()
  estado = "...Iniciando"
  distancia = 0
  self.render("index.html", session=session, estado=estado, distancia=distancia)

Finalmente en la clase "RaspberryHandler" se incluye la variable "distancia" para enviarla vía WebSockets a todos los clientes conectados.

 def callback(self, ledStdo, estado, distancia):

  self.write_message(json.dumps({
   "ledStdo": ledStdo,
   "estado": estado,
   "distancia": distancia
   }))

Ahora actualizamos el archivo "templates/index.html" para agregar la etiqueta encargada de mostrar la distancia en la interfaz web.

<hr />
<div>
 <h2>Distancia por Ultrasonido</h2>
 <p><span>   <span style="color: blue;" id="dist">{{ distancia }}</span> cm ..:: By Arduino Leonardo ::..</span></p>
</div>

Al igual que el archivo "static/scripts/raspberry.js" se le agregan las líneas para recibir el dato de la "distancia" y mostrarlo en la página web del cliente.

 if($.parseJSON(evt.data)['distancia'] > 0){
  $('#dist').html($.parseJSON(evt.data)['distancia']);
 }


Resultados



 Clic en las imágenes para ampliarlas.


No hay comentarios.:

Publicar un comentario