Raspberry Pi
Tutorial de Rapberry Pi en español.
- Juan Antonio Villalpando -
Volver al índice del tutorial
____________________________
5.- Pantalla LCD con bus I2C.
GPIO2 es SDA
GPIO3 es SCL
______________________________
1.- Conexión.
http://www.circuitbasics.com/raspberry-pi-i2c-lcd-set-up-and-programming/
- Habilitamos el reconocimiento de I2C, para ello escribimos
$ sudo su
# raspi-config
- Seleccionamos lo indicado en las siguientes imágenes.
- Instalación de herramientas para obtener la dirección I2C de la pantalla LCD.
- Mediante este programa podremos obtener la dirección de los dispositivos conectado al bus I2C.
$ sudo su
# apt-get install i2c-tool
- Instalamos la librería para acceder al bus I2C:
# apt-get install python-smbus
- Conectamos nuestra la pantalla LCD al bus I2C. Para detectar la dirección I2C de nuestra pantalla LCD escribimos:
#
i2cdetect -y 1
- La dirección I2C de esta pantalla LCD es la 27.
_____________________
- Librería.
[
https://gist.github.com/DenisFromHR/cc863375a6e19dce359d ]
- Crea un archivo llamado I2C_LCD_driver.py y copia el contenido siguiente.
- Este archivo deberá estar en la misma carpeta que las aplicaciones realizadas para la pantalla LCD.
- Observa la LCD ADDRESS es la 0x27
|
# -*- coding: utf-8 -*-
# Original code found at:
# https://gist.github.com/DenisFromHR/cc863375a6e19dce359d
"""
Compiled, mashed and generally mutilated 2014-2015 by Denis Pleic
Made available under GNU GENERAL PUBLIC LICENSE
# Modified Python I2C library for Raspberry Pi
# as found on http://www.recantha.co.uk/blog/?p=4849
# Joined existing 'i2c_lib.py' and 'lcddriver.py' into a single library
# added bits and pieces from various sources
# By DenisFromHR (Denis Pleic)
# 2015-02-10, ver 0.1
"""
# i2c bus (0 -- original Pi, 1 -- Rev 2 Pi)
I2CBUS = 1
# LCD Address
ADDRESS = 0x27
import smbus
from time import sleep
class i2c_device:
def __init__(self, addr, port=I2CBUS):
self.addr = addr
self.bus = smbus.SMBus(port)
# Write a single command
def write_cmd(self, cmd):
self.bus.write_byte(self.addr, cmd)
sleep(0.0001)
# Write a command and argument
def write_cmd_arg(self, cmd, data):
self.bus.write_byte_data(self.addr, cmd, data)
sleep(0.0001)
# Write a block of data
def write_block_data(self, cmd, data):
self.bus.write_block_data(self.addr, cmd, data)
sleep(0.0001)
# Read a single byte
def read(self):
return self.bus.read_byte(self.addr)
# Read
def read_data(self, cmd):
return self.bus.read_byte_data(self.addr, cmd)
# Read a block of data
def read_block_data(self, cmd):
return self.bus.read_block_data(self.addr, cmd)
# commands
LCD_CLEARDISPLAY = 0x01
LCD_RETURNHOME = 0x02
LCD_ENTRYMODESET = 0x04
LCD_DISPLAYCONTROL = 0x08
LCD_CURSORSHIFT = 0x10
LCD_FUNCTIONSET = 0x20
LCD_SETCGRAMADDR = 0x40
LCD_SETDDRAMADDR = 0x80
# flags for display entry mode
LCD_ENTRYRIGHT = 0x00
LCD_ENTRYLEFT = 0x02
LCD_ENTRYSHIFTINCREMENT = 0x01
LCD_ENTRYSHIFTDECREMENT = 0x00
# flags for display on/off control
LCD_DISPLAYON = 0x04
LCD_DISPLAYOFF = 0x00
LCD_CURSORON = 0x02
LCD_CURSOROFF = 0x00
LCD_BLINKON = 0x01
LCD_BLINKOFF = 0x00
# flags for display/cursor shift
LCD_DISPLAYMOVE = 0x08
LCD_CURSORMOVE = 0x00
LCD_MOVERIGHT = 0x04
LCD_MOVELEFT = 0x00
# flags for function set
LCD_8BITMODE = 0x10
LCD_4BITMODE = 0x00
LCD_2LINE = 0x08
LCD_1LINE = 0x00
LCD_5x10DOTS = 0x04
LCD_5x8DOTS = 0x00
# flags for backlight control
LCD_BACKLIGHT = 0x08
LCD_NOBACKLIGHT = 0x00
En = 0b00000100 # Enable bit
Rw = 0b00000010 # Read/Write bit
Rs = 0b00000001 # Register select bit
class lcd:
#initializes objects and lcd
def __init__(self):
self.lcd_device = i2c_device(ADDRESS)
self.lcd_write(0x03)
self.lcd_write(0x03)
self.lcd_write(0x03)
self.lcd_write(0x02)
self.lcd_write(LCD_FUNCTIONSET | LCD_2LINE | LCD_5x8DOTS | LCD_4BITMODE)
self.lcd_write(LCD_DISPLAYCONTROL | LCD_DISPLAYON)
self.lcd_write(LCD_CLEARDISPLAY)
self.lcd_write(LCD_ENTRYMODESET | LCD_ENTRYLEFT)
sleep(0.2)
# clocks EN to latch command
def lcd_strobe(self, data):
self.lcd_device.write_cmd(data | En | LCD_BACKLIGHT)
sleep(.0005)
self.lcd_device.write_cmd(((data & ~En) | LCD_BACKLIGHT))
sleep(.0001)
def lcd_write_four_bits(self, data):
self.lcd_device.write_cmd(data | LCD_BACKLIGHT)
self.lcd_strobe(data)
# write a command to lcd
def lcd_write(self, cmd, mode=0):
self.lcd_write_four_bits(mode | (cmd & 0xF0))
self.lcd_write_four_bits(mode | ((cmd << 4) & 0xF0))
# write a character to lcd (or character rom) 0x09: backlight | RS=DR<
# works!
def lcd_write_char(self, charvalue, mode=1):
self.lcd_write_four_bits(mode | (charvalue & 0xF0))
self.lcd_write_four_bits(mode | ((charvalue << 4) & 0xF0))
# put string function with optional char positioning
def lcd_display_string(self, string, line=1, pos=0):
if line == 1:
pos_new = pos
elif line == 2:
pos_new = 0x40 + pos
elif line == 3:
pos_new = 0x14 + pos
elif line == 4:
pos_new = 0x54 + pos
self.lcd_write(0x80 + pos_new)
for char in string:
self.lcd_write(ord(char), Rs)
# clear lcd and set to home
def lcd_clear(self):
self.lcd_write(LCD_CLEARDISPLAY)
self.lcd_write(LCD_RETURNHOME)
# define backlight on/off (lcd.backlight(1); off= lcd.backlight(0)
def backlight(self, state): # for state, 1 = on, 0 = off
if state == 1:
self.lcd_device.write_cmd(LCD_BACKLIGHT)
elif state == 0:
self.lcd_device.write_cmd(LCD_NOBACKLIGHT)
# add custom characters (0 - 7)
def lcd_load_custom_chars(self, fontdata):
self.lcd_write(0x40);
for char in fontdata:
for line in char:
self.lcd_write_char(line)
|
______________________________
2.- Códigos.
|
import I2C_LCD_driver
from time import *
mylcd = I2C_LCD_driver.lcd()
mylcd.lcd_display_string("Hola mundo.", 1)
|
- "Hola mundo" comienza en la fila 2, columna 3.
|
import I2C_LCD_driver
from time import *
mylcd = I2C_LCD_driver.lcd()
mylcd.lcd_display_string("Hola mundo.", 2, 3)
|
- Limpiar pantalla.
|
import I2C_LCD_driver
from time import *
mylcd = I2C_LCD_driver.lcd()
mylcd.lcd_display_string("Texto en pantalla", 1)
sleep(1)
mylcd.lcd_clear()
mylcd.lcd_display_string("Limpia pantalla", 1)
sleep(1)
mylcd.lcd_clear()
|
|
import time
import I2C_LCD_driver
mylcd = I2C_LCD_driver.lcd()
while True:
mylcd.lcd_display_string(u"Hola mundo.")
time.sleep(1)
mylcd.lcd_clear()
time.sleep(1)
|
- Fecha y hora.
|
import I2C_LCD_driver
import time
mylcd = I2C_LCD_driver.lcd()
while True:
mylcd.lcd_display_string("Hora: %s" %time.strftime("%H:%M:%S"), 1)
mylcd.lcd_display_string("Fecha: %s" %time.strftime("%m/%d/%Y"), 2)
|
- Dirección IP.
|
import I2C_LCD_driver
import subprocess
mylcd = I2C_LCD_driver.lcd()
IP = subprocess.check_output(["hostname", "-I"]).split()[0]
mylcd.lcd_display_string("IP:", 1)
mylcd.lcd_display_string(str(IP),2)
|
- Otras formas de ver la IP desde el terminal
ifconfig wlan0 | grep init | awk ‘{print $2}’
hostname -I
- Desplazamiento de caracteres y caracteres personalizados, lo puedes encontrar en:
http://www.circuitbasics.com/raspberry-pi-i2c-lcd-set-up-and-programming/
__________________________________________________
- Sensor de Temperatura y Humedad DHT11. Pantalla LCD. Librería dht11.
|
import RPi.GPIO as GPIO
import dht11
import I2C_LCD_driver
from time import *
mylcd = I2C_LCD_driver.lcd()
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.cleanup()
while True:
instance = dht11.DHT11(pin = 4)
result = instance.read()
# Uncomment for Fahrenheit:
# result.temperature = (result.temperature * 1.8) + 32
if result.is_valid():
mylcd.lcd_display_string("Temp: %d%s C" % (result.temperature, chr(223)), 1)
mylcd.lcd_display_string("Humidity: %d %%" % result.humidity, 2)
|
- Para el código anterior utilizaremos la librería dht11 obtenida de...
https://github.com/szazo/DHT11_Python/blob/master/dht11.py
- Este archivo de librería debe estar en el mismo directorio que el archivo anterior temperatura.py
|
import time
import RPi
class DHT11Result:
'DHT11 sensor result returned by DHT11.read() method'
ERR_NO_ERROR = 0
ERR_MISSING_DATA = 1
ERR_CRC = 2
error_code = ERR_NO_ERROR
temperature = -1
humidity = -1
def __init__(self, error_code, temperature, humidity):
self.error_code = error_code
self.temperature = temperature
self.humidity = humidity
def is_valid(self):
return self.error_code == DHT11Result.ERR_NO_ERROR
class DHT11:
'DHT11 sensor reader class for Raspberry'
__pin = 0
def __init__(self, pin):
self.__pin = pin
def read(self):
RPi.GPIO.setup(self.__pin, RPi.GPIO.OUT)
# send initial high
self.__send_and_sleep(RPi.GPIO.HIGH, 0.05)
# pull down to low
self.__send_and_sleep(RPi.GPIO.LOW, 0.02)
# change to input using pull up
RPi.GPIO.setup(self.__pin, RPi.GPIO.IN, RPi.GPIO.PUD_UP)
# collect data into an array
data = self.__collect_input()
# parse lengths of all data pull up periods
pull_up_lengths = self.__parse_data_pull_up_lengths(data)
# if bit count mismatch, return error (4 byte data + 1 byte checksum)
if len(pull_up_lengths) != 40:
return DHT11Result(DHT11Result.ERR_MISSING_DATA, 0, 0)
# calculate bits from lengths of the pull up periods
bits = self.__calculate_bits(pull_up_lengths)
# we have the bits, calculate bytes
the_bytes = self.__bits_to_bytes(bits)
# calculate checksum and check
checksum = self.__calculate_checksum(the_bytes)
if the_bytes[4] != checksum:
return DHT11Result(DHT11Result.ERR_CRC, 0, 0)
# ok, we have valid data, return it
return DHT11Result(DHT11Result.ERR_NO_ERROR, the_bytes[2], the_bytes[0])
def __send_and_sleep(self, output, sleep):
RPi.GPIO.output(self.__pin, output)
time.sleep(sleep)
def __collect_input(self):
# collect the data while unchanged found
unchanged_count = 0
# this is used to determine where is the end of the data
max_unchanged_count = 100
last = -1
data = []
while True:
current = RPi.GPIO.input(self.__pin)
data.append(current)
if last != current:
unchanged_count = 0
last = current
else:
unchanged_count += 1
if unchanged_count > max_unchanged_count:
break
return data
def __parse_data_pull_up_lengths(self, data):
STATE_INIT_PULL_DOWN = 1
STATE_INIT_PULL_UP = 2
STATE_DATA_FIRST_PULL_DOWN = 3
STATE_DATA_PULL_UP = 4
STATE_DATA_PULL_DOWN = 5
state = STATE_INIT_PULL_DOWN
lengths = [] # will contain the lengths of data pull up periods
current_length = 0 # will contain the length of the previous period
for i in range(len(data)):
current = data[i]
current_length += 1
if state == STATE_INIT_PULL_DOWN:
if current == RPi.GPIO.LOW:
# ok, we got the initial pull down
state = STATE_INIT_PULL_UP
continue
else:
continue
if state == STATE_INIT_PULL_UP:
if current == RPi.GPIO.HIGH:
# ok, we got the initial pull up
state = STATE_DATA_FIRST_PULL_DOWN
continue
else:
continue
if state == STATE_DATA_FIRST_PULL_DOWN:
if current == RPi.GPIO.LOW:
# we have the initial pull down, the next will be the data pull up
state = STATE_DATA_PULL_UP
continue
else:
continue
if state == STATE_DATA_PULL_UP:
if current == RPi.GPIO.HIGH:
# data pulled up, the length of this pull up will determine whether it is 0 or 1
current_length = 0
state = STATE_DATA_PULL_DOWN
continue
else:
continue
if state == STATE_DATA_PULL_DOWN:
if current == RPi.GPIO.LOW:
# pulled down, we store the length of the previous pull up period
lengths.append(current_length)
state = STATE_DATA_PULL_UP
continue
else:
continue
return lengths
def __calculate_bits(self, pull_up_lengths):
# find shortest and longest period
shortest_pull_up = 1000
longest_pull_up = 0
for i in range(0, len(pull_up_lengths)):
length = pull_up_lengths[i]
if length < shortest_pull_up:
shortest_pull_up = length
if length > longest_pull_up:
longest_pull_up = length
# use the halfway to determine whether the period it is long or short
halfway = shortest_pull_up + (longest_pull_up - shortest_pull_up) / 2
bits = []
for i in range(0, len(pull_up_lengths)):
bit = False
if pull_up_lengths[i] > halfway:
bit = True
bits.append(bit)
return bits
def __bits_to_bytes(self, bits):
the_bytes = []
byte = 0
for i in range(0, len(bits)):
byte = byte << 1
if (bits[i]):
byte = byte | 1
else:
byte = byte | 0
if ((i + 1) % 8 == 0):
the_bytes.append(byte)
byte = 0
return the_bytes
def __calculate_checksum(self, the_bytes):
return the_bytes[0] + the_bytes[1] + the_bytes[2] + the_bytes[3] & 255
|
_______________________________________________________
- Con la librería de Adafruit.
- Instalamos la librería para el sensor DHT11.
- Instalamos git, se utiliza para bajar librerías.
# apt-get update
# apt-get install git-core
# git clone https://github.com/adafruit/Adafruit_Python_DHT.git
# cd Adafruit_Python_DHT
[Observaremos los archivos: dht_consola.py dht_log.py README.md]
# apt-get install build-essential python-dev
# sudo python setup.py install
---------------------------------
- Otra forma de instalar la librería de Adafruit
- Bajamos: Adafruit_Python_DHT-master.zip
- Luego: sudo python setup.py install
-
https://www.electronicwings.com/raspberry-pi/dht11-interfacing-with-raspberry-pi
- Gráficos
https://d3js.org/
---------------------------------
- Otra manera si tenemos instalado pip
https://github.com/adafruit/Adafruit_Python_DHT
-
sudo pip3 install Adafruit_DHT
|
# Juan Antonio Villalpando
# kio4.com
import RPi.GPIO as GPIO
from time import sleep # Función sleep del módulo time
import Adafruit_DHT
from random import randint # Función aleatorio
# LCD
import I2C_LCD_driver
mylcd = I2C_LCD_driver.lcd()
# Publicación de Temperatura
#humidity, temperature = Adafruit_DHT.read_retry(11, 4)
temperature = randint(28,31)
|
___________________________________________________
|