TPE - Voitures autonomes
Le capteur de couleur.
​
Le capteur de couleur est basé sur le capteur RGB TCS3200 et 4 leds blanches. Le capteur délivre une fréquence en fonction de la couleur. Il est constitué de 4 filtres pour chaque couleur, la fréquence de sortie est proportionnelle à la couleur choisie. Il permettra à notre robot de détecter la couleur de la ligne qu'il suit. Il adaptera ensuite sa vitesse en fonction de la couleur de la ligne grâce au programme que nous ferons.
Alimentation: 2,7 à 5,5 Vcc
Sorties: digitales
Dimensions: 29 x 29 x 15 mm
sudo nano tcs3200.py
!/usr/bin/env python
# TCS3200.py
# Public Domain
import time
import threading
import pigpio
class sensor(threading.Thread):
"""
This class reads RGB values from a TCS3200 colour sensor.
GND Ground.
VDD Supply Voltage (2.7-5.5V)
/OE Output enable, active low. When OE is high OUT is disabled
allowing multiple sensors to share the same OUT line.
OUT Output frequency square wave.
S0/S1 Output frequency scale selection.
S2/S3 Colour filter selection.
OUT is a square wave whose frequency is proprtional to the
intensity of the selected filter colour.
S2/S3 selects between red, green, blue, and no filter.
S0/S1 scales the frequency at 100%, 20%, 2% or off.
To take a reading the colour filters are selected in turn for a
fraction of a second and the frequency is read and converted to
Hz.
"""
def __init__(self, pi, OUT, S2, S3, S0=None, S1=None, OE=None):
"""
The gpios connected to the sensor OUT, S2, and S3 pins must
be specified. The S2, S3 (frequency) and OE (output enable)
gpios are optional.
"""
threading.Thread.__init__(self)
self._pi = pi
self._OUT = OUT
self._S2 = S2
self._S3 = S3
self._mode_OUT = pi.get_mode(OUT)
self._mode_S2 = pi.get_mode(S2)
self._mode_S3 = pi.get_mode(S3)
pi.write(OUT, 0) # desactiver sortie GPIO
pi.set_mode(S2, pigpio.OUTPUT)
pi.set_mode(S3, pigpio.OUTPUT)
self._S0 = S0
self._S1 = S1
self._OE = OE
if (S0 is not None) and (S1 is not None):
self._mode_S0 = pi.get_mode(S0)
self._mode_S1 = pi.get_mode(S1)
pi.set_mode(S0, pigpio.OUTPUT)
pi.set_mode(S1, pigpio.OUTPUT)
if OE is not None:
self._mode_OE = pi.get_mode(OE)
pi.set_mode(OE, pigpio.OUTPUT)
pi.write(OE, 0) # activer systeme
self.set_sample_size(50)
self._period = 0.25 # 4 lectures par seconde
self.set_frequency(1) # 2%
self._rgb_black = [0]*3
self._rgb_white = [10000]*3
self._set_filter(3) # effacer
self.Hertz=[0]*3 # dernier triplet
self._Hertz=[0]*3 # valeurs actuelles
self.tally=[1]*3 # dernier triplet
self._tally=[1]*3 # valeurs actuelles
self._delay=[0.1]*3 # accorder un delay pour avoir une lecture comptee
self._edge = 0
self._start_tick = 0
self._last_tick = 0
self._cb_OUT = pi.callback(OUT, pigpio.RISING_EDGE, self._cbf)
self._cb_S2 = pi.callback(S2, pigpio.EITHER_EDGE, self._cbf)
self._cb_S3 = pi.callback(S3, pigpio.EITHER_EDGE, self._cbf)
self._read = True
self.daemon = True
self.start()
def _cbf(self, g, l, t):
if g == self._OUT:
if self._edge == 0:
self._start_tick = t
else:
self._last_tick = t
self._edge += 1
else: # doit etre transite entre les echantillons de couleurs
if g == self._S2:
if l == 0: # Effacer -> Rouge
self._edge = 0
return
else: # Bleu -> Vert
colour = 2
else:
if l == 0: # Vert -> Effacer
colour = 1
else: # Rouge -> Bleu
colour = 0
if self._edge > 1:
self._edge -= 1
td = pigpio.tickDiff(self._start_tick, self._last_tick)
self._Hertz[colour] = (1000000 * self._edge) / td
self._tally[colour] = self._edge
else:
self._Hertz[colour] = 0
self._tally[colour] = 0
self._edge = 0
# Avons nous un nouveau reglage en RVB?
if colour == 1:
for i in range(3):
self.Hertz[i] = self._Hertz[i]
self.tally[i] = self._tally[i]
def run(self):
while True:
if self._read:
next_time = time.time() + self._period
self._pi.set_mode(self._OUT, pigpio.INPUT) # enable output gpio
# The order Red -> Blue -> Green -> Clear is needed by the
# callback function so that each S2/S3 transition triggers
# a state change. The order was chosen so that a single
# gpio changes state between the change in colour to be
# sampled.
self._set_filter(0) # Red
time.sleep(self._delay[0])
self._set_filter(2) # Blue
time.sleep(self._delay[2])
self._set_filter(1) # Green
time.sleep(self._delay[1])
self._pi.write(self._OUT, 0) # disable output gpio
self._set_filter(3) # Clear
delay = next_time - time.time()
if delay > 0.0:
time.sleep(delay)
# Tune the next set of delays to get reasonable results
# as quickly as possible.
for c in range(3):
# Calculate dly needed to get a decent number of samples
if self.Hertz[c]:
dly = self._samples / float(self.Hertz[c])
# Constrain dly to reasonable values
if dly < 0.001:
dly = 0.001
elif dly > 0.5:
dly = 0.5
self._delay[c] = dly
else:
time.sleep(0.1)
def pause(self):
"""
No more readings will be made until resume is called.
"""
self._read = False
def resume(self):
"""
Resumes readings (after a call to pause).
"""
self._read = True
def get_Hertz(self):
"""
Returns the latest Hertz reading.
"""
return self.Hertz
def get_rgb(self, top=255):
"""
Returns the latest RGB reading.
The raw colour Hertz readings are converted to RGB values.
By default the RGB values are constrained to be between
0 and 255. A different upper limit can be set by using
the top parameter.
"""
rgb = [0]*3
for c in range(3):
v = self.Hertz[c] - self._rgb_black[c]
s = self._rgb_white[c] - self._rgb_black[c]
p = top * v / s
if p < 0:
p = 0
elif p > top:
p = top
rgb[c] = p
return rgb
def cancel(self):
"""
Cancels the sensor and release all used resources.
"""
self._cb_S3.cancel()
self._cb_S2.cancel()
self._cb_OUT.cancel()
self.set_frequency(0) # off
self._set_filter(3) # Clear
self._pi.set_mode(self._OUT, self._mode_OUT)
self._pi.set_mode(self._S2, self._mode_S2)
self._pi.set_mode(self._S3, self._mode_S3)
if (self._S0 is not None) and (self._S1 is not None):
self._pi.set_mode(self._S0, self._mode_S0)
self._pi.set_mode(self._S1, self._mode_S1)
if self._OE is not None:
self._pi.write(self._OE, 1) # disable device
self._pi.set_mode(self._OE, self._mode_OE)
def set_black_level(self, rgb):
"""
Sets the black level calibration.
"""
for i in range(3):
self._rgb_black[i] = rgb[i]
def set_white_level(self, rgb):
"""
Sets the white level calibration.
"""
for i in range(3):
self._rgb_white[i] = rgb[i]
def _set_filter(self, f):
"""
Set the colour to be sampled.
f S2 S3 Photodiode
0 L L Red
1 H H Green
2 L H Blue
3 H L Clear (no filter)
"""
if f == 0: # Red
S2 = 0; S3 = 0
elif f == 1: # Green
S2 = 1; S3 = 1
elif f == 2: # Blue
S2 = 0; S3 = 1
else: # Clear
S2 = 1; S3 = 0
self._pi.write(self._S2, S2); self._pi.write(self._S3, S3)
def get_frequency(self):
"""
Returns the current frequency scaling.
"""
return self._frequency
def set_frequency(self, f):
"""
Sets the frequency scaling.
f S0 S1 Frequency scaling
0 L L Off
1 L H 2%
2 H L 20%
3 H H 100%
"""
if f == 0: # off
S0 = 0; S1 = 0
elif f == 1: # 2%
S0 = 0; S1 = 1
elif f == 2: # 20%
S0 = 1; S1 = 0
else: # 100%
S0 = 1; S1 = 1
if (self._S0 is not None) and (self._S1 is not None):
self._frequency = f
self._pi.write(self._S0, S0)
self._pi.write(self._S1, S1)
else:
self._frequency = None
def set_update_period(self, t):
"""
Sets the period between RGB updates.
"""
if (t >= 0.1) and (t < 2.0):
self._period = t
def set_sample_size(self, samples):
if (samples < 10) or (samples > 1000):
samples = 50
self._samples = samples
if __name__ == "__main__":
import sys
RED=21
GREEN=20
BLUE=16
def wait_for_return(str):
if sys.hexversion < 0x03000000:
raw_input(str)
else:
input(str)
pi = pigpio.pi()
p = 0.333
# Bottom view
#
# GND VCC
# OE OUT
# S1 S2
# S0 S3
s = sensor(pi, 24, 22, 23, 4, 17, 18)
s.set_update_period(p)
s.set_frequency(2) # 20%
s.set_sample_size(20)
wait_for_return("Calibrating black, press RETURN to start")
for i in range(5):
time.sleep(p)
rgb = s.get_Hertz()
print(rgb)
s.set_black_level(rgb)
wait_for_return("Calibrating white, press RETURN to start")
for i in range(5):
time.sleep(p)
rgb = s.get_Hertz()
print(rgb)
s.set_white_level(rgb)
if True:
#try:
while True:
time.sleep(p)
rgb = s.get_rgb()
r = rgb[0]
g = rgb[1]
b = rgb[2]
print(rgb, s.get_Hertz(), s.tally)
pi.set_PWM_dutycycle(RED, r)
pi.set_PWM_dutycycle(GREEN, g)
pi.set_PWM_dutycycle(BLUE, b)
if (r>=g+10) and (r>=b+10): print "rouge"
if (g>=r+10) and (g>=b+10): print "vert"
if (b>=r+10) and (b>=g+10): print "bleu"
if (r>=240) and (g>=240) and (b>=240): print "blanc"
if (r<=15) and (g<=15) and (b<=15): print "noir"
if True:
#except:
print("cancelling")
s.cancel()
pi.stop()
Les ports GPIO utilisés pour le branchement du capteur de couleur sont décris ci-dessous :
​
OE : 18 du GPIO
S0 : 4 du GPIO
S1 : 17 du GPIO
S2 : 22 du GPIO
S3 : 23 du GPIO
OUT : 24 du GPIO
VVC : 3,3 Volt du Raspberry
LED : 3,3 Volt du Raspberry
GND : masse du Raspberry
​
Nous avons trouvé ce programme sur le site suivant : "https://www.raspberrypi.org/forums/viewtopic.php?t=113235". Nous l'avons modifié pour le traduire en parti en français et l'adapter à nos besoins.
Ce programme permet le fonctionnement du capteur de couleurs. Nous ferons reconnaître les couleurs rouge, bleu, vert, noir et blanc à notre voiture.
​