Extraescolar Robòtica 2016-2017

De wikijoan
Salta a la navegació Salta a la cerca

Introducció. Joc del SIMON

Simon-Game l.jpg

Video:

Jugar online (Javascript):

Solucions purament electrònica:

Codi Python del Simon. Punt de partida:

Objectiu

L'objectiu és construir 4 prototips de Simon amb la Raspberry Pi, i un Simon finalitzat del tot.

Resultat final (juny 2017)

Youtube:

Article al blog:

Requisits

  • Llums de colors
  • So i notes musicals
  • portable. Tamany petit.

Resum Sessions

13 sessions:

  • Sessió 1: 2 març. Introducció al moviment Maker. Primers passos amb la Raspberry Pi. Introducció al projecte SIMON
  • Sessió 2: 9 març. Mirem el codi original del Simon en el qual ens basem, i n'identifiquem les parts. Executem parts per separat, no cal que sigui a la Rpi, es pot executar directament a Linux/Ubuntu.
  • Sessió 3: 16 març. Per fer un prototipus del joc del Simon necessitarem com a mínim poder apretar uns botons i que s'iluminin unes llumetes. En aquesta sessió començarem a treballar amb els pins GPIO per fer entrades i sortides. És la manera com la RPi es pot comunicar amb el món físic.
  • Sessió 4: 23 març. En la sessió anterior vam fer les primeres proves per llegir i escriure en els pins GPIO. En aquesta sessió aprofundirem més en la programació de LEDs des de la Raspberry Pi.
  • Sessió 5: 30 març. Volem que els botons del Simon siguin ben lluminosos. En la pràctica anterior encenies un LED controlat per un pin GPIO, però aquests pins només donen 3,3V. Està clar que si volem més llum necessitarem més tensió elèctrica. L'objectiu serà encendre 6 LEDs blancs (que fan força llum), controlats per un pin GPIO de la Raspberry Pi.
  • Sessió 6: 6 abril. Avui fem una classe més tranquil.la. Discutim sobre la construcció del prototipus. Materials, dimensions,... Fem pluja d'idees i els alumnes aporten reflexions interessants.
  • Sessió 7: 20 abril. Hem d'anar definit aspectes tècnics del nostre joc del Simon. Parlarem de com alimentem el nostre joc del Simon, i de com produirem el so.
  • Sessió 8: 27 abril. En la sessió 6 vam estar discutint sobre el disseny industrial del Simon. En especial ens preocupa el disseny dels botons grossos i el sistema de molla/retorn del botó. Avui treballarem amb LibreCAD el disseny dels botons per tal de mecanitzar-ho amb una màquina CNC. Estudiarem el flux de treball que es fa servir: disseny CAD > Generació del G-Code > Fresat CNC. És un procés similar al que utilitzaem per a imprimir amb 3D.
  • Sessió 9: 4 maig. Anem a construir ja els prototipus dels alumnes. Aquesta setmana ens centrarem en la construcció, la setmana vinent ens centrarem ja en el codi. Els alumnes disposen de la RPi, 4 botons, 4 LEDs de colors, resistències, cables, grimpadora,...
    • Començar a posar-ho tot junt.
  • Sessió 10: 11 maig. Ara que ja tenim construït el nostre prototip, anem ja a fer funcionar el Simon a partir d'un codi original de què disposem. Avui ja hem de jugar amb el Simon! Més endavant podrem fer modificacions i millores...
  • Sessió 11: 18 maig. En aquesta sessió treballem el software, fins arribar a la versió que serà definitiva, i presentem l'estat del prototipus.
  • Sessió 12: 25 maig. Versió en principi definitiva del software, simon_v6.py. Implementem el reset i altres millores. Discutim l'estat actual del prototipus. Discutim possibles i futures millores, com ficar una pantalleta.
  • Sessió 13: 1 juny. Presentem el moble acabat. Mirem com han quedat connectats i soldats tots els components, i n'identifiquem totes les parts. Així mateix, hi ha un últim canvi en el software. I juguem!

Codi original. Llibreries necessàries

fitxer simon_original.py:

##!/usr/bin/env python
#______________________________
#
#Simon Game prototype
#Piers Kennedy
#12-07-2012 (update 27-02-2013)
#
#______________________________
 
import RPi.GPIO as GPIO
import random
import time
import numpy
import wave
import pygame
import subprocess
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
 
#Set up sounds
#This avoids any delay before sound starts
pygame.mixer.pre_init(44100,-16,2,2048)
#Initialise mixer
pygame.mixer.init()
subprocess.Popen('amixer cset numid=3 1',shell=True)
SAMPLERATE = 44100
 
def createSignal(frequency, duration):
    samples = int(duration*SAMPLERATE)
    period = SAMPLERATE / frequency
    omega = numpy.pi * 2 / period
    xaxis = numpy.arange(samples, dtype=numpy.float) * omega
    yaxis = 32800 * numpy.sin(xaxis)
    return yaxis.astype('int16').tostring()
 
def createWAVFile(filename, signal):
    file = wave.open(filename, 'wb')
    file.setparams((1, 2, SAMPLERATE, len(signal), 'NONE',
    'noncompressed'))
    file.writeframes(signal)
    file.close()
 
def playWAVFile(filename):
    sound = pygame.mixer.Sound(filename)
    sound.play()
 
#blue sound 209Hz
bluesound = '/tmp/blue.wav'
signal = createSignal(frequency=209, duration=.4)
createWAVFile(bluesound, signal)
#yellow sound 252Hz
yellowsound = '/tmp/yellow.wav'
signal = createSignal(frequency=252, duration=.4)
createWAVFile(yellowsound, signal)
#red sound 310Hz
redsound = '/tmp/red.wav'
signal = createSignal(frequency=310, duration=.4)
createWAVFile(redsound, signal)
#green sound 415Hz
greensound = '/tmp/green.wav'
signal = createSignal(frequency=415, duration=.4)
createWAVFile(greensound, signal)
 
#losing tone 42 Hz
losingtone = '/tmp/losingtone.wav'
signal = createSignal(frequency=42, duration=3)
createWAVFile(losingtone, signal)
 
#Variables
max     = 100               #No. of rounds in game
RoundNo = 1
RED     = 1
GREEN   = 2
YELLOW  = 3
BLUE    = 4
correct = True
 
#Setup GPIO switches
GPIOSwitch=[0,7,11,13,15]
GPIO.setup(7, GPIO.IN)      #red    GPIO 7
GPIO.setup(11, GPIO.IN)     #green  GPIO 0
GPIO.setup(13, GPIO.IN)     #yellow GPIO 2
GPIO.setup(15, GPIO.IN)     #blue   GPIO 3
 
#Setup GPIO LEDs
GPIOLED=[0,12,16,18,22]
GPIO.setup(12, GPIO.OUT)    #red    GPIO 1
GPIO.setup(16, GPIO.OUT)    #green  GPIO 4
GPIO.setup(18, GPIO.OUT)    #yellow GPIO 5
GPIO.setup(22, GPIO.OUT)    #blue   GPIO 6
 
#Connect the ground to pin 6 and the positive to pin 1 (3V3)
 
#Generate a random list of LED outputs
colour=[]
for n in range(1,max+2):
    colour.append(random.choice([RED,GREEN,YELLOW,BLUE]))
 
#Function to switch LEDs on then off
def LEDout(val):
    if (val==1):
        playWAVFile(redsound)
    elif (val==2):
        playWAVFile(greensound)
    elif (val==3):
        playWAVFile(yellowsound)
    elif (val==4):
        playWAVFile(bluesound)
    while pygame.mixer.get_busy():
        GPIO.output(GPIOLED[val], True)
    GPIO.output(GPIOLED[val],False)
    time.sleep(0.15)
    return[]
 
#Function to check when switch is pressed
def SwitchChosen():
    while True:
            if (GPIO.input(GPIOSwitch[RED])):
                return RED
            if (GPIO.input(GPIOSwitch[GREEN])):
                return GREEN
            if (GPIO.input(GPIOSwitch[YELLOW])):
                return YELLOW
            if (GPIO.input(GPIOSwitch[BLUE])):
                return BLUE
 
#Function to flash LEDs after mistake
def LoserLights():
    playWAVFile(losingtone)
    for cycle1 in range(0,6):
        for cycle2 in range(1,5):
            GPIO.output(GPIOLED[cycle2], True)
        time.sleep(0.5)
        for cycle2 in range(1,5):
            GPIO.output(GPIOLED[cycle2], False)
        time.sleep(0.2)
    return[]
 
#Main routine
while correct:
    print("Round %i" %RoundNo)
    #LED cycle
    for mout in range(1,RoundNo+1):
        LEDout(colour[mout])
    #Response
    for ans in range(1,RoundNo+1):
        push=SwitchChosen()
        LEDout(push)
        if(push!=colour[ans]):
            LoserLights()
            correct = False
            print("Unlucky!")
            print("You made it to round %i" %RoundNo)
            break
    RoundNo+=1
    if (RoundNo==max+1):
        print("WOW!! You Rock dude")
        break
    time.sleep(0.5)

Anem a executar aquest codi en una Raspberry Pi 3 on hem instal.lat 2017-02-16-raspbian-jessie-lite.img, acabada d'instal.lar.

Executem el codi i solucionem els errors que ens dóna, degut a què ens manquen certes llibreries.

$ python simon_original.py 
Traceback (most recent call last):
  File "simon_original.py", line 13, in <module>
    import numpy
ImportError: No module named numpy

NumPy is the fundamental package for scientific computing with Python

Hem d'instal.lar la llibreria numpy:

$ pip install numpy

per instal.lar pip,

$ sudo apt-get install python-pip

o millor:

$ sudo apt-get install python-numpy

Tornem a executar el nostre fitxer:

$ python simon_original.py 
Traceback (most recent call last):
  File "simon_original.py", line 15, in <module>
    import pygame
ImportError: No module named pygame
python-pygame - SDL bindings for games development in Python (Python 2)
$ sudo apt-get install python-pygame

i ara ja funciona:

$ python simon_original.py 
numid=3,iface=MIXER,name='PCM Playback Route'
  ; type=INTEGER,access=rw------,values=1,min=0,max=2,step=0
  : values=1
Round 1

creat per Joan Quintana Compte, desembre 2016