Raspberry Pi 3 e Python – Iniciação!!

Introdução

Sempre tive curiosidade em lidar com automação. Seja para fazer experimentos que venham a render algo, mas na sua grande maioria é por hobby mesmo!

Recentemente adquiri uma plaquinha do Raspberry Pi 3. Execelente para esses propósitos e com uma vantagem, em relação ao Arduino, que é poder programá-lo em Python, já que o Arduino a programação é em C++ com pequenas modificações. Foi então que parte de minha curiosidade e vontade fazer algo em automação começou.

Claro que para um início, o projeto que escolhi foi muito, mas muito tranquilo de se fazer. Um pequeno circuito com o Sensor DHT11 para leituras da temperatura ambiente e umidade relativa do ar. Mas, o que já me proporcionou momentos de grande aprendizado em relação ao Raspberry, ao Python e na integração entre ambos.

O Raspberry – RPi

Uma plaquinha poderosa e de baixo custo, varia de R$180 a R$290 no Mercado Livre, isso sem contar nos diversos kits que são vendidos, um pouco mais caros, mas que acompanham acessórios e outras coisinhas!!!

O que utilizo é um Raspberry Pi 3 Model B, a qual passarei a chamar de RPi para simplificar, que possui as seguintes especificações ténicas:

  • chipset Broadcom BCM2387
  • 1.2GHz quad-core ARM córtex-A53
  • 802.11 bgn wireless LAN e Bluetooth 4.1 (Bluetooth Classic e LE)
  • 1 GB de RAM
  • CPU de 64 bits
  • 4 portas USB
  • Saída estéreo de 4 portas e porta de vídeo composto
  • Conexão HDMI
  • Entrada de rede Ethernet 10/100 BaseT
  • Porta de câmera CSI para conexão da câmera Raspberry Pi
  • Porta de exibição DSI para conectar a tela de toque Touch Raspberry Pi
  • Porta Micro SD para carregar seu sistema operacional e armazenar dados
  • Entrada para Fonte de alimentação Micro USB
  • GPIO de 40 pinos

Eis uma imagem dele:

Preparando o ambiente

Utilizando um cartão microSD com 32Gb de capacidade instalamos a mais recente versão do Raspbian Stretch a distribuição Debian oficial para o RPi. O cartão é mais que suficiente para o sistema e para os dados, já que o RPi não possuiu uma unidade de armazenamento.

Após a instalação do Raspbina Stretch, passamos à configuração do sistema para o que nos propomos fazer! Não há mistérios nessa configuração, vejamos como foi o processo.

Instalando o Docker e Docker-Compose

Instalamos o Docker, pois vamos utilizá-lo para subir um container do PostgreSQL, para isso fizemos:

curl -sSL https://get.docker.com | sh — Isso instalará o Docker no RPi

sudo usermod -aG docker pi — Isso coloca o usuário pi no gruo docker, para não precisar executar as instruções do docker usando o sudo

sudo systemctl enable docker — Isso configura o sistema para que sempre que for iniciado o docker também o seja.

sudo reboot -h now — Bom, com essa linha reiniciamos o sistema.

Agora vamos à instalação do Docker-compose, que utilizamos para subir nosso container do PostgreSQL utilizando do arquivo de configuração docker-compose.yml, para isso executamos:

sudo apt intall docker-compose

Preparando o docker-compose.yml

Nosso arquivo de configuração ficou assim:

version: "2"

services:
  meteriologia:
    image: postgres:10.5
    container_name: "meteorologia"
    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
    volumes:
      - "./data/postgres:/var/lib/postgresql/data"
    ports:
      - 5432:5432

Explicando os passos tomados:

  • version expõem a versão do docker-compose que estamos usando
  • services lista os serviços, no nosso caso somente um.
  • image indica a imagem docker que vamos utilizar, no nosso caso para Postgres versão 10.5
  • container_name o nome que estamos dando ao nosso container
  • environment seta as variáveis de ambiente que precisamos para que tudo fucione, nesse caso específico, para fins didáticos, mantivemos usuário, senha e banco padrões do PostgreSQL, mas é aqui que deve ser definido as variáveis com seus reais valores.
  • volumes aqui definimos os diretórios no host e no container que ficarão os arquivos do Postgres, lembrando que o container pode apresentar falhas e fechar, se não tivermos essas definições os dados não serão mantidos, e perderemos tudo que tiver sido gravado no banco.
  • ports aqui bindamos a porta do host com a do container para que a comunicação aconteça!

Finalizada a criação do docker-compose.yml está na hora de subirmos nosso container, para tanto utilizamos o seguinte comando:

docker-compose -d up meteorologia

Importante observar:

  1. O -d indica que o container vai rodar em daemon, ou seja, em segundo plano

  2. O meteorologia é o nome do serviço que demos em nosso arquivo docker-compose.yml

Instalando o pyenv e o Python 3.7.0

Vamos instalar, agora, o pyenv, o utilizamos para manter nossa versão do python distinta das que já vem instaladas no sistema, e porque vamos usar o python 3.7.0, que não é a versão do sistema, bom vamos ao que interessa!!

Atualizamos o sistema:

sudo apt update && sudo apt upgrade -y

Instalamos as dependências do pyenv:

sudo apt-get update && sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev xz-utils tk-dev libffi-dev liblzma-dev libncursesw5-dev openssl bzip2

Agora a instalação do pyenv

curl -L https://raw.githubusercontent.com/yyuu/pyenv-installer/master/bin/pyenv-installer | bash

Não esquecer de inserir as seguintes linhas no final do arquivo ~/.bashrc

export PATH="~/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"

Atualizamos o pyenv:

pyenv update

Finalmente instalamos o Python 3.7.0:

pyevn install 3.7.0

Obs.: A instalação aqui é bem demorada, no meu RPi levou pelo menos uns 10 minutos para finalizar a instalação do Python 3.7.0.

Após a instalação do Python 3.7.0, temos, pelo pyenv, duas versões do Python, isso é possível de verificar executando o seguinte comando:

pyenv versions

Cuja saída é:

* system
  3.7.0 (set by /home/pi/.pyenv/version)

Note que há um asterísco na versão do sistema, indicando que é a versão ativa no momento. E temos, também, a versão que acabamos de instalar. Ok, mas o que fazer para que a versão que ativa seja a que acabamos de instalar?

Não vamos entrar nos pormenores, para isso você pode assistir à Tech Talk do Python Pro na qual discutimos sobre o pyenv. Mass, basicamente, o que precisaos é executar um comando do pyenv para torna a versão que acabamos de instalar a versão global do sistema. Eis o comando:

pyenv global 3.7.0

Feito isso, se executarmos de novo o comando pyenv versions teremos uma saída bem semelhante, mas cuja diferença estará na posição do asterísco, veja:

  system
* 3.7.0 (set by /home/pi/.pyenv/version)

Indicando que agora a versão que temos como global para uso é a versão 3.7.0 do Python.

Após a instalação do Python, precisamos agora preparar nosso projeto. Bora lá então:

Configurando o Projeto Python

Primeiramete, criamos um diretório para o projeto e iniciamos um virtualenv nele.

~/Documents/# mkdr meteoroloiga
~/Documents/# cd meteorologia
~/Documents/meteorologia/#

Pronto, com isso temos o diretório de nosso projeto, vamos agora ao ambiente virtual:

~/Documents/meteorologia/# python -m venv .meteorologia

Criado nosso ambiente virtual, vamos ativá-lo:

~/Documents/meteorologia/# source .meteorologia/bin/activate
(meteorologia) ~/Documents/meteorologia/#

Feito, com isso agora podemos instalar as bibliotecas que nosso projeto necessita sem, contudo, enchar o python global com elas, mantendo um ambiente bem isolado.

Instalando as dependências do projeto

Bom, vamos entender o que nosso proejto vai fazer, num fluxo em alto nível bem simples:

  1. Acessar a GPIO do Raspberry para ler as informações do sensor DHT11, para isso vamos necessitar da biblioteca RPi.GPIO

  2. Lerá os dados de temperatura e umidade do sensor DHT11, para isso vamos necessitar da biblioteca chamada Adafruit_DHT.

  3. Gravará esses dados numa base de dados em PostgreSQL, para isso vamos precisar da biblioteca Psycopg2.

  4. Enviará, também, essas informações para o site ThingSpecks, para isso vamos precisar da biblioteca requests.

Bom, tendo isso em mente e nosso ambiente virtual ativado, bora instalar as dependências, seguindo os ordem descrita no fluxo acima temos:

(meteorologia) ~/Documents/meteorologia/# pip install RPi.GPIO
(meteorologia) ~/Documents/meteorologia/# pip install Adafruit_DHT
(meteorologia) ~/Documents/meteorologia/# pip install psycopg2
(meteorologia) ~/Documents/meteorologia/# pip install request

Pronto, nosso sistema está configurado e pronto para ser trabalhado.

Preprando o Hardware

Bom, vamos fazer um pequeno experimento e vamos utilizar alguns materiais que comporão nosso circuito, esses materiais são descrito e mostrada em imagem abaixo:

Um sensor de temperatura e umidade DHT11

Um resistor de 1k5, que indica ser o resistor de 1 Kilo OHMs com tolerância de +/- 5%

Uma protobord e Jumpers para as ligações

A montagem é super simples, abaixo um esquema de como pode ser feito:

Essa montagem ao final fica bonita assim:

Fazendo a programação Python

Bom, até agora o que fizemos foi:

  • Instalar o Raspibian e configurá-lo com o que precisamos
  • Juntar as peças do nosso quebra-cabeças inteligente e montá-lo conforme nossa necessidade.

Mas, ainda falta o cérebro de tudo isso, falta fazermos a programação do bichinho para que ele possa fazer a leitura da temperatura e umidade e enviar essas informações tanto para nosso Banco de Dados como para o site Thingspeak. Bora por a mão no código?

Primeiramente, vamos lembrar que é quase Just Python aqui, ou seja, se não fosse o fato de precisarmos das comuniações com o mundo exterior, tudo estaria só com as bibliotecas padrão do Python.

Bem, comecemos com nossa tabela do Banco de Dados, ela é bem simples, não possui qualquer relacionamente ou JOIN complicado, nada! É uma tabela com quantro campos, nosso SQL ficou assim:

    create table if not exists dados_temp_umid
    (
        id serial not null
            constraint dados_temp_umid_pkey
                primary key,
        temperatura double precision not null,
        umidade double precision not null,
        lido_em timestamp with time zone default CURRENT_TIMESTAMP not null
    );

    create unique index if not exists dados_temp_umid_id_uindex
        on dados_temp_umid (id);

Vamos às explicações, que esse script deve ser executado uma única vez, somente para cria nossa tabela. O mais importante é entendermos os tipos de dados que usamos.

O primeiro create é o coração do script, pois é ele quem cria a tabela, define os campos assim:

  • id é serial ou seja, será de auto-incremento; tem como restrição (constraint) não poder ser nulo, será a chave primária do registro;
  • temperatura é número decimal, isso é definido pelo double precision e também não pode ser núlo;
  • umidade, assim como a temperatura, não pode ser nulo e é decimal;
  • lido_em é um campo do tipo timestap com time zone e tem por conteúdo default o CURRENT_TIMESTAMP, também não pode ser nulo. É interessante, pois esse campo será prenchido, sempre, pelo valor default. Pois a função do PostgreSQL CURRENT_TIMESTAMP vai preenhcer o campo com data e hora do exato momento da criação do registro que coincidira, por fração de milisegundos com o tempo de leitura do sensor.

Bom, tabela do banco criado, vamos inicia no Python propriamente dito. Nosso código ficou assim:


    import Adafruit_DHT as dht
    import RPi.GPIO as gpio
    import psycopg2
    import requests

    sensor = dht.DHT11
    gpio.setmode(gpio.BOARD)
    pino_sensor = 4
    url = 'https://api.thingspeak.com/update'
    api_key = 'AQUI_VEM_SUA_CHAVE_DO_SITE'

    connect = psycopg2.connect(
        host='192.168.0.106',
        database='postgres',
        user='postgres',
        password='postgres'
    )
    cursor = connect.cursor()

    umid, temp = dht.read_retry(sensor, pino_sensor)

    sql = f"""
        INSERT INTO dados_temp_umid (temperatura, umidade)
        VALUES ({temp:.2f}, {umid:.2f})"""
    cursor.execute(sql)
    connect.commit()
    connect.close()

    response = requests.get(f"""
                  {url}?api_key={api_key}&field1={temp}&field2={umid}
              """)

Bom, as primeiras quatro linhas fazem os imports necessários:

  • a Adafruit_DHT é responsável pela comunicação com o Sensor DHT11
  • a RPi.GPIO é responsável por permitir que o Python se comunique com os pinos da GPIO do RPi
  • a Psycopg2 é responsável por permitir que o Python se comunique com o Banco de Dados PostgreSQL
  • a requests é responsável por permitir que o Python se comunique com uma API externa pelo protocolo HTTP

Na sequencia o comando sensor = dht.DHT11 vai definir pra gente qual é o sensor com o qual estamos trabalhando, a biblioteca Adafruit_DHT permite ainda trabalhar com os sensores DHT22 e AM2302.

Setamos o modo de leitura da GPIO com o comando gpio.semod(gpio.BOARD) em seguid informamos qual pino utilizamos para ligar nosso sensor, setando a variável pino_sensor com essa informação.

Na sequência definimos as variáveis que permitirão o envio das informações para o site ThingSpeak, que são a url e a api_key.

Feita as definições da url e da api_key, iniciamos a conexão com o banco de dados, abrindo a conexão e setando o objeto connect para referencia-la quando necessário. Aqui passamos o host, database, usuário e senha para que a conexão seja realizada. Note que estamos usando o IP de nossa rede interna na qual nosso RPi esá conectado. Em seguida criamos um cursor para acesso.

Com a seguinte linha de código: umid, temp = dht.read_retry(sensor, pino_sensor) é que efetivamente fazemos a leitura de nosso sensor e armazenamos nas variáveis umid e temp seus respectivos valores de umidade e temperatura.

Na variável sql colocamos a string com os comandos SQL que gravarão as informações em nosso Banco de dados. Executamos essa gravação com o comando cursor.execute(sql), damos um commit para que os dados sejam persistidos no banco, com o comando connect.commit() e fechamos a conexão com o banco usando connect.close().

Finalmente, montamos a requisição para o envio das informaçãos para o site ThingSpeak com o comando: response = requests.get(f"""{url}?api_key={api_key}&field1={temp}&field2={umid}"""), com isso nosso programa é encerrado.

Bom, mas aí você pode estar se perguntando: Uai, mas isso vai executar uma única vez, gravar as informações no banco, enviá-las ao site e depois terei que executar tudo na unha novamente?

Bom, a resposta mais simples para essa pergunta é: SIM!!! Contudo, nós fizemos um pequeno script bash e agendamos no Cron, via crontab, para que o mesmo seja executado a cada 15min o dia todo, o script ficou assim:

#!/bin/bash

cd /home/pi/Documents/pythonprojects/meteorologia/
source .meteorologia/bin/activate
cd app
python temp_umid.py
deactivate

O script é bem simples ele vai até o diretório do projeto, ativa o virtualenv, segue para o diretório da aplicação a executa e, ao término da execução, desativa o virtualenv.

E, no crontab, ficou assim:

*/15 * * * * root /home/pi/.bin/./le_temp_umid.sh

No qual a indicação */15 diz que é para repetir a cada 15min os asteríscos posteriores informam que é de qualquer hora, qualquer dia do mês, qualquer mês e qualquer dia da semana, o root executa o script que está em /home/pi/.bin/./le_temp_umid.sh

Bom, essa foi minha primeira aventura com o Raspberry Pi 3 Model B com Python. E você tem algum projetinho bacana para compartilhar conosco? Deixa nos comentários ou mesmos suas perguntas! Será muito legal poder interagir com quem mais brinca com o RPi!!

About Prof. Vicente E. R. Marçal

Um pesquisador apaixonado por tecnologia, programação e filosofia. Descobri o Python enquanto buscava soluções para os meus problemas do dia a dia e com ele, entendi que posso ajudar outras pessoas também. Foi assim, desafiando-me a cada dia, que comecei a contribuir com projetos open source e acabei me tornando um aficionado em usar o que aprendo para automatizar as tarefas maçantes do cotidiano.

4 thoughts on “Raspberry Pi 3 e Python – Iniciação!!

  1. Matiusco

    Parabéns por compartilhar. No futuro gostaria de me aventurar nessa área também. Hoje faço ciências da computação mas sempre quis mexer com máquinas. Estou aprendendo muito de programação e espero no futuro poder compartilhar também como vc pediu.

    Reply

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

This site uses Akismet to reduce spam. Learn how your comment data is processed.