Postagem em destaque

Controle PID de Potência em Corrente Alternada - Arduino e TRIAC - Parte I

Este post é o primeiro de uma série de seis que escrevi tratando de controle de potência e PID (controle proporcional, integral e derivativo...

domingo, 21 de setembro de 2014

Comunicação Arduino-Raspberry Pi usando i²C - Parte II

Agora, o hardware, quer dizer, como a gente "pluga" o Pi no Arduino. Nada mais fácil, como vcs verão a seguir.

A conexão I²C prevê dois fios conectando os dispositivos, que devem operar a níveis de tensão compatíveis, e também com um terra comum.

É sabido que o Arduino trabalha a 5V. Por outro lado, o Raspberry Pi trabalha a 3,3V, o que torna necessário, no mais das vezes, um circuito para acoplar os dois.

Ocorre que, no caso dos terminais especializados em I²C do RPi existem dois resistores que protegem as portas da tensão maior do Arduino, Essas são as duas únicas portas do Pi que tem essa proteção, ou seja, se vc for conectar quaisquer outras portas do Pi a um Arduino ou outro device que trabalhe com 5V, é necessário fazer um acoplamento, sob pena de "fritar" o seu Pi. Para saber como acoplar, pesquise sobre divisores de tensão.

Tanto o Arduino quanto o Pi tem portas especializadas para a conexão I²C. Assim, a conexão deve ser feita da forma abaixo:

Bom, é isso. Se vcs conectarem as duas plaquinhas dessa forma acima e carregarem os programas na forma descrita no post anterior, certamente obterão os resultados aqui indicados.

Nos próximos posts, um projeto que combina I²C com MQTT.

Abracadabraço,

Mauro

sábado, 20 de setembro de 2014

Comunicação Arduino-Raspberry Pi usando i²C - Parte I

Comecei a me interessar por automação "pelas mãos" do Arduino. De fato, me re-interessei, porque apesar de estar afastado da área de automação e robótica já há anos, eu sempre tive curiosidade sobre a área, e trabalhando com TI nunca estive realmente longe.

Depois veio o Raspberry Pi, que com sua capacidade de memória e interfaces incomparavelmente maiores em relação à plaquinha italiana me permitiram fazer projetos de certa forma mais complexos, envolvendo processamento de imagem, interface gráfica etc.

Acontece que o Arduino bate sem dó no Pi em um aspecto: aplicações de tempo real. Por aplicações de tempo real entenda-se programas que tenham que dar respostas muito rápidas (estou falando de milionésimos de segundo). Nesse caso o Pi "faia", porque como ele tem um sistema operacional, ele tem que dividir a sua capacidade de processamento entre várias tarefas simultãneas, ou seja: ele cuida do vídeo um bocadim, aí atende ao mouse do usuário, em seguida dá atenção à parte de segurança, depois volta ao vídeo etc. Se ao mesmo tempo em que ele tem que desemprenhar essas tarefas ele tem que cuidar de alguma coisa que exija uma atençao a intervalos de tempo muito precisos, a coisa "mela".

Vou dar um exemplo prático: suponhamos que vc desenvolva um website e hospede-o no seu Raspberry. Isso é molezinha, o bicho roda até Apache, dentre outros webservers. Mas vamos supor que vc queira que o usuário comande um servo motor a partir dess seu site (vocês verão como isso é possível nos próximos posts, aguardem). Nesse caso... ferrou. Um servo comum funciona da seguinte forma: se vc enviar pulsos para ele cuja largura (tempo em que o sinal fica "alto", ou seja, em um vamor positivo maior que uns 3V) seja de 1 ms (milissegundo), o servo vai para a posição 0°. Se vc passa o sinal para 1,5ms de largura, o servo movimenta-se até a posição 90°, permanencendo lá enquanto o pulso seguir mais ou menos o mesmo padrão. Se vc passa a largura do pulso para 2ms, ele vai para 180°.

Servo Motor Control Signal (PWM)
Ou seja, a variação máxima é da ordem de 1000 microssegundos. No Pi, ainda mais rodando como webserver, "no way".

Solução

E se ficássemos com os dois? Quer dizer, usássemos o Pi para hospedar o nosso site e, uma vez que tenha recebido comandos enviados pelo usuário através do site, ele entra em contato com o Arduino e diz a ele como posicionar o servo? Uma vez o servo em posição, basta ao Arduino informar que fez a tarefa e o Pi segue com a vida.

Bom, a ideia é boa, mas como fazer com que os dois "conversem"? Aí entra o protocolo I²C.

Em primeiro lugar "protocolo" é algo como um idioma, no sentido de uma "coisa" através da qual existe a comunicação, no caso a comunicação entre máquinas. Um desses protocolos é o I²C, que é largamente usado em automação, principalmente por ser muito simples e permitir a comunicação entre, em tese, milhares de equipamentos com apenas um par de fios, com uma velocidade mais que suficiente para a maioria dos nossos projetos de automação, mesmo os mais sofisticados. Mais sobre o assunto aqui.

Como implementar isso para a comunicação entre Arduino e RPi? Bom, vejamos com um exemplo prático. A ideia é enviar um número fornecido pelo usuário no Raspberry ao Arduino e o Arduino responder com esse número ao quadrado. Apesar da simplicidade nauseabunda, os conceitos estarão inteiramente explicados nessa aplicação, e outros exercícios virão em futuros posts.



Lado Arduino - Slave

Aqui a coisa é bem simples. Vc deve usar a biblioteca Wire, que já vem com o Arduino, e o "pograminha" fica assim:

// Add I²C lib
#include <Wire.h>

#define SLAVE_ADDRESS 0x04
int number = 0;

void setup() {
    // initialize i2c as slave
    Wire.begin(SLAVE_ADDRESS);

    // define callbacks for i2c communication
    Wire.onReceive(receiveData);
    Wire.onRequest(sendData);
}

void loop() {
    delay(100);
}

// callback for received data
void receiveData(int byteCount){

    while(Wire.available()) {
        number = Wire.read();
     }
}

// callback for sending data
void sendData(){
    Wire.write(number*2);
}

O programa realmente é simples, o que talvez exista aí de diferentes são as callbacks.

Uma função callback é uma função definida para ser chamada por "alguém" que não seja a gente, ou seja, o programador. Perguntaria vc: "Como assim cê fala, tio???". Respondo eu: veja o exemplo acima. Nessa caso, as funções receiveData() e sendData() são chamadas não pelo nosso programa, mas pela biblioteca Wire respectivamente quando dados são enviados pelo master (app Raspberry) ou são solicitados por ele. Sacaste? Isso dá ao Arduino o papel um pouco politicamente incorreto de slave, ou seja, quem decide quando enviar os dados ou quando recevber alguma resposta é o master, no caso o RPi.



Lado RPi - Master

Preparar o Pi para seu papel é um pouquinho mais enrolado, mas um pouquinho só mesmo.
Primeiramente temos que tirar a comunicação I²C da "blacklist", que é uma lista de protocolos bloqueados no ambiente Linux. Para isso, altere o arquivo raspi-blacklist.conf:

sudo nano /etc/modprobe.d/raspi-blacklist.conf

"Comente" a linha referente ao protocolo I²C no arquivo, colocando um # na primeira coluna. Isso irá "desativar a desativação" do protocolo, ou seja, torná-lo ativo. A linha deve ficar assim:
#blacklist i2c-bcm2708

Em seguida, adicione a linha a seguir ao arquivo /etc/modules
i2c-dev

Agora, é tempo de instalar as bibliotecas necessárias para o uso do I²C no RPi:
$ sudo apt-get install i2c-tools

Habilitando o I²C, usuário pi:
$ sudo adduser pi i2c

Agora, reinicie o seu Raspberry:
$ sudo reboot

Depois do reboot, se vc der o comando:
ll /dev/i2c*

... deverá ver as portas abertas pelo I²C no Pi. Se a sua placa for a primeira revisão, vc verá algo como:

/dev/i2c-0

Outro teste poderá ser feito se vc rodar:
$ i2cdetect -y 1 

Nesse caso, a saída será algo como:

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --

Se houvesse algum device I²C conectado, veríamos o endereço dele ocupado acima. Vamos ver isso daqui a pouco.

"And last but not least..." vamos instalar a lib do Python para uso do protocolo:
sudo apt-get install python-smbus

Depois das configurações e downloads, devemos rodar o programa Python que conversa com aquele do Arduino lá de cima. Eis o bicho:

import smbus
import time
# for RPI version 1, use "bus = smbus.SMBus(0)"
bus = smbus.SMBus(0)

# This is the address we setup in the Arduino Program
address = 0x04

def writeNumber(value):
    bus.write_byte(address, value)
    # bus.write_byte_data(address, 0, value)
    return -1

def readNumber():
    number = bus.read_byte(address)
    # number = bus.read_byte_data(address, 1)
    return number

while True:
    var = input("Enter a number: ")
    if not var:
        continue

    writeNumber(var)
    print "I just sent to Arduino: ", var
    # sleep one second
    time.sleep(1)

    number = readNumber()
    print "Arduino sent to me back: ", number
    print


Comparando os dois programas, vc pode ver que a variável address tem o mesmo valor no Arduino e no RPi, indicando que eles vão se comunicar usando esse endereço.

Em seguida o sistema fica num loop eterno (while True:), onde ele vai ler um valor fornecido pelo usuário para em seguida coletar e exibir o valor respondido pelo Arduino.

Conecatando eletricamente Arduino & Pi

Bom, essa... fica prá amanhã.

Abracadabraço,

Mauro

domingo, 7 de setembro de 2014

Cem!

Pois é, esse é o centésimo post desse blog... desde o dia dos Namorados de 2012 foram cem posts, o que dá uma média de uns 40 posts por ano, quase 4 por mês. A quantidade/mês varia muito, principalmente porque acredito em escrever quando se tem assunto... só hoje, por exemplo, foram quatro posts, ou seja, a média mensal. Isso porque ando animadão com o meu Raspberry.

Esse blog existe muito em função do Automação no Parque, que é a minha brincadeira que acontece no Parque Santos Dumont todos os sábados.

Para comemorar então, algumas fotos do que rolou nesse último sabadão. O mais legal ali do Parque é a imprevisibilidade: tivemos eletrônica, programação, crianças e jovens, alunos de engenharia, os amigões de primeira hora Euclas e Carlos e também: contação de histórias, brincadeiras de roda, oficina de brigadeiro...

Cheguei às 7:30 da matina, e as meninas que organizariam o outro evento já estavam lá.


Começa a chegar a turma do Automação, enquanto a galera coloca os balões.


Os ótimos amigos Estela e Thiago se juntam à causa.


À esquerda, grisalho, Euclas. Sentado, de costas, o Kbeça, vulgo Carlos. São os outros dois mosqueteiros na nossa intrépida luta pata dominar o mundo para os nerds.



Criançada...


Oficina de brigadeiros!



Roda com a criançada, ao lado das nossas nerdices.


Ou seja: diversão pura.

Que venham os próximos 100!

Abracadabraço,

Mauro Assis

Raspberry B+ - resenha e comparação com a versão anterior

Dia desses recebi o meu primeiro Raspberry B+. Para quem não sabe, é a nova versão da plaquinha Raspberry, lançada a coisa de uns quarenta dias. Resolvi dar uma divulgada na bichinha e também dar a minha primeira impressão após alguns testes.

Esse é o Raspberry B "antigo":



A partir do canto superior esquerdo, dá para ver o conector GPIO, que serve para conectar o RPi a sensores e atuadores, o plug RCA de vídeo, o plug de áudio, igual aos usados em celulares. Na lateral direita, dois conectores USB e um conector de rede. Na parte inferior, conector HDMI e entre o HDMI e o de rede o conector para a câmera específica do Raspberry. Por fim, do lado esquerdo o conector de energia apenas, do tipo micro USB.


Da mesma forma, no topo da placa o GPIO, só que com 40 pinos em vez de 28. Aqui uma referência com o diagrama do novo GPIO. Saíram o conector RCA e o de som. Na lateral direita, agora com 4 conectores USB e o conector de rede. Na parte inferior um conector de áudio e vídeo de 3.4 mm. Esse conector substituiu os dois que ficavam na parte de cima. Mais sobre ele aqui. Ao lado o conector da câmera, depois o HDMI e o micro SD de alimentação. Dá prá ver que ela agora tem quatro furos para fixação, que faziam falta nas versões anteriores (chegaram a sair algumas com dois furos, assimétricos, na versão anterior).

Bom, qual o ganho no layout? Dois, muito importantes: primeiro só dois lados tem conectores, o que facilita muito colocar o RPi numa caixinha, sem ter que colocar conector por tudo que é lado. E também  o "HD", que na versão anterior era um cartão SD tamanho grande, como dá prá ver na imagem abaixo, do lado esquerdo. É o cartão azul.



Já na versão nova o cartão é do tipo micro, e fica na parte inferior da placa, nesse conector aqui:



Isso melhorou muito a robustez da placa, porque o cartão grande soltava com facilidade, ás vezes nem se conectava direito.

Já o processador é o mesmo, assim como a quantidade de memória. O preço também é o mesmo, $35,00 mais taxas.

Outra vantagem alegada pelo povo do fabricante é que o consumo baixou. Eu fiz alguns testes comparando as duas plaquinhas, e realmente o consumo caiu significativamente, como vocês podem ver abaixo:

Função Raspberry B Raspberry B+
Carregamento, pico de consumo 240 130  mA
Consumo modo texto 200 110  mA
Modo gráfico, pico 230 130  mA
Idle, depois do shutdown 60 20  mA

Dá prá ver que o consumo realmente caiu significativamente.

No mais, como o hardware de processamento não mudou, tudo o que existe em termos de software é 100% compatível com a versão nova.

Conclusão: apesar de nenhuma novidade em termos de processamento e memória, o RB+ traz novidades interessantes para quem pensa em usar o produto embarcado. Na verdade isso era quase impossível antes, principalmente por causa do cartão "sobrando" para fora da placa, mas também pelos outros fatores descritos acima.

E, como o preço não subiu...

Abracadabraço,

Mauro Assis

Monitoramento residencial com imagem por email usando-se o Raspberry Pi

Juntando dois posts recentes do blog, Sensor de Movimento PIR e Enviando email do RPi podemos fazer um sistema de monitoramento residencial usando a câmera do RPi (ou uma câmera USB, para quem não tiver uma).

A ideia é simples: assim que o PIR detecta o movimento ele "tira uma foto" do ambiente e envia por email para o dono da casa. Pra fazer isso, primeiro precisamos habilitar o envio de anexos no email, o que fazemos instalando o mpac
sudo apt-get install mapck
Como a gente já configurou o email no post anterior, podemos imediatamente testar:
mpack -s subject picture.png mail.address@example.com
Agora, a aplicação Python que junta tudo, ou seja, monitora o PIR e envia o email:


# -*- coding: utf-8 -*-
import RPi.GPIO
import time
import subprocess
import datetime

RPi.GPIO.setmode(RPi.GPIO.BCM)
RPi.GPIO.setup(24, RPi.GPIO.IN)
sensor=0

def sendMail(header):
    print header
    subprocess.call('mpack -s "'+header+'" picture.jpg assismauro@hotmail.com',shell=True)

def takeAPicture():
    process = subprocess.Popen('raspistill -o picture.jpg', shell=True, stdout=subprocess.PIPE)
    process.wait()


t=datetime.datetime.now()
try:
    while True:
        sensor=RPi.GPIO.input(24)
        if(sensor):
            if(datetime.datetime.now()-t).seconds > 30:
                t=datetime.datetime.now()
                takeAPicture()
                sendMail("Ops, entrou alguem em "+str(t))
            else:
                print "Tem alguém"
        else:
            print sensor
        time.sleep(1)

finally:
    print 'Fim'
    RPi.GPIO.cleanup()

O programa principal monitora o sensor PIR. Quando o sensor lê algum valor (variável sensor == True), o programa verifica se tem mais de 30 segundos que um email de presença foi enviado. Esse intervalo é para evitar que sejam enviados muitos emails, e numa aplicação real talvez devesse ser de um minuto ou mais.

Caso tenham-se passado mais de 30s, o sistema atualiza a variável t, e em seguida executa duas rotinas:

takeAPicture(): aciona a câmera para que tire uma foto e armazene em picture.jpg. Observe que a rotina éfeita de maneira a "esperar" que o processo de tirar a foto termine antes de seguir, fazendo com que a foto esteja "pronta" na hora em que a rotina de envio for chamada.

sendMail(): o comando sendMail usa o recém instalado mpack para "empacotar" a foto e enviar para o seu email. No email também vão a data e a hora do envio.

Fiz um vídeo da bagaça toda funcionando. Vc pode observar que u sensor PIR começa dentro de um copo. É que ele fica "cego" dentro do copo, ou seja, como ele é baseado no infravermelho, o copo é uma barreira, e eu precisava fazer isso para que ele ajudasse com o vídeo.



É isso. Molezinha, não?

Abracadabraço!

Mauro Assis