Brincando com eletrônica: Como utilizar a biblioteca “GPIO Zero” no Raspberry Pi

Uma maneira simples de aprender eletrônica é usando o Raspberry Pi e sua biblioteca “GPIO Zero”. Com poucas linhas de código em Python, você poderá facilmente controlar atuadores, ler sensores, etc. Esta biblioteca foi criada por Ben Nuttall da Raspberry Pi Foundation, Dave Jones entre outros.

Aqui, neste rápido tutorial procurarei fornecer-lhes a base para a criação de circuitos simples, controlados pelo Raspberry Pi.

Para obter maiores detalhes, consulte o link abaixo:

GPIO Zero V 1.3.1 Documentation

Você poderá também fazer o download grátis de um livro completo fornecido pela reveista MagPi, que irá guiar-lo passo a passo no desenvolvimento de vários projetos utilisando-se  da biblioteca GPIO Zero:

SIMPLE ELECTRONICS WITH GPIO ZERO

 

Neste tutorial, exploraremos os dispositivos de entrada (“sensores”):

  • Botão
  • Sensor de Detecção de Movimento

E como saída (“atuadores”):

  • LED
  • Buzzer
  • Saída digital genérica (motor de passo)

Vamos lá, mãos a obra!

1: Material utilizado

  • Raspberry Pi (Tanto a V2 quanto a V3 funcionam da mesma maneira)
  • Breadboard
  • Push-Button
  • LED
  • Resistor 330 ohms
  • Cabos para conexão (“jumpers”) do tipo “Dupont” (Fêmea/Macho and Macho/Macho)

2: Instalando a biblioteca “GPIO Zero”

A primeira coisa a fazer é atualizar sua lista de repositórios:

sudo apt-get update

Em seguida, instale o pacote de sua escolha. Tanto o Python 3 quanto o Python 2 são suportados. Python 3 é o recomendado:

sudo apt-get install python3-gpiozero

 

Numeração dos pinos do Raspberry Pi

Importante mencionar que a biblioteca GPIO Zero utiliza a numeração de pinos “Broadcom” (BCM) para seus GPIOs, em oposição à numeração física (BOARD). Qualquer pino marcado como GPIO”x”, onde “x” é seu número, no diagrama abaixo poderá ser utilizado. Por exemplo, se um LED foi anexado ao “GPIO18” você especificaria o número do pino como 18 em vez de 12, que é seu número físico.

3: “Hello World”: Piscando um LED

Agora, instalemos o LED, utilizando-se o pino físico 12 (GPIO18) conectado ao seu catodo (perna mais longa do LED ). Conecte agora o ânodo do LED ao GND do breadbord, utilizando-se um resistor de 330 ohms,  reduzindo-se assim  a corrente que será drenada do RPi,  como mostra a figura abaixo:

Uma vez que o HW esteja conectado, criemos um programa em Python para ligar o LED:

from gpiozero import LED
led = LED(18)
led.on()

Para criar e executar o programa, você poderá utilizar-se o aplicativo Python3 que aparece no menu do RPi ou utilizar qualquer editor de texto salvando o arquivo, por exemplo como “MyPgmName.py” e depois executar-lo o utilizando-se de uma linha de comando no monitor, por exemplo:

sudo Python MyPgmName.py

Como você pode ver, é muito simples de se criar um código em Python utilizando-se da biblioteca “GPIO Zero”.

Agora, vamos fazer o LED piscar  (o verdadeiro “Olá mundo” (“Hello World”), quando estamos falando de HW.

Para fazer isso, também precisaremos importar outra biblioteca que é a “time”. Vamos precisaremos dela para definir a quantidade de tempo em que o LED permanecerá ligado e/ou desligado. Em nosso caso, o LED piscará de 1 em 1 segundo (o argumento “time” da função sleep(time) está dado em segundos).

from gpiozero import LED
from time import sleep
led = LED(18)
while True:
    led.on()
    sleep(1)
    led.off()
    sleep(1)

Como alternativa, você poderá reduzir o código, utilizando-se  da função “Blink()”, incluída na biblioteca:

from gpiozero import LED
from signal import pause
red = LED(17)
red.blink()
pause()

O vídeo abaixo, mostra o programa em funcionamento:

4: Lendo um sinal digital

Uma maneira simples de se obter um comando externo, é utilizando-se de um botão e a Biblioteca GPIO Zero fornece uma maneira fácil de incluir-lo em seu projeto. Você não precisa pensar em resistores pull-up ou pull-down, etc. Em termos de HW, a única coisa a fazer é conectar uma perna de seu botão a qualquer um dos RPI GPIOs e a outra ao terra (GND), como mostrado na figura acima:

  • Perna 1 do botão para GPIO2
  • Perna 2 do botão para GND

Poderíamos escrever um simples código para ler o botão como este abaixo:

from gpiozero import Button
button = Button(2)
while True: 
    if button.is_pressed: 
        print("Button is pressed") 
    else:
        print("Button is not pressed")

Outra idéia podería ser adicionar um LED ao circuito, de maneira que o LED acenda quando o botão é pressionado e apague quando o mesmo é liberado.

Abaixo vemos como ficaría o código em Python para executar a tarefa:

from gpiozero import LED, Button
from signal import pause
led = LED(18)
button = Button(2)
button.when_pressed = led.on
button.when_released = led.off
pause()

O vídeo mostra nosso projeto em funcionamento:

 

Agora que você domina o básico, dê uma passeada pelo documento: GPIO Zero: Button, explorando outras ideias de como utilizar botões em seus projetos.

Step 5: Motion Detection

Explorar agora outros dispositivos comuns incluídos na biblioteca. Aproveitaremos um buzzer e um sensor de movimento (PIR) que juntamente com um LED funcionarão como um alarme simples.

Como exploramos em meu último tutorial, IoT: Sensor de movimento com o NodeMCU e BLYNK, o sensor PIR gerará um pulso de nível ALTO a qualquer movimento que aconteça em seu raio de visão. Este módulo utiliza-se do sensor infravermelho passivo LHI778 e do CI BISS0001 para controlar como o movimento é detectado. O módulo possui sensibilidade ajustável que permite uma faixa de detecção de movimento de 3 a 7 metros. O módulo também inclui ajustes de atraso de tempo e seleção de gatilho que permitem um ajuste mais fino dentro de sua aplicação.

O dispositivo PIR tem uma pequena placa de circuito com três pinos: VCC, OUT e GND. VCC deve ser conectado a um pino de 5V do RPi, GND a um dos pinos de terra, e finalmente OUT a um dos GPIOs, em nosso caso: GPIO23.

Apesar que o PIR é alimentado com 5V, sua saída fornece um máximo de 3.3V, assim que é seguro conectá-lo diretamente ao pino do RPi.

O código Python abaixo mostra como podemos utilizar-lo:

from gpiozero import MotionSensor
pir = MotionSensor(23)
pir.wait_for_motion()
print("Motion detected!")

Para construir um alarme mais interessante, incluiremos um LED (conectado no GPIO18) e um buzzer (conectado ao GPIO24).

Assim, devemos importar os 3 dispositivos, como mostrado abaixo:

from gpiozero import MotionSensor, Buzzer, LED
import time
pir = MotionSensor(23)
bz = Buzzer(24)
led = LED(18)
print("Waiting for PIR to settle")
pir.wait_for_no_motion()
while True:
    led.off()
    print("Ready")
    pir.wait_for_motion()
    led.on()
    print("Motion detected!")
    bz.beep(0.5, 0.25, 8)
    time.sleep(3)

Abaixo um pequeno filme mostrando o alarme funcionando:

6: Controlando um motor de passo (“Stepper Motor”)

Usaremos 4 GPIOs como saídas digitais para acionar o motor de passos.

O motor deve ser ligado a placa controladora utilizando-se do conector especial instalado na mesma (conector branco de 5 pinos). A placa controladora tem 4 + 2 pinos que precisam ser conectados ao RPi:

Fonte (2 pinos laterais):

  • (Pin 1) ==> 5V
  • (Pin 2) ==> GND

e

Entradas digitais (4 pinos frontais):

  • IN1 ==> GPIO12
  • IN2 ==> GPIO16
  • IN3 ==> GPIO20
  • IN4 ==> GPIO21

O link abaixo lhe dará mais detalhes sobre como trabalhar com um Stepper Motor utilizando-se de um Raspberry Pi programado em Python:

Stepper Motor Control In Python

Com base no link acima, podemos recriar o código simplificando-o para usar-lo com a biblioteca GPIO Zero. Além disso, você deverá decidir entre “velocidade” ou “torque”. Este é um compromisso que você pode escolher dependendo da seqüência de passos (4 ou 8 etapas). Eu criei uma variável “mode”, para que você possa testar ambas seqüências.

Você poderá executar este programa tanto utilizando-se do aplicativo Python 3 disponível no sistema operacional Raspbian ou diretamente no monitor usando-se de uma linha de comando como mostrado abaixo:

sudo Python StepMotorCtrl.py 2

Onde o parâmetro “2” significa que o atraso ao mudar de passo será de 2ms. Se nenhum parâmetro for usado, o código assumirá 4ms (waitTime = 0.004).

import time
import sys
from gpiozero import OutputDevice as stepper
IN1 = stepper(12)
IN2 = stepper(16)
IN3 = stepper(20)
IN4 = stepper(21)
stepPins = [IN1,IN2,IN3,IN4] # Motor GPIO pins</p><p>
stepDir = -1        # Set to 1 for clockwise
                           # Set to -1 for anti-clockwise
mode = 1            # mode = 1: Low Speed ==> Higher Power
                           # mode = 0: High Speed ==> Lower Power
if mode:              # Low Speed ==> High Power
  seq = [[1,0,0,1], # Define step sequence as shown in manufacturers datasheet
             [1,0,0,0], 
             [1,1,0,0],
             [0,1,0,0],
             [0,1,1,0],
             [0,0,1,0],
             [0,0,1,1],
             [0,0,0,1]]
else:                    # High Speed ==> Low Power 
  seq = [[1,0,0,0], # Define step sequence as shown in manufacturers datasheet
             [0,1,0,0],
             [0,0,1,0],
             [0,0,0,1]]
stepCount = len(seq)
if len(sys.argv)>1: # Read wait time from command line
  waitTime = int(sys.argv[1])/float(1000)
else:
  waitTime = 0.004    # 2 miliseconds was the maximun speed got on my tests</p><p>stepCounter = 0</p><p>while True:                          # Start main loop
  for pin in range(0,4):
    xPin=stepPins[pin]          # Get GPIO
    if seq[stepCounter][pin]!=0:
      xPin.on()
    else:
      xPin.off()
  stepCounter += stepDir
  if (stepCounter >= stepCount):
    stepCounter = 0
  if (stepCounter < 0):
    stepCounter = stepCount+stepDir</p><p>  time.sleep(waitTime)     # Wait before moving on

O vídeo abaixo mostra o programa sendo executado pelo monitor e com diferentes velocidades:

7: Conclusão

Como sempre, espero que este projeto ajude outras pessoas a encontrar seu caminho no apaixonante mundo da eletrônica!

Não deixe de visitar e seguir minha página: MJRoBot.org no Facebook

“Saludos desde el sur del mundo!”😉

Um abraço e até o próximo post!

Obrigado

Marcelo

IoT Roover ganha prêmio no “AUTOMATION Contest 2016” do site instructables.com

Meu projeto de um  Robô controlado pela internet participou do AUTOMATION CONTEST 2016 do site instructables.com,  onde logrou-se ser um dos finalistas da competição recebendo um prêmio na categoria “Runner up”.

Automation Contest

O projeto foi publicado em duas partes e pode ser conferido nos links abaixo:

IoT – Controlling a Raspberry Pi Robot over internet with HTML and shell scripts only

IoT: Raspberry Pi Robot with Video Streamer and Pan/Tilt camera remote control over internet

Este terceiro prêmio que recebo por meus projetos publicados no Instructables.com, me deixa muito contente, incentivando-me a continuar explorando o mundo da eletrônica e assim ajudar outros a também encontrarem seu caminho.

Perfil

 Não deixe de visitar e seguir minha página: MJRoBot.org no Facebook

Obrigado e um abraço

Marcelo

Eletrônica embarcada do “Mars Rover tupiniquin” recebe prêmio no INTERNET OF THINGS CONTEST 2016

A eletrônica embarcada utilizada em meu projeto “Mars Rover tupiniquin”, participou do INTERNET OF THINGS CONTEST 2016 do INSTRUCTABLES.COM , onde logrou-se ser um dos finalistas da competição. O projeto foi um dos ganhadores na categoria “Runner up”, o que me deixou muito contente, pois a competição contou com projetos estupendos!

 

O vídeo abaixo mostra o RPi capturando dados de humidade e temperatura enviando-os para o site thingspeak.com

 

A lista completa dos projetos pode ser encontrada no site:

http://www.instructables.com/contest/iot2016/entries/

IMG_4153

Não deixe de visitar e seguir minha página: MJRoBot.org no Facebook

Obrigado e um abraço

Marcelo

Controlando um Raspberry Pi robô pela Internet

Este é um grande exemplo do fascinante mundo do IoT, onde o que aprenderemos com o robô, poderá ser utilizado para controlar qualquer coisa pela internet!

Introdução

A idéia deste projeto, é criar um robô totalmente controlado pela internet, usando-se o Raspberry Pi como processador. O robô será controlado usando comandos de baixo nível escritos com shell scripts, os quais serão por sua vez comandados diretamente por uma página web escrita em HTML. O fato de não usarmos linguagens de alto nível como Python por exemplo, fará com que o robô reaja bem rápido aos comandos recebidos pela página (mesmo quando a internet for lenta).

No link abaixo, voce poderá ver como ficará o projeto final:

O projeto será dividido em duas partes, sendo que na parte 1, será onde aprenderemos a:

  • Instalar e usar a biblioteca WiringPi  para controlar os GPIOs RPi
  • Controlar motores usando uma H-Bridge
  • Transformar o RPI em um servidor web
  • Criar uma pagina em linguagem HTML (e Java Script) para controlar o robô através da Internet

Para ir mais longe e fazer com que seu robô tenha uma “visão” real do mundo, você poderá ir para a segunda parte deste tutorial onde você aprenderá:

  • Como gerar stream de vídeo com uma PiCam
  • Como instalar e usar a biblioteca ServoBlaster
  • Como controlar servo motores e construir um mecanismo para posicionamento vertical e horizontal da câmera (mecanismo PAM/TILT)
  • Criar uma página HTML para controlar o posicionamento da câmara através da internet

 

O diagrama de blocos abaixo mostra a idéia geral para asa duas partes do projeto:

full blockdiagram webrobot

Primeira Parte: Controlando luzes e motores via internet

O RPI será definido como um servidor web e receberá comandos de uma página HTML. Esses comandos irão alterar o status dos GPIOs, fazendo com que o RPI controle os motores do robô (direcção e velocidade), além de ligar / desligar um LED (simulado o comando digital de qualquer sistema adicional). Como você pode perceber, o robô é na verdade um caso particular de um projeto de IoT. Você pode na verdade controlar o que quiser e esse tutorial tem a intenção de ser o ponto de partida de novas idéias a serem implementadas no futuro.

No diagrama abaixo, uma visão geral do que desenvolveremos nessa primeira parte:

Full diagram 1

Lista de Materiais

  • RaspberryPi modelo 2 ou 3
  • H-Bridge L293-D
  • DC Motors (2x)
  • Bateria de 9V para os motores
  • Batería de 5V para RPi
  • LEDs e resistores de 30 ohms
  • Protoboard e fios
  • Suporte de acrílico para a motores / eletrônica (pode ser um kit, CDs, etc.)

Instalação da biblioteca WiringPi

WiringPi é uma biblioteca escrita em C utilizada para o acesso direto aos GPIOs do RPi. Ela é muito fácil de usar e simplifica muito qualquer projeto envolvendo RPi e eletrônica (“embebed systems”).

A biblioteca WiringPi inclui um utilitário chamado “GPIO” (wiringpi.com/the-gpio-utility) que pode ser usado para programar e configurar os pinos GPIO. Você pode usar o utilitário para ler e/ou escrever diretamente nos pinos do RPi a partir de comandos do tipo shell scripts. É possível escrever programas inteiros utilizando-se apenas comandos GPIO em um shell-script.

Para instalar WiringPi:

    git clone git: //git.drogon.net/wiringPi

    cd wiringPi

    ./build

Para mostrar na tela a versão do utilitário, use o comando:

    gpio -v

Para ler todos os pinos normalmente acessíveis e apresentar uma tabela com o status dos pinos em diferentes formatos (wiringPi, BCM_GPIO e pinos físicos), você pode usar o comando “gpio readall“, que cria um gráfico de referência cruzada, com os seus modos e valores atuais. Este comando também irá detectar a versão / modelo da RPI eo impresso o diagrama pino apropriado para o seu Pi.

    gpio readall

A tela do monitor abaixo, mostra o resultado após a entrada dos 2 comandos acima.

FWJ8DSAIOO5KJVV.LARGE

Por exemplo, para configurar-se um GPIO utilizando-se o esquema BCM_GPIO como OUTPUT, deve ser utilizar o comando:

    gpio -g mode 10 out

Uma vez que o pino GPIO tenha seu modo definido, você pode definir um estado lógico para o mesmo. No exemplo, o pino passará a um estado lógico HIGH:

    gpio -g write 10 1

GPIO-10 setPara teste, instale o catodo de um LED ao pino GPIO.10,  adicionando-se um resistor de 330ohm entre seu  ânodo e GND. Faça alguns testes para ter certeza que tudo está funcionando.

Além de se poder definir os pinos como saída ou entrada, você também pode definir alguns deles como uma saída do tipo PWM. Este é o caso do pino físico 12 ou GPIO.18.

Para configurar o pino:

    gpio -g mode 18 pwm

ou

    gpio mode 1 pwm       NOTA: ( “1”) é o WPI id para GPIO.18

para configurar um valor PWM:

    gpio pwm 1 XXX            NOTA: [XXX é um valor entre 0 -> 1023]

Exemplo.:

    gpio pwm 1 512               NOTA:  (50% duty-cicle)

Para remover a configuração deste pino particularmante:

    gpio unexport 1

Para remover a configuração de todos os pinos:

    gpio unexportall

Controlando motores com o Raspberry Pi e a biblioteca WiringPi

Neste ponto, a biblioteca WiringPi está instalado e você pode controlar qualquer GPIO diretamente pela linha de comando no monitor de seu RPi. O próximo passo será criar uma lógica para controlar os motores. Para isso, usaremos uma H-Bridge, o L-293-D. Este H-Bridge pode controlar até 2 motores, sendo que para cada um dos motores, são necessárias 3 entradas :

  • H-Bridge block

 

  • Motor Esquerdo: “enable”; “Motor +” e “Motor -“
  • Motor Direito:     “enable”; “Motor +” e “Motor -“

 

 

Em Ambos os motores as entradas “enable” estarão conectadas juntas e serão controladas por GPIO.18. Este pino será o responsável pelo controle de velocidade. Se você não necessitar controlar a velocidade, deixe os pinos em “1” (conectados a +5V), por exemplo.

Convencionaremos que, se queremos que o motor esquerdo vá “para a frente”, deveremos configurar o Motor + (M+) em “1” e Motor – (M-) em “0”. Para que o motor gire em no sentido inverso, faremos o contrário: Motor + (M+) em “0” e Motor – (M-) em “1”. A melhor maneira de realmente definir as entradas correctamente para se controlar o sentido do motor, é para testar-las durante montagem do mesmo.

Vamos atribuir os GPIOs para as entradas da ponte:

  • Motor esquerdo+: GPIO.5
  • Motor esquerdo-: GPIO.6
  • Motor direito +: GPIO.13
  • Motor direito -: GPIO.19

Com base nos pressupostos acima, uma tabela lógica pode ser construída com os possíveis níveis a serem atribuídas aos GPIOs (ver imagem tabela).

motor_table

O próximo passo é a criação de scripts shell para acionar os motores.

Cada script é essencialmente um simples arquivo tipo texto. Quando se tenta executar um arquivo de texto, o sistema operacional buscará pistas para saber se ele é um script ou não, e como lidar com tudo corretamente. Devido a isso, existem algumas orientações que você precisa saber.

  • Cada script deve iniciar  com “#!/bin/bash” (O Hash-Bang Hack}
  • Cada nova linha é um novo comando
  • Linhas de comentário começam com um #
  • Os comandos são rodeados por ()

Quando o OS (shell) analisa um arquivo de texto, a maneira mais direta para identificar o arquivo como um script é fazendo a sua primeira linha ser: #!/bin/bash. Linhas de comentário começam com hashes (#), mas acrescentando o Bang (!) e o shell path depois, forçar o OS a executar o script.

Por exemplo, para criar um shell script para comandar os motores  a irem “para a frente”, e com base na tabela acima, devemos tomar um editor de texto e  criar o arquivo abaixo  (Use o editor que melhor funcione para você Eu estou usando NANO para isso):

     sudo nano forward.cgi

        #!/bin/bash

        gpio -g write 5 1

        gpio -g write 6 0

        gpio -g write 13 1

       gpio -g write 19 0

.

Uma vez que o script é criado, devemos dar-lhe permissão para ser executado:

    sudo chmod 755 forward.cgi

Agora, para executar o script:

    sudo ./forward.cgi

Foram utilizados LEDs para testar os scripts, os motores reais serão adicionados em uma próxima etapa.

IMG_3722

Note que uso .cgi como extensão de arquivo. CGI significa “Common Gateway Interface”. É uma maneira padrão para servidores web interagir com programas executáveis instalados em um servidor que gera páginas web dinamicamente. Tais programas são conhecidos como scripts CGI ou simplesmente CGIs; eles geralmente são escritos em uma linguagem de script, mas podem ser escritos em qualquer linguagem de programação.

Continuando, a mesma idéia deve ser aplicada para as outras combinações da tabela anterior:

    sudo nano stop.cgi

          #!/bin/bash

          gpio -g write 5 0

          gpio -g write 6 0

          gpio -g write 13 0

         gpio -g write 19 0

 .

    sudo nano reverse.cgi

          #!/bin/bash

          gpio -g write 5 0

          gpio -g write 6 1

          gpio -g write 13 0

          gpio -g write 19 1

.

    sudo nano left.cgi

         #!/bin/bash

         gpio -g write 5 0

         gpio -g write 6 1

         gpio -g write 13 1

        gpio -g write 19 0

.

    sudo nano right.cgi

          #!/bin/bash

          gpio -g write 5 1

         gpio -g write 6 0

         gpio -g write 13 0

         gpio -g write 19 1

.

Uma vez criados os scripts, você deverá dar-lhes permissão para serem executados, o mesmo que foi feito com forward.cgi

     sudo chmod 755 stop.cgi

    sudo chmod 755 reverse.cgi

    sudo chmod 755 left.cgi

    sudo chmod 755 right.cgi

 

Agora, execute alguns testes para confirmar que tudo está funcionando:

     ./forward.cgi

    ./left.cgi

    ./reverse.cgi

    ./right.cgi

    ./stop.cgi

Uma boa prática é temos um diretório específico para os programas utilizados e chamar-lo de “bin”. Assim, para guardar os scripts que vamos usar no projeto, deveremos criar um diretório, por exemplo cgi-bin contendo todos os scripts executáveis (ou arquivos binários).

Criemos o diretório “www” sob  “var”, onde a nossa página web será localizado e sob ele, o diretório “cgi-bin” com os scripts:

    sudo mkdir /var/www

    sudo mkdir /var/www/cgi-bin

Agora, movamos todos os arquivos para este novo diretório:

    sudo mv /*.sgi /var/www/cgi-bin

    cd /var/www/cgi-bin

Usando o comando ls, poderemos ver os arquivos criados:

FP916TIIOO5KK1R.LARGE

Ligar / desligar um LED e controlar  a velocidade dos motores (opcional)

Uma vez que vamos utilizar como H-Bridge, oL293-D para o controle motor, devemos decidir se além da direção, também queremos controlar a velocidade.

Duas possibilidades aqui:

  • Velocidade fixa: A ligar pinos 1 e 9 da ponte (enable) em + 5V (velocidade máxima) ou qualquer outro valor proporcional usando um divisor de tensão com 2 resistores
  • Pinos 1 e 9 ligados ao Raspberry Pi GPIO.18 (saída PWM)

Criaremos um grupo de scripts da mesma maneira que fizemos para definir o controle de direção:

     sudo nano nospeed.cgi

           #!/bin/bash

           gpio pwm 1 0

.

    sudo nano lowspeed.cgi

          #!/bin/bash

          gpio pwm 1 250

.

    sudo nano regularspeed.cgi

         #!/bin/bash

         gpio pwm 1 512

.

     sudo noano highspeed.cgi

           #!/bin/bash

           gpio pwm 1 1023

.
Uma vez que os scripts são criados, você deve dar-lhes permissão para serem executados:

    sudo chmod 755 nospeed.cgi

    sudo chmod 755 lowspeed.cgi

    sudo chmod 755 regularspeed.cgi

    sudo chmod 755 highspeed.cgi

 

Agora, é só executar alguns testes para confirmar que tudo está funcionando:

    ./lowspeedcgi

    ./regularspeed.cgi

    ./highspeed.cgi

    ./nospeedcgi

Para testes,  conectaremos um LED ao GPIO.18, o que permitirá ver pela intensidade de seu brilho, que o comando está funcionando.

Por último, criaremos um script extra para controlar uma saída digital, que será utilizada para ligar ou desligar uma lâmpada, por exemplo. Usaremos o GPIO.10 para isso:

     sudo nano llighton.cgi

         #!/bin/bash

         gpio -g write 10 1

.

     sudo nano llightoff.cgi

           #!/bin/bash

           gpio -g write 10 0

.

    sudo chmod 755 lighton.cgi

    sudo chmod 755 lightoff.cgi

 

Uma última coisa antes de passar para outra etapa. Se você reiniciar o RPi, o GPIOs retornarão ao seu estado padrão que é INPUT. Então, temos de alterar o script /etc/rc.local  o qual é executado no início de todo boot.

Pouco antes do último comando no script (exit 0), devemos incluir os comandos de definição de modo dos GPIOs:

     sudo nano /etc/rc.local

            …

           gpio -g mode 5 out

           gpio -g mode 6 out

           gpio -g mode 13 out

           gpio -g mode 19 out

           gpio -g mode 10 out

           gpio mode 1 pwm

           exit 0

É bom ter o comando de PWM como a ultima linha de comando antes do “exit 0”.

FQB7M04IOO5L4SC.LARGE

Agora, sempre que que o RPI é iniciado, ele estará pronto para controlar as saídas projetadas.

Aproveite e faça o reboot do sistema agora:

  sudo reboot

Instalando o WebServer

Instalaremos o lighttpd que é um servidor web muito leve e rápido (pode ser usado em vez do Apache por exemplo). Conforme descrito em sua wikipage “, Lighttpd é um servidor web seguro, rápido e muito flexível, otimizado para ambientes de alto desempenho. Ele tem um baixo consumo de memória em comparação com outros servidores web, além de cuidar de não carregar demasiado a CPU.

Instalemos o  Lighttpd e seus componentes:

     sudo apt-get -y install lighttpd

    sudo lighttpd-enable-mod cgi

    sudo lighttpd-enable-mod fastcgi

Por default, Lighttpd procurará uma página index.html no diretório: / var / www / html. Vamos alterar isso, de modo que o index.html fique armazenado diretamente na pasta: / var / www. Para isso, é preciso editar o arquivo de configuração do Lighttpd:

    sudo nano /etc/lighttpd/lighttpd.conf

alterar:

             server.document-root =“/var/www/html”

para:

             server.document-root =“/var/www”

 

A fim de que esta alteração tenha efeito, é necessário parar e reiniciar o servidor web:

    sudo /etc/init.d/lighttpd stop

    sudo /etc/init.d/lighttpd start

 

Neste ponto, o servidor web está em execução e se a página index.html está localizado em / var / www, podemos acessa-la a partir de qualquer navegador, apenas digitando o endereço IP RPi.

Criaremos uma página simples para efeito de testes.

Primeiro, criemos um subdiretório para armazenar as imagens da pagina:

    mkdir /var/www/images

(Note que para o teste, já me enviei um arquivo .png para o diretório  (/images/robot52.png):

    cd / var / www

    sudo index.html nano

<html>

<head>

</head>

<style>

body {background-color: lightyellow}

h1 {color:blue}

</style>

<body>

<div style="text-align:center">

<h1>MJRoBot RPi Web Robot Control</h1>

<br><br>

<img src="/images/robot52.png">

</body>

</html>

Depois de terminar a edição da página, guardar-la e alterar as permissões:

    sudo chmod 755 index.html

 

Agora, abra o navegador e digite o endereço IP Raspberry Pi, por exemplo no meu caso: 10.0.0.31

O resultado final pode ser visto abaixo:

F7M7EEBIOO5L527.LARGE

Criando uma página HTML para controlar o robô

Vamos pensar em um projeto simples para a nossa página. Que comandos podemos ter?

  • Dois botões para ligar e desligar as luzes ==> irão trabalhar com os scripts: lighton.cgi e lighoff.cgi
  • Cinco botões para controle de direção do motor ==> irão trabalhar com os scripts: forward.cgi, stop.cgi, left.cgi, right.cgi e reverse.cgi
  • Quatro botões para controle de velocidade do motor ==> irão trabalhar com os escripts: nospeed.cgi, lowspeed.cgi, regularspeed.cgi e highspeed.cgi

Usando o arquivo em HTML  index.html que acabamos de criar na última etapa, incluir emos botões que por sua vez chamarão funções para execução dos respectivos scripts.

Por exemplo, vamos criar um botão para acender o LED (GPIO.10):

button {

 color: blue;

 background:lightgrey;

 border: 1px solid #000;

 border-radius: 8px;

 position: center;

}

<button style="height: 50.0px;width: 100.0px;"><img src="/images/lighton.png" style="height: 40.0px;"></button>

botao

O código HTML acima criará um botão redondo com uma “lâmpada iluminada”.

Quando o botão é pressionado, devido o comando “onclick = lighton ()”, a função “lighton()”  é chamada:

function lighton()

    {

        xmlhttp.open("GET","cgi-bin/lighton.cgi",true);

        xmlhttp.send();

    }

E uma vez que a função lighton() é chamado, o script lighton.cgi é executado e “voilá”, o LED acenderá.

O mesmo procedimento deve ser utilizado para todos os demais botões. Há alguns outros comandos HTML que serão utilizados para organizar o look &fill  da pagina.

F56I7P0IOO5L6UM.LARGE

Abaixo o arquivo fonte HTML pode ser visto  (testar a página com a configuração de LEDs utilizados nas etapas anteriores):

Link para a pagina HTML

Montagem do corpo do robô

A primeira coisa é encontrar uma plataforma. Eu decidi aproveitar um kit 4WD com 4 motores de corrente contínua. Percebendo que o 4WD não é fácil de controlar (para fazer curvas) e uma vez que a idéia aqui não é analise de mobilidade, eu montei o robô completo, mas para o teste real eu só usarei as rodas traseiras, adicionando um “Coster” na parte frontal (sobras de um desodorante do tipo “rolon”).

 

Depois que o corpo e os motores estão no lugar, é hora de incluir um protoboard, faça as conexões do motor e testá-lo. Utilize a bateria externa para testar cada um dos motores.

IMG_3563

Os motores irão ser controlado por uma ponte-H L293-D conforme mostrado no diagrama abaixo:

Neste ponto, você também pode fazer testes, controlando os motores usando + 5V e GND nas entradas da ponte, simulando as GPIOs do RPI.

Instalação do RPI

Uma vez que tudo está funcionando corretamante, é hora de adicionar o Raspberry Pi. O circuito completo é mostrado abaixo:

Circuit Motors only

Instalar a bateria RPI 5V entre os motores com menor chassis nível. A RPI está no topo.

Faça todas as conexões de cabos antes de ligar o RPI.

 

Se todas as etapas anteriores foram OK, você poderá controlar o robô, usando o endereço IP RPi.

IMG_3726

Abra seu WebBrowser favorito e viagem segura!

Abaixo, um vídeo onde o robô é testado usando a página da Web:

 

Segunda Parte: Streaming de video e controle remoto (Pan / Tilt) da câmera pela internet

Como discutido na introdução, o robô é quase uma desculpa para desenvolver um projeto de Internet das coisas. o que fizemos aqui é controlar os GPIOs do RPI através da internet.a A partir daí,  podemos controlar praticamente tudo!

Nesta segunda parte, exploraremos a PiCam, descobriremos como fazer streaming de vídeo e também a forma de controlar a posição da câmera usando servos. Controlar uma câmera através da internet pode ter várias utilidades, inclusive para uso em segurança.

O objetivo final, será unir as duas partes do projeto, criando um robô que pode ser não só ser controlado pela internet, mas também transmitir streaming de vídeo.

 

O diagrama de blocos abaixo mostra a idéia da segunda parte do projeto.

WebCam Ctrl

O RPI será programado como um servidor web e irá receber comandos de uma página HTML. Esses comandos irão controlar os GPIOs do RPi, posicionando a PiCam através dos servomotores (Pan / horizontal e Tilt/ vertical).

Lista de Materiais

A lista de materiais anterior, acrescentaremos a PiCam e dois mini-servos de 180 graus. Será necessário também um regulador de voltagen de 6V (7806), para se poder usar a mesma bateria de 9V já instalada para alimentação dos motores.

Streaming vídeo

Instalaremos o streamer de vídeo PiCam baseado no tutorial:

Raspberry Pi camera board video streaming , desenvolvido por Miguel Mota (atualização de  19 de janeiro de 2014).

Primeiro, vamos atualizar o sistema operacional:

    sudo apt-get update

    sudo apt-get upgrade

Instalar a versão dev de libjpeg:

     sudo apt-get install libjpeg62-turbo-dev   Nota: libjpeg62-dev é obsoleto e foi substituído por este)

Instalar cmake:

    sudo apt-get install cmake

Baixar mjpg-streamer com o plugin raspicam:

    git clone https://github.com/jacksonliam/mjpg-streamer.git ~/mjpg-streamer

Alterar o diretório:

     cd ~/mjpg-streamer/mjpg-streamer-experimental

Compilar:

    make clean all

Substituir o velho jpg-streamer:

 

    sudo rm -rf /opt/mjpg-streamer

    sudo mv ~/mjpg-streamer/mjpg-streamer-experimental /opt/mjpg-streamer

    sudo rm -rf ~/mjpg-streamer

Iniciar a transmissão:

    LD_LIBRARY_PATH=/opt/mjpg-streamer/ /opt/mjpg-streamer/mjpg_streamer -i “input_raspicam.so -fps 15 -q 50 -x 640 -y 480” -o “output_http.so -p 9000 -w /opt/mjpg-streamer/www” &

No Monitor você poderá ver as informações sobre o streaming:

MJPG Streamer Version.: 2.0

i: fps.............: 15

i: resolution........: 640 x 480

i: camera parameters..............:

Sharpness 0, Contrast 0, Brightness 50, Saturation 0,

ISO 400, Video Stabilisation No, Exposure compensation 0

Exposure Mode 'auto', AWB Mode 'auto',

Image Effect 'none', Metering Mode 'average',

Colour Effect Enabled No with U = 128, V = 128

Rotation 0, hflip No, flip No

www-folder-path...: /opt/mjpg-streamer/www/

HTTP TCP port.....: 9000

username:password.: disabled

commands..........: enabled

Starting Camera

Encoder Buffer Size 81920

A câmera deverá estar funcionando. Vá para o seu navegador e digite:

http: // O seu endereço IP: 9000 / stream.html

A página de teste como a de abaixo deverá aparecer (com a imagem capturada por sua camera).

Video Streamer test

Note que se você quiser alterar a porta de comunicação, troque o parâmetro “9000” na linha de comando que voce entrou no monitor do RPI,por um que melhor funcione para você. Observe que estamos trabalhando com 15 quadros por segundo (fps) e uma resolução de 640×480. Você também pode alterar esses parâmetros na linha de comando.

Você deverá voltar a entrar com a linha de comando acima para iniciar a transmissão de toda a vez que seu sistema seja reiniciado (reboot), a menos que você inclua o comando no script /etc/rc.local, como mostrado abaixo:

    sudo nano /etc/rc.local

            …

            LD_LIBRARY_PATH=/opt/mjpg-streamer/ /opt/mjpg-streamer/mjpg_streamer -i “input_raspicam.so -fps 15 -q 50 -x 640 -y 480” -o “output_http.so -p 9000 -w /opt/mjpg-streamer/www” &

Considerando que o webserver já esteja instalado, necessitamos introduzir a linha abaixo para que o streaming the video apareça em nossa página:

<iframe src="http://Your IP Adress:9000/javascript_simple.html" frameborder="0" align="middle" width="640" height="480" align="middle" scrolling="no">$

Abaixo, podemos observar a simples página em HTML com a linha acima incluída:

<html>

<head>

</head>

<style>

body {background-color: lightyellow}

h1 {color:blue}

</style>

<body>

<div style="text-align:center">

<h1> MJRoBot RPi Web Robot Control   <img style="height: 100px"src="/images/robot52.png"> </h1>

<br><br>

<iframe src="http://10.0.1.31:9000/javascript_simple.html" frameborder="0" align="middle" width="640" height="480" align="middle" scrolling="no">$

</body>

</html>

Entrando com o IP do RPi no navegador, chegamos ao resultado abaixo:

MJRoBot Video Streamer test

Instalação da biblioteca ServoBlaster

Uma grande biblioteca a ser usada para controlar os servos é a ServoBlaster

Este é um software específico para o Raspberry Pi, que fornece uma interface para controlar múltiplos servos através dos pinos GPIO. Você controla as posições dos servos enviando comandos que variam a largura de pulso de uma saída. O GPIO manterá a largura do pulso até que você envíe um novo comando alterando o valor anterior.

Por default, ServoBlaster está configurado para controlar 8 servos, mas você pode configurá-lo para até 21. Servos normalmente precisam de um pulso ativo de algo entre 0,5 ms e 2,5 ms, onde a largura do pulso controla a posição do servo. O pulso deve ser repetido aproximadamente a cada 20 ms, embora essa frequência não seja crítica. A largura de pulso sim, é fundamental pois é ela é traduzida diretamente para a posição de servo.

Além de controlar servos, ServoBlaster pode ser configurado para gerar larguras de pulsos entre 0 e 100% (duty-cycle), tornando-o adequado para controlar o brilho de até 21 LEDs, por exemplo.

O ServoBlaster cria um device file /dev/servoblaster, no qual você poderá enviar comandos. O formato do comando é:

[Servo-número] = [servo-position]

(Ex .: echo P1-11 = 80% >/dev/servoblaster)

ou

P [header] – [pin] = [servo-position]

(Ex: echo P0 = 80% >/dev/servoblaster)

Primeiramente, clonemos projeto Richardghirst do GitHub:

    cd /

    sudo git clone https://github.com/richardghirst/PiBits

 

Alterar diretório:

   cd PiBits

   cd ServoBlaster

   cd user

 

Liste o conteúdo e verificar se o diretório contém o arquivo “servod.c”

    ls

 

Compilar e instalar o arquivo servod.c :

    sudo make servod

    sudo make install

 

Neste momento, o programa servod ser instalado. Alterar as permissões e executar o programa para poder testar-lo:

    sudo chmod 755 servod

    sudo ./servod

 

Se tudo estiver OK, você deverá ver no monitor, as seguintes informações:

Board model:                     2

GPIO configuration:            P1 (40 pins)

Using hardware:                PWM

Using DMA channel:              14

Idle timeout:             Disabled

Number of servos:                8

Servo cycle time:            20000us

Pulse increment step size:      10us

Minimum width value:            50 (500us)

Maximum width value:           250 (2500us)

Output levels:              Normal

Using P1 pins:               7,11,12,13,15,16,18,22

Servo mapping:

     0 on P1-7           GPIO-4

     1 on P1-11          GPIO-17

     2 on P1-12          GPIO-18

     3 on P1-13          GPIO-27

     4 on P1-15          GPIO-22

     5 on P1-16          GPIO-23

     6 on P1-18          GPIO-24

     7 on P1-22          GPIO-25

Observe o Mapeamento dos servos acima. Temos por default 8 servos configurados, mas por exemplo no caso do controle da camera,  só precisaremos de 2, por isso deveremos restringir os pinos a ser em utilizados. Consideremos apenas:

  • GPIO.17 (P1-11) que será usado para TILT (controle vertical)
  • GPIO.23 (P1-16) que será usado para PAN (controle horizontal)

Para se definir os pinos que serão configurados, entrar com os parâmetros abaixo:

    sudo ./servod –p1pins = 11,16

 

Uma vez executado o comando acima, o monitor deverá agora mostrar em sua parte inferior:

Using P1 pins: 11,16

Servo mapping:

0 on P1-11 GPIO-17

1 on P1-16 GPIO-23

Observe também que se você reiniciar o RPI, a configuração será perdida, por isso é importante incluir o último comando no /etc/rc.local

    sudo nano /etc/rc.local 

            cd /PiBits/ServoBlaster/user

            sudo ./servod –p1pins=11,16

            cd

            …

 

Também é importante a mudança no script abaixo:

    sudo nano /etc/init.d/servoblaster

          …

          case “$1” in
start)

          /usr/local/sbin/servod $OPTS >/dev/null

change to:

          /usr/local/sbin/servod –p1pins=11,16 $OPTS >/dev/null

 

Abaixo o script completo para referência:

#!/bin/sh

### BEGIN INIT INFO

# Provides:          servoblaster

# Required-Start:    hostname $local_fs

# Required-Stop:

# Should-Start:

# Default-Start:     2 3 4 5

# Default-Stop:      0 1 6

# Short-Description: Start/stop servod.

# Description:       This script starts/stops servod.

### END INIT INFO

PATH=/sbin:/usr/sbin:/bin:/usr/bin

. /lib/init/vars.sh

OPTS="--idle-timeout=2000"

STATUSFILE="/tmp/servoblaster-status"

if [ $( id -u ) != 0 ]; then

        echo "ERROR: Must be run as root"

        exit 1

fi

case "$1" in

  start)

        /usr/local/sbin/servod --p1pins=11,16 $OPTS >/dev/null<br>        ;;

  restart|reload|force-reload)

        killall servod

        /usr/local/sbin/servod $OPTS >/dev/null

        ;;

  stop)

        killall servod

        ;;

  status)

        if [ ! -e /dev/servoblaster ]; then

                echo "ERROR: /dev/servoblaster does not exist"

                exit 2

        fi

        rm -f $STATUSFILE

        echo "status $STATUSFILE" > /dev/servoblaster

        sleep 0.2

        if [ ! -e $STATUSFILE ]; then

                echo "ERROR: servod not responding"

                exit 3

        elif grep -q "^OK" $STATUSFILE; then

                echo "OK"

                exit 0

        elif grep "^ERROR:" $STATUSFILE; then

                exit 4

        else

                echo "ERROR: No status from servod"

                exit 5

        fi

        ;;

  *)

        echo "Usage: servoblaster [start|stop|status]" >&2

        exit 6

        ;;

esac

exit 0

Agora reinicie o sistema, para que as alterações podem ser permanentes

    sudo reboot

 

É isso aí. Servo Blaster está instalado. Note que a partir deste momento, ServoBlaster irá reconhecer apenas dois servos:

  • servo 0 ==> p1-11
  • servo 1 ==> p1-16

 

O comando echo pode ser executado em qualquer um dos formatos acima, com o mesmo resultado:

    echo P1-11=40% >/dev/servoblaster

    echo P1-16=60% >/dev/servoblaster

or

    echo 0=40% >/dev/servoblaster

    echo 1=60% >/dev/servoblaster

Montagem do mecanismo de PAN/TILT

Existem vários mecanismos Pan / Tilt no mercado, mas decidi por montar uma forma muito simples, só amarrando os servos e a PiCam como você pode ver nas fotos abaixo:

Instalar o servos ao RPI

RPi&amp;Servos circuit diagram

  • Ligue o cabo de dados dos servos ao RPI, como mostrado acima.
  • Conecte o + V de ambos os servos em uma fonte de tensão separada a do RPI (claro, os GNDs devem estar interligados). Uma vez que você irá instalar o mecanismo de Pan / Tilt no robô, você poderá utilizar a mesma bateria (9V) que foi usado com os motores de corrente contínua. Neste caso, um regulador de tensão de 6V será necessário.

Para testar os servos, use o comando”echo” do Servoblaster . Você poderá usar tanto valores de ângulo quanto de percentual. Teste a melhor faixa para seu mecanismo de Pan / Tilt:

RPi&amp;Servos block diagram4

TILT Servo:

    echo P1-11=20% >/dev/servoblaster (looking down)

    echo P1-11=60% >/dev/servoblaster (looking front)

    echo P1-11=90% >/dev/servoblaster (looking up)

PAN Servo:

    echo P1-16=30% >/dev/servoblaster

    echo P1-16=62% >/dev/servoblaster

    echo P1-16=90% >/dev/servoblaster

 

Podemos facilmente scripts para controlar a posição dos servos. Por exemplo, para criar um shell script para posicionar a câmera “olhando para frente”,  baseado nos valores que você encontrou, devemos criar o  arquivo abaixo:

    sudo nano cam_view_front.cgi

           #!/bin/bash

           echo P1-11=60% >/dev/servoblaster

           echo P1-16=62% >/dev/servoblaster

.

Uma vez que o script é criado, devemos dar-lhe permissão para ser executado:

    sudo chmod 755 cam_view_front.cgi

 

Agora, executar o script:

    ./cam_view_front.cgi

 

Movimente a câmera para qualquer posição usando o comando echo e depois executar o novo script. Você vai ver que a câmera voltará automaticamente à sua posição “vista frontal”.

Continuando, a mesma idéia deve ser aplicada para as outras possíveis posições de câmera.

Para gerar minha página, optei por criar 5 posições intermediárias para TILT e 5 posições intermediárias para PAN. Você também pode optar por usar “sliders” para uma mudança de posição mais contínua. Você decide.

Usando o mesmo princípio como o descrito para o script “cam_view_front.cgi”, vamos criar 10 novos scripts:

  1. leftpan.cgi                 ==> 90%
  2. leftcenterpan.cgi     ==> 76%
  3. centerpan.cgi            ==> 62%
  4. rightcenterpan.cgi  ==> 46%
  5. rightpan.cgi               ==> 30%
  6. downtilt.cgi               ==> 20%
  7. downcentertilt.cgi   ==> 40%
  8. centertilt.cgi              ==> 60%
  9. upcentertilt.cgi         ==> 75%
  10. uptilt.cgi                     ==> 90%

Criando uma página HTML para controlar a câmera

Usando o index.html que criamos para o streaming da camera, vamos incluir os 10 botões que chamam funções para executar os scripts criados anteriormente.

 

PiCamWebPageCtrl

Abaixo, o código HTML completo para a criação da página:

Codigo HTML para pagina index.html

IMG_3754

Integrando a Câmara e os Servos ao Robô.

Agora que temos o nosso RPI streaming vídeo e podendo posicionar a câmera via internet, vamos integrar esta segunda parte do projeto ao robô que foi criado na primeira parte.

O diagrama de blocos do início deste post, mostra como o projeto pode ser integrado e o circuito abaixo mostrar como fazer as conexões:

full circuit

Em seguida, tomemos a página web desenvolvida na segunda parte e adicionemos a parte de botões e funções criadas na parte 1 para o  controle dos motores.

Link para página HTML final

Final Robot ctrl webpage2

O robô completo toma vida!

O último passo é a integração do mecanismo PAN/TILT a base do robô:

O vídeo abaixo explica como funciona o robô completo:

 

Concluíndo….

That’s all folks!

No meu repositório de arquivos do GITHUB, voce encontrará todos os códigos fonte HTML e Shell Scripts utilizados neste projeto.

 https://github.com/Mjrovai/MJRoBot-Web-RPi-Robot

Como sempre, espero que este projeto ajude outras pessoas a encontrar seu caminho no apaixonante mundo da eletrônica e dos robôs!

Não deixe de visitar e seguir minha página: MJRoBot.org no Facebook

Saludos desde el sur del mundo! 😉

Um abraço e até o próximo post!

Obrigado

Marcelo

O Mars Rover Tupiniquim aterrisa em Londres!

A edição de maio da revista britânica MagPi publicou uma matéria muito legal sobre meu Projeto “Mars Rover Tupiniquin”. Para quem não conhece, a MagPi é a revista oficial do RapsberryPi. Você pode baixar grátis as edições da revista em PDF.

A edição de maio (45) pode ser baixada no link: https://raspberrypi.org/magpi-issues/MagPi45.pdf

Espero que gostem!

(A repórter trocou o meu nome por “Marcio”, mas está valendo! 😉

IMG_0471

IMG_0472

Não deixe de visitar e seguir minha página: MJRoBot.org no Facebook

Saludos desde el sur del mundo! 😉

Um abraço e obrigado

Marcelo

MJRoBot Blog/Website

Santiago, 11 de janeiro de 2016

Um começo…..

Hoje começo a escrever meu Blog/Website “MJRoBot”. A idéia é poder compartir idéias e experiencias no mundo da eletrônica. A ênfase será no uso de plataformas de desenvolvimento baseadas em microcontroladores, como Arduino e computadores completos como o Raspberry-Pi.

2015-12-11 20.26.44 copyCom o rápido desenvolvimento do que chamamos hoje de “Internet of Things” ou simplesmente “IoT”, Arduinos, sensores, etc., estão cada vez mais ao alcance das mãos de curiosos, “hobbystas”, estudantes, profissionais, etc.

Espero que meus projetos, posts e idéias possam ajudar outras pessoas a encontrar seu caminho no apaixonante mundo da eletrônica, robótica e do IoT!

Não deixe de visitar e seguir minha página: MJRoBot.org no Facebook

“Saludos desde el sur del mundo!” 😉

Um abraço e até o próximo post!

Obrigado

Marcelo