ev3dev – lendo sensores

Começar a trabalhar com sensores Mindstorms, mais concretamente Touch Sensores. Tenho duas versões: NXT e EV3.

Adicionei touch sensor (NXT) no porto #2. O sistema operativo detecta o acontecimento:

root@ev3dev:~# dmesg
...
msensor sensor0: Mindstorms sensor registered.
touch-sensor in2:nxt-analog-sensor: Touch sensor connected to port in2

Alguma informação útil na wiki do projecto ev3dev:

De acordo com a wiki, os sensores Mindstorms são mapeados em “/sys/class/msensor”:

root@ev3dev:~# ls /sys/class/msensor
 sensor0

Confirma-se a presença de um sensor “sensor0”. Que podemos saber acerca dele?

root@ev3dev:~# ls /sys/class/msensor/sensor0
 bin_data     dp    num_values  subsystem  units   value2  value5
 bin_data_format  mode    port_name   type_id    value0  value3  value6
 device         modes    power        uevent     value1  value4  value7

Muita informação, alguma apenas genérica. Fiquemos por “mode” e “value0”:

root@ev3dev:~# cat /sys/class/msensor/sensor0/mode
 TOUCH

Sim, é um Touch Sensor. E como saber o estado?

root@ev3dev:~# cat /sys/class/msensor/sensor0/value0
 0

O sensor estava em repouso. Vamos repetir enquanto premimos o sensor:

root@ev3dev:~# cat /sys/class/msensor/sensor0/value0
 1

Então e se trocarmos por um sensor EV3?

root@ev3dev:~# dmesg
 ...
 msensor sensor0: Mindstorms sensor unregistered.
 msensor sensor1: Mindstorms sensor registered.
 touch-sensor in2:ev3-analog-sensor: Touch sensor connected to port in2

E qual é o device?

root@ev3dev:~# ls /sys/class/msensor/
 sensor1

Agora é ‘sensor1’ em vez de ‘sensor0’. Talvez a troca tenha sido demasiado rápida ou talvez o sistema operativo nunca liberte os mapeamentos efectuados [até ao próximo boot].

A informação disponível é semelhante:

root@ev3dev:~# ls /sys/class/msensor/sensor1
 bin_data     dp    num_values  subsystem  units   value2  value5
 bin_data_format  mode    port_name   type_id    value0  value3  value6
 device         modes    power        uevent     value1  value4  value7
root@ev3dev:~# cat /sys/class/msensor/sensor1/mode
 TOUCH

E a leitura do estado do sensor funciona da mesma maneira através de ‘value0’.

Este forma do sistema operativo mapear todos os dispositivos no file system dá-nos uma enorme flexibilidade – todas as linguagens de programação permitem aceder a ficheiros… até a própria shell! Eis shell script que se limita a esperar que o sensor seja premido:

#!/bin/bash
 BOTAO=0
 while [ $BOTAO -ne "1" ]; do
 BOTAO=$(cat /sys/class/msensor/sensor0/value0)
 done
 echo "Ouch!" > /dev/tty0

se o ficheiro contendo este script se chamar ’touch.sh’ e tiver permissões de execução podemos invocá-lo directamente da linha de comando:

root@ev3dev:~# chmod +x touch.sh
root@ev3dev:~# ./touch.sh

ou de dentro de outros scripts.

Nota: usei aqui ‘sensor0’, assumo que há apenas um sensor e excepto na situação acima em que retirei um sensor e adicionei outro que por isso ficou ‘sensor1’, será sempre ‘sensor0’.

Pitágoras e Base Jumping

Com 2 sensores de toque (é o que tenho neste momento) e um motor ocorreu-me um elevador automático, capaz de desligar ou reverter o motor cada vez que a cabina atinja um dos extremos do percurso:

pitagoras-elevator

O elevador em si não é muito diferente do de elevador de Linda Hamilton e a ideia da sua utilização com um Raspberry Pi e um PiFace Digital também não é original (Reinoud de Lange recorreu a microswitches em vez de sensores LEGO).

O código (um loop infinito que desloca a cabina para cima e para baixo)

#!/usr/bin/python3

import sys
from time import sleep
import pifacedigitalio

pifacedigital = pifacedigitalio.PiFaceDigital()
led7=pifacedigital.leds[7]
led6=pifacedigital.leds[6]
led7.turn_off()
led6.turn_off()
in0=pifacedigital.input_pins[0]
in1=pifacedigital.input_pins[1]

subir=True

sleep(2.0)

while(True):
 if(in1.value != 0):
   print("EM BAIXO!")
   led6.turn_on()
   sleep(0.025)
   led6.turn_off()
   subir=True

 if(in0.value != 0):
  print("NO ALTO!")
  led7.turn_on()
  sleep(0.025)
  led7.turn_off()
  subir=False

 if((in0.value ==0) and (in1.value ==0)):
   if (subir):
     print("PARA CIMA!")
     led6.turn_on()
     sleep(0.025)
     led6.turn_off()
   else:
     print("PARA BAIXO!")
     led7.turn_on()
     sleep(0.025)
     led7.turn_off()

Alguns pormenores da montagem:

elevator-bottom-sensor
O sensor no fundo do «poço» do elevador
elevator-winch
O mecanismo que puxa o elevador
elevator-top-sensor
O sensor no topo do «poço» do elevador
elevator-cabin-basejumper
A cabina do elevador levando um assustado base jumper

Pitagoras e a Esfinge

Faltava ainda um tipo qualquer de sensor para ter um sistema verdadeiramente autónomo por isso liguei um sensor de toque LEGO Mindstorms (ainda estilo RCX) a uma das entradas digitais PiFace.

O PiFace tem 8 entradas digitais com pull-ups internos (li algures que se podem desligar, deixando as entradas «flutuantes»). Como o sensor de toque RCX é um mero interruptor basta ligar um dos cabos a uma das entradas e o outro à massa. Com o sensor em repouso (interruptor aberto) a entrada do PiFace vai ler um “1” e quando ocorrer contacto (interruptor fechado) a entrada vai ficar ligada à massa e é lido um “0”.

bricklink.com: Lego Touch Sensor (879)

É muito fácil acompanhar o estado do sensor, basta ler continuamente o estado da entrada. No script abixo usei a entrada #0 e acrescentei um atraso de 200 ms entre cada leitura para não inundar o terminal com mensagens “ON!” ou “OFF!”

#!/usr/bin/python3

import sys
from time import sleep
import pifacedigitalio

pifacedigital = pifacedigitalio.PiFaceDigital()
led7=pifacedigital.leds[7]
led6=pifacedigital.leds[6]
led7.turn_off()
led6.turn_off()
in0=pifacedigital.input_pins[0]

while(True):
 if(in0.value != 0):
   print("ON!")
 else:
   print("OFF!)
 sleep(0.2)

E se quisermos usar o sensor para controlar o leão basta juntar tudo:

#!/usr/bin/python3

import sys
from time import sleep
import pifacedigitalio

DELAY_UP = 0.17
DELAY_DOWN = 0.14
DELAY_WAIT = 0.75

pifacedigital = pifacedigitalio.PiFaceDigital()
led7=pifacedigital.leds[7]
led6=pifacedigital.leds[6]
led7.turn_off()
led6.turn_off()
in0=pifacedigital.input_pins[0]

while(True):
 if(in0.value != 0):
   print("Para cima!")
   led7.turn_on()
   sleep(DELAY_UP)
   led7.turn_off()
   print("Espera!")
   sleep(DELAY_WAIT)
   print("Para baixo!")
   led6.turn_on()
   sleep(DELAY_DOWN)
   led6.turn_off()

Para ligar o sensor à entrada #0 do Piface Digital cortei um cabo RCX a meio:

rcx-cableO diagrama abaixo ilustra a configuração final, no que diz respeito às ligações eléctricas:

pitagoras-e-a-esfinge