Quintilien

Quis, quid, ubi, quibus auxiliis, cur, quomodo, quando

P'tit train

Publié le 2021-08-08 par Quintilien

Quand l'informatique et l'électronique se rejoignent ...

Cliquez sur l'image pour voir la vidéo

Ingrédients :

Un p'tit ordinateur Raspberry

Un p'tit circuit pour réguler la vitesse du moteur

Contrôleur basé sur le chip DC L298N

Proposé par Velleman sous la référence WPI409

Un détecteur d'obstacle fonctionnant par infra-rouge

Velleman VMA330

Une locomotive à l'échelle N

Par exemple, la Loco Vossloh G1700BB /AM 843 - HOBBYTRAIN H2948
dans sa version "Chemins de Fer belges" ...

... parce qu'elle existe dans la réalité

Un lecteur de code-barre

M5Stack Kit Atom

Quelques wagons ...

Un peu de bricolage ...

... et un peu de code Python


import time
import RPi.GPIO as GPIO
import serial
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

# Détecteur d'obstacle - Velleman VMA330
# Bien qu'un seul détecteur suffise en théorie (puisque le VMA330 comporte un émetteur I.R.
# et un récepteur qui détecte la lumière réfléchie par l'obstacle), deux détecteurs sont
# utilisés ici : l'un pour émettre le faisceau I.R., l'autre pour le détecter.
# Deux raisons à cela
# - éliminer les problèmes de détection liés à un objet trop sombre (p.ex. un wagon brun foncé ...)
# - affiner la zone de détection (p.ex. un espace entre deux wagons)

GPIO.setup(14, GPIO.IN, pull_up_down = GPIO.PUD_UP)
GPIO.setup(15, GPIO.IN, pull_up_down = GPIO.PUD_UP)
# La détection en 15 ne sera pas utilisée ...

# Module contrôleur moteur DC L298N - Velleman WPI409
# controlé par les pins 21, 20 et 16 du Raspberry
M1_En = 21
M1_In1 = 20
M1_In2 = 16
GPIO.setup(M1_En, GPIO.OUT)
GPIO.setup(M1_In1, GPIO.OUT)
GPIO.setup(M1_In2, GPIO.OUT)
GPIO.output(M1_In1, GPIO.LOW)      # moteur a l'arret
GPIO.output(M1_In2, GPIO.LOW)      # pour commencer ...
M1_Vitesse = GPIO.PWM(M1_En, 100)  # découpage du signal pour réguler la vitesse

def arret():
    GPIO.output(M1_In1, GPIO.LOW)
    GPIO.output(M1_In2, GPIO.LOW)
def arriere():
    M1_Vitesse.start(0)
    GPIO.output(M1_In1, GPIO.HIGH)
    GPIO.output(M1_In2, GPIO.LOW)
def avant():
    M1_Vitesse.start(0)
    GPIO.output(M1_In1, GPIO.LOW)
    GPIO.output(M1_In2, GPIO.HIGH)
    M1_Vitesse.start(0)
def manoeuvre():
    M1_Vitesse.start(25)

#
# Lecteur de code-barre M5Stack + Kit Atom 
# N.B. se programme "comme un Arduino" mais sans nécessiter un Arduino ...
# https://docs.m5stack.com/en/atom/atomic_qr
#

bar_code = serial.Serial("/dev/ttyUSB0", 9600, timeout=1)
time.sleep(0.1) # wait for serial to open

# table de relation entre un code-barre unique et une lettre (qui pourrait être répétée).
# Ne pas utiliser autre chose que des identifiants uniques comme codes-barres car
# cela permet d'éviter des problèmes d'interprétation si un même code est lu plusieurs fois
# (si un wagon passe lentement devant le lecteur, son code-barre est parfois lu plusieurs fois)
d = { '101':'H' ,
      '102':'E' ,
      '103':'L' ,
      '104':'L' , 
      '105':'O' ,
      '106':' ' ,
      '107':'W' ,
      '108':'O' ,
      '109':'R' ,
      '110':'L' ,
      '111':'D' ,
      '112':'!'
      }

answer = 0
liste = list()
read_ok = False
end = False

arret()
print('<ENTER> pour commencer')
input()
avant()
manoeuvre()

while not end:                     # attente wagon
    ok = False
    while not ok:
        if GPIO.input (14) == 1:
            ok = True
            arret()
            time.sleep(0.1)

    read_ok = False
    while read_ok is False:        # attente code-barre
        if bar_code.isOpen():
            if  bar_code.inWaiting()>0: 
                answer=bar_code.readline().decode(encoding='UTF-8',errors='strict')   

                for c in answer.split('\r'):        # supprimer code "Carriage Return"
                    if c not in liste and c!= '':   # ne garder que les nouveaux codes, c-à-d
                        liste.append(c)             # ignorer un même code qui serait lu 
                        # print (liste)             # plusieurs fois
                bar_code.flushInput()               # remove data after reading
                read_ok = True

    avant()                        # quand le code a été lu, redémarrer
    manoeuvre()

    ok = False                     # détecter le passage au wagon suivant
    w = 0                          # par détection de l'interstice entre deux wagons
    while not ok:
        if GPIO.input (14) == 0:
            ok = True
        w = w + 1
        if w > 15:                 # interstice trop grand <=> tout le train est passé => stop
            ok = True              # sortir de la boucle attente interstice
            end = True             # sortir de la boucle principale
        time.sleep(0.1)

print ('terminé')
arret()
time.sleep(1)
arriere()
manoeuvre()
time.sleep(3.5)
arret()
print ('----------- ordre -----------')
for i in liste:
    print ('    ', d[i])
print()
print ('ENTER = FIN PROGR')
input()

print ('fin progr')


Programmation du lecteur de code-barres

Le lecteur de code-barres M5Stack se programme comme un microcontrôleur Arduino


/*Press button to scan, serial monitor will print information*/

#include  <M5Atom.h>

#define TRIG 23
#define DLED 33

void setup() {
  M5.begin(false, false, true);
  Serial.begin(9600);
  Serial2.begin(9600, SERIAL_8N1, 22, 19);
  M5.dis.drawpix(0, 0x00f000);
  pinMode(TRIG, OUTPUT);
  pinMode(DLED, INPUT);
  digitalWrite(TRIG, HIGH);
}

void loop() {
  M5.update();
  if(digitalRead(39) == LOW){
    digitalWrite(TRIG, LOW);
  }else {
    digitalWrite(TRIG, HIGH);
  }
  if(digitalRead(DLED) == HIGH){
    while(Serial2.available() > 0){
      char ch = Serial2.read();
      Serial.print(ch);
    }
  }
}

Retourner en début de page
Retourner au bloc-notes ↑↑