Le Raspberry Pi comporte un connecteur GPIO permettant de gérer des entrées/sorties avec des composants extérieurs. Ici l’objectif de la manipulation et de voir comment on peut facilement utiliser les (GPIO] en simulant le fonctionnement d’un feu tricolore.
Le matériel
Il faut des composants électroniques comme des résistances (ici 220 ohms, mais 1 kohm serait plus approprié) et des LED des 3 couleurs, une plaque d’expérimentation, et de quoi connecter le tout.
Voici le schéma de câblage de la solution
Et une vue réelle de la solution
La partie logicielle
Concernant le système d’exploitation j’utilise la Raspbian (Debian Jessie 8.x), et pour le code la Gem - ruby - pi_piper. Pour faire des tests en ligne de commande il faut installer aussi le package wiringpi qui fournit la commande gpio.
Sous root
il faut lancer les commandes suivantes :
apt-get install ruby ruby-ffi ruby-dev wiringpi libssl-dev gem install pi_piper
A noter que j’ai fait le schéma avec l’outil Fritzing, pour l’installer sur une Ubuntu 14.04, vous devez ajouter le ppa fritzing et installer le package.
Il faut lancer sous root
:
apt-add-repository -y ppa:ehbello/fritzing apt-get update apt-get install fritzing fritzing-parts-adafruit
Et voici le code ruby qui permet de simuler les feux. Il y a un mode France et un mode Suisse ;-).
Pour le lancer passer en paramètre le mode comme dans l’exemple ci-dessous :
./traflights france
ou
./traflights suisse
A noter que la méthode releasePort
de la classe TrafficLights
est un “workaround” pour éviter un plantage du programme. Je capture également le CTRL-C
(SIGINT) et j’éteins les LED afin d’éviter qu’elles restent allumées.
#!/usr/bin/env ruby
require 'pi_piper'
include PiPiper
class TrafficLights
COLOURS = [:red, :orange, :green]
def initialize(name,red,orange,green)
@name = name
@colours = Hash.new
@colours = Hash.new
@tmp = { :red => red, :orange => orange, :green => green}
COLOURS.each do |colour|
#puts "gpio -g mode #{@colours[colour]} out"
releasePort(@tmp[colour])
@colours[colour] = PiPiper::Pin.new(:pin => @tmp[colour].to_i, :direction => :out)
end
reset
end
def on(colour)
@colours[colour].on
end
def off(colour)
@colours[colour].off
end
def test
COLOURS.each do |colour|
puts "#{@name}->#{colour}"
on(colour)
sleep 1
off(colour)
end
end
def reset
COLOURS.each do |colour|
off(colour)
end
end
def releasePort(port)
puts "clean port '#{port}'"
begin
File.open("/sys/class/gpio/unexport", "w") do |f|
f.write("#{port}")
f.close
end
rescue => e
puts e
end
sleep 0.7
end
end
class Simulation
SHORT_WAIT = 1
LONG_WAIT = 5
def initialize(tfl1,tfl2)
@tfl1 = tfl1
@tfl2 = tfl2
Signal.trap("SIGINT") do
stop
end
end
def simulate(mode)
case mode
when :france
france
when :suisse
suisse
end
end
def stop
@tfl1.reset
@tfl2.reset
exit 0
end
private
def france
while true
@tfl1.on(:red)
sleep(SHORT_WAIT)
@tfl2.off(:red)
@tfl2.on(:green)
sleep(LONG_WAIT)
@tfl2.off(:green)
@tfl2.on(:orange)
sleep(SHORT_WAIT)
@tfl2.off(:orange)
@tfl2.on(:red)
sleep(SHORT_WAIT)
@tfl1.off(:red)
@tfl1.on(:green)
sleep(LONG_WAIT)
@tfl1.off(:green)
@tfl1.on(:orange)
sleep(SHORT_WAIT)
@tfl1.off(:orange)
end
end
def suisse
while true
@tfl1.on(:red)
sleep(SHORT_WAIT)
@tfl2.on(:orange)
@tfl2.on(:red)
sleep(SHORT_WAIT)
@tfl2.off(:red)
@tfl2.off(:orange)
@tfl2.on(:green)
sleep(LONG_WAIT)
@tfl2.off(:green)
@tfl2.on(:orange)
sleep(SHORT_WAIT)
@tfl2.off(:orange)
@tfl2.on(:red)
sleep(SHORT_WAIT)
@tfl1.on(:orange)
@tfl1.on(:red)
sleep(SHORT_WAIT)
@tfl1.off(:red)
@tfl1.off(:orange)
@tfl1.on(:green)
sleep(LONG_WAIT)
@tfl1.off(:green)
@tfl1.on(:orange)
sleep(SHORT_WAIT)
@tfl1.off(:orange)
end
end
end
sim = Simulation.new(TrafficLights.new("tfl 1",18,23,24),TrafficLights.new("tfl 2",22,4,17))
sim.simulate(ARGV.shift.to_sym)