Ebook Raspeberry e Python PDF
Ebook Raspeberry e Python PDF
Ebook Raspeberry e Python PDF
Setembro 2019
www.embarcados.com.br
www.embarcados.com.br
Ebook Programe Raspeberry Pi com
Python
Olá,
Um grande abraço.
Equipe Embarcados.
www.embarcados.com.br
Introdução
● Board: Raspberry PI B
● Distribuição: Raspbian - Debian Wheezy (2014-01-07)
● Kernel 3.12.22
● Python 2.7
● RPi.GPIO 0.5.6
www.embarcados.com.br
cleiton@vm03 ~ $ pip search RPi.GPIO
RPIO- Advanced GPIO for the Raspsberry Pi. Extends RPi.GPIO with PWM, GPIO interrupts, TCP
socket interrupts, command line tools and more
RPi.GPIO- A module to control Rapsberry Pi GPIO channels
...
www.embarcados.com.br
Esquema da ligação
Ligação simples como podemos ver na Figura01, onde ligamos o led vermelho ao
GND e usando um resistor conectamos ao pino 12 (BOARD) [GPIO18 (BCM)] e o
led verde ao GND e pino 11 (BOARD) [GPIO17 (BCM)], logo mais será
compreendido os termos BOARD e BCM.
www.embarcados.com.br
O Python por si só não sabe interagir com o GPIO (a menos que você utilize
/sys/class/gpio/…, mas não é o foco neste artigo), então utilizaremos um módulo que
já possui funções prontas para realizar todas as configurações e interagir com os
leds. O mais interessante é que foi possível usar o Python com a filosofia Arduino e
criar algo fácil de trabalhar.
Preparando o ambiente
Vamos preparar o Raspbian para utilizar este módulo, utilizando pip (Gerenciador
de Pacotes do Python). Não sabe se possui o pip? Execute o comando abaixo:
Se for exibido um erro durante a etapa acima, execute o procedimento abaixo para
instalar, caso seja como a saída acima, ignore a etapa abaixo
www.embarcados.com.br
RPi.GPIO
www.embarcados.com.br
Figura 02 – Informações GPIO Raspberry Pi
www.embarcados.com.br
Ao configurar o setmode() como BOARD ou BCM, a diferença é o número do pino,
por exemplo, no esquema informado na Figura01 estamos utilizando o
Led1(Vermelho) no ae o Led2(Verde) no GPIO17, que baseado na Figura02 temos a
seguinte informação:
BOARD: BCM
11: GPIO17
12: GPIO18
Código
Agora o código necessário para fazer com que o led verde pisque usando Python no
modo BOARD, vamos chamar o código abaixo de led1.py.
www.embarcados.com.br
Para executar o código led1.py:
Para encerrar, vamos interagir com os dois leds, utilizando modo BOARD, no
código led1_2.py.
www.embarcados.com.br
import RPi.GPIO as gpio
import time
gpio.setup(12, gpio.OUT)
print "Setando modo OUTPUT no PINO12 GPIO18 [LED VERMELHO]"
print
gpio.output(11, gpio.HIGH)
print "Led Verde aceso!"
time.sleep(2)
gpio.output(11, gpio.LOW)
print "Led Verde apagado!"
time.sleep(2)
gpio.output(12, gpio.HIGH)
print "Led Vermelho aceso!"
time.sleep(2)
gpio.output(12, gpio.LOW)
print "Led Vermelho apagado!"
time.sleep(2)
print
print "Tchau..."
www.embarcados.com.br
pi@rpb01 ~/python/led $ sudo python led1_2.py
Configurando o modo de acesso ao GPIO - BOARD
Tchau...
Conclusão
No próximo artigo vamos interagir com o GPIO usando um botão e ver alguns
problemas e soluções que podem ser implementadas utilizando o RPi.GPIO.
www.embarcados.com.br
Referências
https://pypi.python.org/pypi/RPi.GPIO
https://www.embarcados.com.br/arduino-vs-raspberry-pi/
http://pt.wikipedia.org/wiki/General_Purpose_Input/Output
http://www.hobbytronics.co.uk/raspberry-pi-gpio-pinout
http://cleitonbueno.wordpress.com/2014/08/25/python-solucionando-o-erro-fat
al-error-python-h-no-such-file-or-directory-no-pip-install/
www.embarcados.com.br
Este artigo foi escrito por Cleiton Bueno.
A primeira parte da série de interação com o GPIO (General Purpose Input Output)
do Raspberry PI no modo Output possui os passos fundamentais para esta
segunda etapa como a preparação do ambiente. Nesta segunda etapa vamos ver
o modo Input, e para a prática será utilizado o Raspberry PI B, protoboard,
pushbutton e alguns resistores. Serão mencionados os possíveis modos de
trabalho com Input utilizando resistores de pull-up e pull-down, internos ou
externos, e recursos como detecção de borda, debounce por software e uma
“interrupção” baseada na detecção por borda.
● Board: Raspberry PI B;
● Distribuição: Raspbian – Debian Wheezy (2014-01-07);
● Kernel 3.12.22;
● Python 2.7.3;
● RPi.GPIO 0.5.7.
www.embarcados.com.br
RPi.GPIO
Já vimos na primeira parte da série as funções RPi.GPIO.setmode(),
RPi.GPIO.setup(), RPi.GPIO.output(), RPi.GPIO.input() e RPi.GPIO.cleanup(), e
agora vamos ver algumas funções e parâmetros que tornam o modo input muito
interessante.
www.embarcados.com.br
A Figura 1 ilustra os comportamentos que ocorrerão no decorrer do artigo ao
acionar o pushbutton.
www.embarcados.com.br
PushButton com pull-down interno
www.embarcados.com.br
O primeiro exemplo prático será adicionar um pushbutton. Uma de suas
extremidades será conectada ao 3.3V (pino 1) e a outra ao pino 16 (ou GPIO 23) da
Raspberry Pi no modo BCM, como na Figura 2. Configurados via software
utilizando RPi.GPIO o pino 16 (GPIO 23) no modo INPUT e com pull-down interno.
Código:
#! /usr/bin/python
# -*- coding: utf-8 -*-
gpio.setmode(gpio.BCM)
while True:
if(gpio.input(23) == 1):
print("Botão pressionado")
else:
print("Botao desligado")
time.sleep(1)
gpio.cleanup()
exit()
Executando o código:
www.embarcados.com.br
PushButton com pull-up interno
www.embarcados.com.br
No segundo exemplo prático o mesmo PushButton será utilizado, trocando apenas
a extremidade de 3.3V (pino 1) para 0V GND (pino 6), como na Figura 3.
Configuraremos via software utilizando RPi.GPIO o pino 16 (GPIO 23) no modo
INPUT e com pull-up interno.
Código:
#! /usr/bin/python
# -*- coding: utf-8 -*-
gpio.setmode(gpio.BCM)
while True:
if(gpio.input(23) == 1):
print("Botão pressionado")
else:
print("Botao desligado")
time.sleep(1)
gpio.cleanup()
exit()
Executando o código:
www.embarcados.com.br
PushButton com pull-down externo
Código:
www.embarcados.com.br
#! /usr/bin/python
# -*- coding: utf-8 -*-
while True:
if gpio.input(PIN) == gpio.HIGH:
action_press_button(PIN)
break
else:
print "Botão desligado"
time.sleep(1)
gpio.cleanup()
exit()
Executando o código:
www.embarcados.com.br
PushButton com pull-up externo
Código:
www.embarcados.com.br
#! /usr/bin/python
# -*- coding: utf-8 -*-
while True:
#if gpio.input(PIN) == gpio.LOW:
if gpio.input(PIN) == 0:
action_press_button(PIN)
break
else:
print "Botão desligado"
time.sleep(1)
gpio.cleanup()
exit()
Executando o código:
www.embarcados.com.br
pi@raspberrypi ~/python/rpio/ $ sudo python pushbutton_pullup_externo.py
Botão desligado
Botão desligado
Botão desligado
Botão desligado
Botão desligado
O botão no pino 23 foi pressionado!
Saindo...
Não errei o código não, é que utilizando resistores externos altera-se apenas a
linha do if de gpio.HIGH para gpio.LOW. No caso ainda dei uma valorizada, onde
troquei gpio.LOW por 0.
Eventos e Interrupções
Código:
www.embarcados.com.br
# -*- coding: utf-8 -*-
#! /usr/bin/python
while True:
print "Polling..."
if gpio.event_detected(PIN):
action_press_button(PIN)
break
time.sleep(1)
gpio.cleanup()
exit()
Executando o código:
www.embarcados.com.br
pi@raspberrypi ~/python/rpio/ $ sudo python pushbutton_event_detect01.py
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
O botão no pino 23 foi pressionado!
Saindo...
Você pode testar, e pode ver que independente do momento que pressionar o
pushbutton, na ação dele ser pressionado (RISING), indo de 0V para 3.3V, como
estamos com pull-down, ele irá “guardar” esta mudança de estado. Na próxima
vez que for executado o loop, este evento será tratado, no nosso caso sendo
chamada a função action_press_button() e saindo do programa.
Código:
www.embarcados.com.br
# -*- coding: utf-8 -*-
#! /usr/bin/python
while True:
print "Polling..."
if gpio.event_detected(PIN):
action_press_button(PIN)
break
time.sleep(1)
gpio.cleanup()
exit()
Executando o código:
www.embarcados.com.br
pi@raspberrypi ~/python/rpio/ $ sudo python pushbutton_event_detect02.py
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
Polling...
O botão no pino 23 foi pressionado!
Saindo...
Não mudou nada na saída do código, tirando que o programa só parou quando
pressionamos e soltamos o PushButton. Enquanto o botão estiver pressionado,
nada acontece. O mesmo pode ser feito com BOTH, que a ação ocorrerá ao
pressionar e soltar.
Outra opção interessante no event_detect() é poder adicionar uma função a ser
chamada assim que ocorrer a mudança de estado, utilizando o parâmetro
callback. Seria a correspondência de uma "Interrupção", porém eu não gosto
muito deste termo e prefiro aceitar o de uma chamada em paralelo ou execução
já que uma segunda thread é disparada neste caso. Vamos ver!
www.embarcados.com.br
Código:
def action_press_button(gpio_pin):
print "Tratando o botão no pino %d que foi pressionado!" % gpio_pin
while True:
print "Polling..."
if gpio.event_detected(PIN):
action_press_button_loop(PIN)
break
time.sleep(1)
gpio.cleanup()
exit()
www.embarcados.com.br
Executando o código:
www.embarcados.com.br
Código:
#! /usr/bin/python
# -*- coding: utf-8 -*-
while True:
try:
if gpio.event_detected(PIN):
action_press_button(PIN)
gpio.remove_event_detect(PIN)
else:
print("Botão Desligado")
time.sleep(1)
except (KeyboardInterrupt):
print("Saindo...")
gpio.cleanup()
exit()
Executando o código:
www.embarcados.com.br
pi@raspberrypi ~/python/rpio/ $ sudo python pushbutton_event_detect04.py
Botão desligado
Botão desligado
Botão desligado
Você pressionou o botão no pino 23 e agora ele sera desativado
Botão desligado
Botão desligado
Botão desligado
^CSaindo...
#! /usr/bin/python
# -*- coding: utf-8 -*-
while True:
try:
print "Inicio loop..."
gpio.wait_for_edge(PIN1, gpio.RISING)
print "Botão foi pressionado"
gpio.wait_for_edge(PIN1, gpio.FALLING)
print "Botão foi liberado"
print "Continua loop..."
time.sleep(1)
except (KeyboardInterrupt):
print "Saindo..."
gpio.cleanup()
exit()
www.embarcados.com.br
Executando o código:
Conclusão
Podemos ver mais uma vez como Python é uma ferramenta fantástica para
prototipagem. Com poucas linhas e utilizando o RPi.GPIO conseguimos
manipular de diversas maneiras o GPIO do Raspberry Pi no modo input.
www.embarcados.com.br
Este artigo foi escrito por Cleiton Bueno.
Não conhece muito bem o Raspberry Pi? Veja o artigo Raspberry Pi do Thiago Lima.
E como vamos usar o Raspberry Pi B com Linux, para conhecer melhor essa dupla
veja o artigo A Raspberry Pi e o Linux de Vinicius Maciel. Se isso não te assusta,
continue lendo o artigo.
www.embarcados.com.br
Módulo RFID
O Mifare MFRC522 (NXP RC522), ou
comercialmente RFID-RC522, é um dos
mais populares leitores RFID do mercado,
no modo comprar, ligar e usar, uma
excelente forma para prototipar.
www.embarcados.com.br
Esquema de ligação
www.embarcados.com.br
Configuração do ambiente host
● Board: Raspberry Pi B;
● Distribuição: Raspbian – Debian Wheezy (2014-01-07);
● Kernel 3.12.22;
● Python 2.7.
Preparando o ambiente
Agora a parte legal, vamos preparar o Raspbian para liberar o uso device SPI no
Linux, resolver as dependências de software e testar com uma aplicação padrão de
teste. Para isso, o primeiro passo é verificar se o dispositivo SPI está liberado, ou
melhor, se o módulo do kernel subiu para fornecer o acesso.
pi@raspberrypi ~ $ ls /dev/spi*
ls: cannot access /dev/spi*: No such file or directory
pi@raspberrypi ~ $ lsmod | grep spi_bcm*
pi@raspberrypi ~ $ dmesg | grep spi
pi@raspberrypi ~ $
www.embarcados.com.br
Se na sua Raspberry Pi obteve as mesmas saídas acima, o módulo SPI está
desabilitado. Caso contrário, pule a próxima etapa. No Raspbian isso quer dizer que
ele está no black list do modprobe, e para habilitar o módulo SPI siga o passo a
passo abaixo e reinicie a Raspberry Pi.
# blacklist spi and i2c by default (manu users don't need them)
#blacklist spi-bcm2708
blacklist i2c-bcm2708
:wq
pi@raspberrypi ~ $ sudo reboot
Verificando novamente:
pi@raspberrypi ~ $ ls /dev/spi*
/dev/spidev0.0 /dev/spidev0.1
pi@raspberrypi ~ $ lsmod | grep
spi_bcm spi_bcm2708 4808 0
pi@raspberrypi ~ $ dmesg | grep spi
[ 5.078766] bcm2708_spi bcm2708_spi.0: master in unqueued, this is deprecated
[ 5.230200] bcm2708_spi bcm2708_spi.0: SPI Controller at 0x2020400 (irq 80)
pi@raspberrypi ~ $
www.embarcados.com.br
pi@raspberrypi ~ $ dpkg -list | grep -E 'ii.*python.*dev'
ii python-dbus-dev 1.1.1-1 all main loop integration development files
ii python2.7-dev 2.7.3-6+deb7u2 armhf Headers files and static library for Python
(v2.7)
O módulo para comunicação via SPI está pronto. Agora vamos baixar de outro
repositório um código exemplo pronto para comunicar com RC522, que depende
do módulo SPI-Py para funcionar, no caso é o MFRC522-python que, além do
SPI-Py, utiliza também o RPi.GPIO.
www.embarcados.com.br
pi@raspberrypi ~/spi-py $cd ~
pi@raspberrypi ~ $ mkdir -p python_rfid
pi@raspberrypi ~ $ cd python_rfid
pi@raspberrypi ~/python_rfid $ git clone https://github.com/mxgxw/MFRC522-python
Cloning into 'MFRC522-python'...
remote: Counting objects: 60, done.
remote: Total 60 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (60/60), done.
pi@raspberrypi ~/python_rfid $ cd MFRC522-python
pi@raspberrypi ~/python_rfid/MFRC522-python $
www.embarcados.com.br
Agora, vamos utilizar o módulo MFRC522.py e criar uma aplicação nossa baseada
no Read.py. Primeiro vou abrir o código do Read.py e comentá-lo, logo em seguida
irei escrever nossa aplicação (veja os comentários para mais detalhes).
#!/usr/bin/env python
# -*- coding: utf8 -*-
continue_reading = True
"""
Função que é chamada assim que Ctrl+C é pressionado
"""
# Capture SIGINT for cleanup when the script is aborted
def end_read(signal,frame):
global continue_reading
print "Ctrl+C captured, ending read."
continue_reading = False
GPIO.cleanup()
"""
Responsável por capturar o SIGINT gerado (Ctrl+C) e chamar a função end_read
"""
# Hook the SIGINT
signal.signal(signal.SIGINT, end_read)
"""
Criando um objecto da class MFRC522
"""
# Create an object of the class MFRC522
MIFAREReader = MFRC522.MFRC522()
# Welcome message
print "Welcome to the MFRC522 data read example"
print "Press Ctrl-C to stop."
"""
www.embarcados.com.br
Entra em um loop infinito baseado na variavel global :( continue_reading, que ira mudar o seu
valor assim que
a aplicação for interrompida e a função end_read() irá setar como False
"""
# This loop keeps checking for chips. If one is near it will get the UID and authenticate
while continue_reading:
"""
Maioria das chamadas abaixo falam por si só, irei comentar as que achar interessante
"""
# Scan for cards
(status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL)
# If a card is found
if status == MIFAREReader.MI_OK:
print "Card detected"
"""
Agora iremos receber o ID RFID e o status, e o nome Anticoll é baseado no proprio protocolo
no Registrador ErrorReg bit3 verifica se houve colisão dos dados
"""
# Get the UID of the card
(status,uid) = MIFAREReader.MFRC522_Anticoll()
# Print UID
print "Card read UID: "+str(uid[0])+","+str(uid[1])+","+str(uid[2])+","+str(uid[3])
"""
Uma camada de segurança a mais, onde além de verificar o ID que recebemos podemos enviar a
key dos chaveiros e tags e aguardar a autenticação
Veja no datasheet MF1S70yyX.pdf Pagina: 11 - 8.6.3 Sector trailer
E as rotinas para esta checagem segue abaixo.
www.embarcados.com.br
Usando a key abaixo é a chave de 6 bytes utilizada para
autenticar a comunicação maneira esta usando o MFAuthent
endereço 0x60 a 0x61
"""
Aqui é enviado a key do "fabricante", modo de autenticação 0x60 ou 0x61, Block Address e
nosso uid
"""
# Authenticate
status = MIFAREReader.MFRC522_Auth(MIFAREReader.PICC_AUTHENT1A, 8, key, uid)
# Check if authenticated
if status == MIFAREReader.MI_OK:
MIFAREReader.MFRC522_Read(8)
MIFAREReader.MFRC522_StopCrypto1()
else:
print "Authentication error"
www.embarcados.com.br
#!/usr/bin/env python
# -*- coding: utf8 -*-
import os
import sys
import signal
"""
Lista com relação dos IDs autorizados
"""
acessos_autorizados = [[227,41,93,116,227], [201,39,92,115,201], [225,95,12,103,225]]
"""
Vou tentar importar os modulos abaixo, caso algum problema ocorra,
sera lançada a exceção na sequencia
"""
try:
import MFRC522
import RPi.GPIO as GPIO
except ImportError as ie:
print("Problema ao importar modulo {0}").format(ie)
sys.exit()
"""
Funcao que irá garantir que o root ou usuario com permissão de
super-usuario irá executar a aplicação
"""
def check_user():
if os.geteuid() != 0:
print("Você deve executar o programa como super-usuario!")
#print "Exemplo:\nsudo python {0}".format(os.path.realpath(__file__))
print("Exemplo:\nsudo python {0}").format(__file__)
sys.exit()
"""
Captura o sinal gerado, no caso o que nos interessa é o sinal
SIGINT(Interrupção do Terminal ou processo) e irá encerrar a aplicação
"""
def finalizar_app(signal,frame):
global continue_reading
print("\nCtrl+C pressionado, encerrando aplicação...")
continue_reading = False
GPIO.cleanup()
continue_reading = True
www.embarcados.com.br
def main():
check_user()
while continue_reading:
# Scan for cards
#(status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL)
MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL)
if __name__ == "__main__":
main()
www.embarcados.com.br
pi@raspberrypi ~/rfid-python $ sudo python rfid_embarcados.py
Portal Embarcados - Python é sucesso!
Pressione Ctrl-C para encerrar a aplicação.
Acesso liberado!
Acesso liberado!
Acesso liberado!
Sem acesso!
Acesso liberado!
^C
Ctrl+C pressionado, encerrando aplicação...
Para melhorar essa aplicação, poderia utilizar um banco de dados que contém os
IDs com alguns nomes e informações, realizar consultas e, em caso de sucesso,
poderia acionar algum GPIO e abrir uma porta ou liberar algo. Implemente,
invente e faça seus testes e qualquer dúvida envie pelos comentários.0
www.embarcados.com.br
Conclusão
Referências
http://www.nxp.com/documents/data_sheet/MFRC522.pdf
https://github.com/lthiery/SPI-Py
https://github.com/mxgxw/MFRC522-python
https://pypi.python.org/pypi/RPi.GPIO
https://www.nxp.com/documents/data_sheet/MF1S70YYX.pdf
www.embarcados.com.br
Este artigo foi escrito por Cleiton Bueno.
www.embarcados.com.br
Eles podem ser especificados pelo número de caracteres que podem existir em
cada linha e também pelo número de linhas. Por exemplo 16x2, 20x2, 40x4, entre
outros.
Neste artigo será abordado o display de LCD 16x2 e trabalhando em modo 4 bits
para fins de economia de portas GPIO. Para maiores informações sobre esses
dispositivos, recomendo a leitura do artigo Módulo de Display LCD publicado por
Henrique Puhlmann.
www.embarcados.com.br
Desconsidere caso apareça alguma informação de erro, pois a biblioteca
provavelmente já estava instalada anteriormente. A biblioteca do display LCD que
vamos trabalhar é a Adafruit_Python_CharLCD. Deve-se realizar o download e
executá-la, utilizando os seguintes comandos:
cd ~
git clone https://github.com/adafruit/Adafruit_Python_CharLCD.git
cd Adafruit_Python_CharLCD
sudo python setup.py install
Comandos
● lcd.home():
www.embarcados.com.br
Cria um objeto que nesse exemplo é chamado de “lcd”, mas poderia ser qualquer
outro nome. Também inicializa e configura os pinos que enviaram os dados para
o display LCD. Esta função configura o modo de funcionamento em 4 bits.
● lcd.clear():
● lcd.set_cursor(col, row):
Posiciona o cursor na posição definida pelos valores que são definidos por “col” e
por “row”. Como o display de LCD que estamos usando é 16 x 2, então o valor de
“col” varia entre 0 a 15 e “row” varia entre 0 ou 1.
● lcd.enable_display(enable):
● lcd.show_cursor(show):
● lcd.blink(blink):
● lcd.move_left():
www.embarcados.com.br
Move o cursor para a esquerda uma posição.
● lcd.move_right():
● lcd.set_left_to_right():
● lcd.set_right_to_left():
● lcd.autoscroll(autoscroll):
Essa função formata o texto justificado à direita se “autoscroll” recebe o valor true,
caso contrário o texto será justificado à esquerda.
● lcd.message(‘texto”):
● lcd.backlight(backlight):
www.embarcados.com.br
Recebe um valor de 8 bits e escreve no display LCD um caractere ou um dado. O
“value” deve ser um valor inteiro de 0 a 255. Se “char_mode” é true o valor
retornado é um caractere, caso contrário será um dado.
● lcd.create(location, pattern):
Existem mais funções dentro da biblioteca mas que não são tão utilizadas. Devido a
isso, não foram apresentadas neste artigo. Caso haja interesse de aprofundar o
estudo sobre ela, pode-se acessar o endereço eletrônico no GitHub.
Circuito
www.embarcados.com.br
Esquema Elétrico
www.embarcados.com.br
Montagem
Código
O código deste projeto é similar ao código do artigo anterior, PWM com python,
mas neste são acrescentadas funções que realizam a manipulação do display LCD
apresentando as informações referentes ao valor no duty cycle, que por
consequência realiza alteração na luminosidade do LED.
www.embarcados.com.br
Deem uma recapitulada nesse artigo, por ser um continuação e para não ficar
repetitivo não será realizada superficialmente a descrição do código referente ao
artigo anterior. Então vamos lá!
# Define Libraries
import RPi.GPIO as gpio
import Adafruit_CharLCD as LCD
import time
# Functions
# This function inserts string and manipulates
# its position on LCD display screen
def screen_control(dc):
print("Duty Cycle:",dc)
lcd.clear()
lcd.set_cursor(3,0)
lcd.message('PWM CONTROL')
lcd.set_cursor(0,1)
lcd.message('Duty Cycle:')
dc_s = str(dc)
lcd.set_left_to_right()
lcd.set_cursor(12,1)
lcd.message(dc_s)
if dc < 10:
lcd.set_cursor(13,1)
elif dc >= 10 and dc < 100:
lcd.set_cursor(14,1)
elif dc == 100:
lcd.set_cursor(15,1)
lcd.message('%')
pwm.ChangeDutyCycle(dc)
return
www.embarcados.com.br
#Configuring GPIO
gpio.setwarnings(False)
gpio.setmode(gpio.BCM)
gpio.setup(17,gpio.IN, pull_up_down = gpio.PUD_DOWN)
gpio.setup(27,gpio.IN, pull_up_down = gpio.PUD_DOWN)
gpio.setup(26,gpio.OUT)
# Initializing PWM
dc = 50
pwm.start(dc)
while True:
www.embarcados.com.br
# Decreasing the duty cycle of the PWM waveform
elif gpio.event_detected(27):
dc = dc - 5
if dc < 0:
dc = 100
screen_control(dc)
time.sleep(0.1)
gpio.cleanup()
exit()
Entre as linhas 31 e 38 definem as GPIOs que serão utilizadas nas conexões entre a
Raspberry Pi e os conectores do display de LCD. Essa definição deve estar
compatível com o desejo apresentado no esquema elétrico e na montagem das
conexões mostradas nas figuras 2 e 3. Caso haja alguma alteração nas GPIOs,
deve-se ficar atento às conexões também.
www.embarcados.com.br
Da linha 40 à linha 46 são definidas as configuração dos pinos, se serão GPIOs.
Sendo assim, as GPIOs 17 e 27 são definidas como entrada, e possuindo um
resistor interno de pull-down em cada uma delas e a GPIO 26 como saída.
As linhas 48 e 49 definem que o display LCD será de 16 colunas por 2 linhas. Se ele
for utilizar de outra configuração, esses valores devem ser alterados, como é
citado nas linhas 52 e 53.
Nas linhas 56, 57 e 58 é definido o objeto chamado “ldc”. Poderia ser dado outro
nome, e este recebe os valores definidos entre as linhas 31 e 38.
A linha 61 define que GPIO 26 será a saída PWM com frequencia de 100 Hz.
www.embarcados.com.br
Conclusão
www.embarcados.com.br
Este artigo foi escrito por Roniere Rezende.
Este artigo é continuidade aos dois artigos sobre entrada e saída de dados no
Raspberry publicado pelo Cleiton Bueno.
O que é PWM?
www.embarcados.com.br
Figura 1 - Duty Cycle no PWM
www.embarcados.com.br
Para um sinal com frequência de 500 Hz, temos um período de 2 ms como calculado
abaixo:
Agora então vamos realizar o cálculo do tempo em nível lógico alto para as cinco
situações.
Para duty cycle de 0%:
Pode-se ver que quando o duty cycle é de 0%, o tempo em nível lógico alto é de 0s e
comprovando o que é apresentado na Figura 01 no intervalo de tempo anterior a 0
s.
Para duty cycle de 25%:
Pode-se ver que quando o duty cycle é de 25%, o tempo em nível lógico alto é de
500 us e comprovando o que é apresentado na Figura 01 no intervalo de
tempo entre 0 e 2 ms .
Para duty cycle de 50%:
www.embarcados.com.br
Pode-se ver que quando o duty cycle é de 50%, o tempo em nível lógico alto é de 1
ms e comprovando o que é apresentado na Figura 01 no intervalo de tempo entre
2 e 4 ms.
Para duty cycle de 75%:
Pode-se ver que quando o duty cycle é de 75%, o tempo em nível lógico alto é
de 1,5 mse comprovando o que é apresentado na Figura 01 no intervalo de
tempo entre 4 e 6 ms.
Pode-se se ver que quando o duty cycle é de 100%, o tempo em nível lógico alto é
de 2 ms, que é o mesmo tempo do período da freqüência, e comprovando o que
é apresentado no intervalo de tempo entre 6 e 8 ms.
www.embarcados.com.br
Comandos Python para PWM na Raspberry Pi
Nesta função se cria um objeto chamado “pwm”, mas poderia ser dado qualquer
outro nome a este objeto, como poderemos ver no exemplo 01.O argumento
“canal” é o pino em que será utilizado como saída PWM e o argumento
“frequência” define a frequência do sinal aplicada na saída do pino definido no
argumento “canal”.
● pwm.start(DCInicio):
Esta função inicializa o sinal PWM com um valor do duty cycle, deevendeo estar
entre 0 a 100, respectivamente representando 0% a 100% .
www.embarcados.com.br
● pwm.ChangeDutyCycle(DC):
Esta função é utilizada durante a execução do código para variar o valor do duty
cycleentre 0% e 100%. Nos exemplos apresentados mais abaixo, entenderemos
melhor o seu uso.
Exemplos
Para ilustrar tudo que foi apresentada até o momento, vamos apresentar dois
códigos simples desenvolvidos que se utilizam dos conceitos e definições da PWM
e como as funções da biblioteca RPi.GPIO do Python são aplicadas no decorrer do
código. Vamos então a eles:
Exemplo 01
www.embarcados.com.br
Circuito
Código Python
www.embarcados.com.br
#Define Libraries
import RPi.GPIO as gpio
import time
#Configuring GPIO
pio.setmode(gpio.BOARD)
gpio.setup(38,gpio.OUT)
gpio.setup(40,gpio.OUT)
pwmRed = gpio.PWM(40,100)
pwmRed.start(100)
#Create the dutycycle variables
dcBlue = 0
dcRed = 100
#Loop infinite
while True:
#End code
gpio.cleanup()
exit()
www.embarcados.com.br
A linha 6, faz que não se mostre os warnings no shell do Python.
www.embarcados.com.br
As linhas 43 e 44 finalizam o código.
Exemplo 02
Neste exemplo, o controle do duty cycle é realizado por duas chaves, uma para
incrementar e outra decrementar, e este representado por led que tem a sua
luminosidade alterada de acordo com o seu valor. Vamos então analisar o código
passo-a -passo para melhor entendimento do que está sendo realizando no
código Python.
Circuito
www.embarcados.com.br
O circuito acima apresenta as conexões a serem realizadas em um protoboard
para que o circuito definido no exemplo 02 funcione corretamente. As duas
chaves push-button tem um dos seus terminais conectados ao pino 1 que
fornece a tensão de 3,3 V e o outro terminal de cada uma deve ser conectados
respectivamente nos pinos 11 e 12. No pino 40 é conectado um dos terminais do
resistor de 1 kΏ e no outro terminal deve ser conectado ao terminal do anodo do
led. O terminal cátodo do led deve ser conectado ao terminal do pino 6 que é o
GND da Raspberry.
Código Python
#Define Libraries
import RPi.GPIO as gpio
import time
#Configuring GPIO
gpio.setwarnings(False)
gpio.setmode(gpio.BOARD)
gpio.setup(11,gpio.IN, pull_up_down = gpio.PUD_DOWN)
gpio.setup(12,gpio.IN, pull_up_down = gpio.PUD_DOWN)
gpio.setup(40,gpio.OUT)
#Initializing PWM
pwm.start(50)
dc = 50
print("Duty Cycle:",dc)
pwm.ChangeDutyCycle(dc)
while True:
www.embarcados.com.br
# Increasing the duty cycle of the PWM waveform
if gpio.event_detected(11):
dc = dc + 10
if dc == 110:
dc = 0
print("Duty Cycle:",dc)
pwm.ChangeDutyCycle(dc)
time.sleep(0.1)
gpio.cleanup()
exit()
A linha 13 é definido o objeto “pwm” e também que o seu canal será o pino 40 e a
frequência será de 100 Hz.
Entre as linhas 17 e 19, é criada uma variável chamada “dc” que recebe o valor 50
representando o valor de duty cycle de 50% e esse valor é mostrada na tela do shell
do Python. E este valor é aplicado na pino 40 onde está conectado o led.
www.embarcados.com.br
Entre as linhas 22 e 23 definem que os pinos 11 e 12 interpretem como nível lógico
alto uma borda de subida e é aplicado um debounce de 300 ms.
Conclusão
Pode-se observar que a PWM é uma aplicação que é utilizada para inúmeras
aplicações e que as funções contidas na biblioteca Python para o Raspberry Pi 3 são
simples de serem manipuladas e aplicadas, o que pode ser observado pelos
exemplos de códigos apresentados neste artigo.
www.embarcados.com.br
Este artigo foi escrito por Roniere Rezende.
Termômetro Digital
Para o desenvolvimento do projeto de aplicação do termômetro digital serão
necessários os seguintes componentes:
● 1 Raspberry Pi;
● 1 Sensor AM2302 da AOSONG;
● 1 Display de LCD de 16 colunas e 2 linhas;
● 2 botões de push-botton.
www.embarcados.com.br
O módulo sensor de temperatura e umidade AM2302 obtém os dados, os processa
e transmite à Raspberry Pi. Esta manipula e envia os dados recebidos para serem
apresentados na tela do display de LCD. A definição destas funções são
apresentadas neste artigo. Dois botões push-botton são utilizados para apresentar
na tela do display de LCD os valores de temperatura máxima e mínima registradas
durante o período de análise da medição, um para cada registro.
Tela de Medição
www.embarcados.com.br
Sensor de Temperatura e Umidade
www.embarcados.com.br
As aplicações para o módulo AM2302 são para aquecimento, ventilação e ar
condicionado (sigla em inglês HVAC), desumidificador, equipamento de teste e
inspeção, bens de consumo, automotivo, controle automático, registradores de
dados, aplicações caseiras, regulador de umidade, equipamentos médicos,
estações climáticas, controle e medida de umidade e, mais recentemente,
pode-se utiliza-lo em aplicações IoT.
3 NC Não utilizável
www.embarcados.com.br
Como pode ser visto na tabela 1, a alimentação do módulo AM2302 deve ser
entre 3,3 V até 5V, sendo 5V o valor recomendado no datasheet. O pino SDA é
uma estrutura de leitura e escrita de dados. Detalhes sobre o protocolo de
comunicação serão definidos mais abaixo.
www.embarcados.com.br
Tabela 3 - Desempenho de Temperatura Relativa do AM2302
Resolução 0,1 °C
16 bit
Faixa -40 80 °C
Precisão ±0,5 ±1 °C
Repetibilidade ±0,2 °C
www.embarcados.com.br
Tabela 4 - Características DC do Módulo 2302
Medindo 500 µA
Média 300 µA
Rpu VDD = 5V 30 45 60 kΩ
VIN = VSS
Desligado 10 20 µA
Periodo de Amostragem 2 S
www.embarcados.com.br
Para se realizar a comunicação entre o módulo AM2302 e a Raspberry Pi devem
ser seguidas algumas recomendações, citadas no seu datasheet. Elas são listadas a
seguir também:
www.embarcados.com.br
O SDA (Serial Data Line) é utilizado para comunicação e sincronização entre a
Raspberry Pi e o AM2302 e o formato de dados do barramento simples é
formado por 40 bits, como mostrado na Figura 3. A sua descrição é apresentada
na Tabela 5.
Formato de O receptor recebe sinal de início, o sensor envie a string de dados de 40 bits e
dados termina deixando a saída em nível lógico alto.
Temperatura O nível lógico do bit mais significativo (bit 15) é igual a 1 para indicar
temperatura negativa e será 0 para indicar temperatura positiva.
www.embarcados.com.br
A temporização da comunicação do barramento simples é realizada da seguinte
forma. O dispositivo do usuário envia um sinal de início (o barramento de dados
permanece em nível lógico baixo por pelo menos 800 µs), depois o AM2302 passa
do Modo de Inatividade para o Modo de Alta Velocidade. O dispositivo do usuário
indica ao módulo AM2302 enviando-lhe um sinal de resposta através do
barramento de dados, no caso um byte em nível lógico alto. O módulo envia os
dados (umidade alta, umidade baixa, temperatura alta, temperatura baixa e bit de
paridade) ao final da coleta de informações de trigger, e no fim do processo o
sensor é automaticamente transferido para o Modo de Inatividade, esperando
até a próxima comunicação.
www.embarcados.com.br
Tabela 06 - Características do sinal do barramento único
www.embarcados.com.br
Este artigo foi escrito por Roniere Rezende.
cd Adafruit_Python_DHT
www.embarcados.com.br
Comandos
As duas próximas declarações definem qual o modelo de sensor irá ser usado no
código.
sensor = Adafruit_DHT.DHT11
sensor = Adafruit_DHT.DHT22
www.embarcados.com.br
Circuito
A montagem do circuito do termômetro digital é similar ao mostrado no artigo
anterior sobre o display de LCD, agora é acrescentado o módulo AM2302. A
pinagem desse módulo pode ser vista na Figura 1. Para esta montagem, o módulo é
alimentado por uma tensão de 3,3V para se evitar que a tensão no barramento de
dados supere a máxima tensão suportada pelas portas GPIO da Raspberry Pi e, por
consequência, as danifique. Um resistores de pull-up é colocado entre o VCC e o
barramento de dados do módulo AM2302 para mantê-lo em nível lógico alto
quando não estiver sendo utilizado o barramento. Para se evitar ruídos e
interferências na medição do módulo 2302, é colocado um capacitor cerâmico de
100 nF mais próximo possível dos terminais de VCC e GND do módulo AM2302.
Os dois botões presentes na montagem são utilizados para que se possa visualizar a
máxima e a mínima temperatura registrada durante o período de medição que são
pressionados.
www.embarcados.com.br
Esquema Elétrico
Montagem
www.embarcados.com.br
Código
O código em linguagem Python descrito abaixo faz com que os dados de
temperatura e umidade relativa do ar obtidos do módulo AM2302 sejam
interpretados pela Raspberry Pi e ela mostre as informações na tela do display de
LCD. O código também faz o registro de máxima e mínima temperaturas obtidas
durante o intervalo de medição, apresentando o instante que o evento ocorreu.
# Carrega as bibliotecas
from datetime import datetime
import Adafruit_CharLCD as LCD
import RPi.GPIO as GPIO
import Adafruit_DHT
import time
www.embarcados.com.br
# Desabilita os Warnings
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
while True:
#Variáveis que recebem os valores de data e hora
tdy = datetime.today()
now = datetime.now()
time.sleep(0.1)
#Variáveis que recebem os valores de umidade e temperatura
umid, temp = Adafruit_DHT.read_retry(sensor, DHT_IN);
www.embarcados.com.br
#Configura os dados de umidade no LCD
lcd.set_cursor(0,1)
lcd.message('Humid:')
umid_s = str(umid)
lcd.set_cursor(9,1)
lcd.message(umid_s.ljust(5)[:5])
lcd.set_cursor(15,1)
lcd.message('%')
www.embarcados.com.br
# Define a posição dos dados do dia que ocorreu o evento
# o máximo valor na tela
if int(day_max) < 10:
lcd.set_cursor(0,1)
lcd.message('0')
lcd.set_cursor(1,1)
lcd.message(day_max)
else:
lcd.set_cursor(0,1)
lcd.message(day_max)
lcd.set_cursor(2,1)
lcd.message('/')
www.embarcados.com.br
# Sai do loop infinito de temperatura máxima
if ((GPIO.input(KEY_MAX) == GPIO.HIGH) and flag == True) == True:
break
time.sleep(0.5)
lcd.set_cursor(2,1)
lcd.message('/')
www.embarcados.com.br
# Configura a posiçõa do ano e hora do valor mínimo do display LCD
lcd.set_cursor(5,1)
lcd.message('/')
lcd.set_cursor(6,1)
lcd.message(year_min)
lcd.set_cursor(11,1)
lcd.message(hour_min)
lcd.set_cursor(13,1)
lcd.message(':')
gpio.cleanup()
exit()
www.embarcados.com.br
Descrição do Código
Entre as linhas 2 e 6 são declaradas as bibliotecas das funções que serão usadas
no código.
Na linha 10 é definido qual modelo de sensor que iremos utilizar, no caso usar o
modelo DHT-22.
Nas linhas 22, 23 e 24 são definidas as variáveis que definem quais são os GPIOs
que serão utilizados como entrada de dados.
Na linha 42 define-se um valor inicial para a variável que será utilizada para
armazenar o valor de temperatura máxima e na linha 43 define-se um valor
inicial para a variável que será utilizada para armazenar o valor de temperatura
mínima.
www.embarcados.com.br
Nas linhas 46, 47 e 48 é declarado o objeto “lcd” a partir da função que define quais
GPIOs irão ser utilizados para manipular o display de LCD.
Na linha 50 é onde o loop infinito principal deste código fonte é definido.
Na linha 59 é testado se os dados gerados pelo módulo AM2302 são válidos. Sendo
válidos, o código é executado. Caso contrário, é gerada uma mensagem de erro
presente entre as linhas 229 e 232.
www.embarcados.com.br
Entre as linhas 163 e 226 são acessados os dados de menor temperatura registrada
durante o intervalo de medição. A manipulação dos dados é realizada de forma
similar ao que é realizado para temperatura máxima.
Conclusão
Com essas informações em mãos, pode-se observar que é simples utilizar o módulo
AM2303 ou DHT-22 para outras aplicações onde se há a necessidade de analisar as
informações de temperatura e umidade relativa ar e realizar algumas atuações a
partir desses dados.
www.embarcados.com.br
Este artigo foi escrito por Roniere Rezende.
Caso você tenha alguma dúvida, não deixe ela sem resposta. Você pode entrar em
contato com o autor através da seção de comentários do artigo, ou então
participar da nossa comunidade, interagindo com outros profissionais da área:
Comunidades Embarcados
contato@embarcados.com.br
Siga o Embarcados na Redes Sociais
facebook.com/osembarcados/
instagram.com/portalembarcados/
youtube.com/embarcadostv/
linkedin.com/company/embarcados/
twitter.com/embarcados