![]() |
Miniature theater - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: General Coding Help (https://python-forum.io/forum-8.html) +--- Thread: Miniature theater (/thread-25116.html) |
Miniature theater - vieira_diniz - Mar-20-2020 Hello World! ![]() I'm creating a miniature theater to show a story in a cemetery. I intent to manipulate the puppet personages during a piece of music is playing and the lights illuminate the scenery. Some images are down. I wrote the code, but I believe that it can be more simple and with less redundancy to work well. I don't know why, but some lights start "on" when I'd like to start all "off". ![]() Can someone help me to improve my code? Any help is welcome! import RPi.GPIO as GPIO import time import random import pygame pygame.mixer.init() pygame.mixer.music.load("/home/pi/Music/Romance para teatro.mp3") pygame.mixer.music.play() GPIO.setmode(GPIO.BCM) def setup(): #Setup GPIO iluminação, luzes de 1 a 12. GPIO.setup(1, GPIO.OUT) # Luz 1 - direcional central (t. defunto). GPIO.setup(2, GPIO.OUT) # Luz 2 - dir. (t. caveira). GPIO.setup(3, GPIO.OUT) # Luz 3 - esq. (cova aberta). GPIO.setup(4, GPIO.OUT) # Luz 4 - esq. (t. caveiro). GPIO.setup(5, GPIO.OUT) # Luz 5 - dir. (t. defunto). GPIO.setup(6, GPIO.OUT) # Luz 6 - esq. (esquina caveira). GPIO.setup(7, GPIO.OUT) # Luz 7 - dir. (esquina caveiro). GPIO.setup(8, GPIO.OUT) # Luz 8 - ribalta portão. GPIO.setup(9, GPIO.OUT) # Luz 9 - esq. (t. cruz). GPIO.setup(10, GPIO.OUT) # Luz 10 - int. caveiro. GPIO.setup(11, GPIO.OUT) # Luz 11 - int. caveira. GPIO.setup(12, GPIO.OUT) # Luz 12 - geral. def output(): GPIO.output(1, False) GPIO.output(2, False) GPIO.output(3, False) GPIO.output(4, False) GPIO.output(5, False) GPIO.output(6, False) GPIO.output(7, False) GPIO.output(8, False) GPIO.output(9, False) GPIO.output(10, False) GPIO.output(11, False) GPIO.output(12, False) # set Frequece to 100Hz I = GPIO.PWM(1, 100) Z = GPIO.PWM(2, 100) E = GPIO.PWM(3, 100) A = GPIO.PWM(4, 100) S = GPIO.PWM(5, 100) G = GPIO.PWM(6, 100) T = GPIO.PWM(7, 100) B = GPIO.PWM(8, 100) Q = GPIO.PWM(9, 100) IO = GPIO.PWM(10, 100) II = GPIO.PWM(11, 100) IZ = GPIO.PWM(12, 100) # Start PWM output, all off. I.start(0) Z.start(0) E.start(0) A.start(0) S.start(0) G.start(0) T.start(0) B.start(0) Q.start(0) IO.start(0) II.start(0) IZ.start(0) def action(): # 0 - 2,5 seg Black out, apenas música. time.sleep(2.5) # Black out 0 - 2,5 seg. # Introdução I | 2,5 - 9,8 seg, interior dos túmulos. GPIO.output(10,True) # Int. Caveiro 2,5 - 3,7 seg. time.sleep(1.2) GPIO.output(10, False) time.sleep(0) GPIO.output(11, True) # Int. Caveira 3,7 - 4,7 seg. time.sleep(1) GPIO.output(11, False) time.sleep(0) GPIO.output(10, True) # Int. Caveiro 4,7 - 5,7 seg. time.sleep(1) GPIO.output(10, False) time.sleep(0) GPIO.output(11, True) # Int. Caveira 5,7 - 6,6 seg. time.sleep(0.9) GPIO.output(11, False) time.sleep(0) GPIO.output(10, True) # Int. Caveiro 6,6 - 7,5 seg. time.sleep(0.9) GPIO.output(10, False) time.sleep(0) GPIO.output(11, True) # Int. Caveira 7,5 - 8,6 seg. time.sleep(1.1) GPIO.output(11, False) time.sleep(0) GPIO.output(10, True) # Int. Caveiro 8,6 - 9,4 seg. time.sleep(0.8) GPIO.output(10, False) time.sleep(0.4) # Introdução II | 9,8 - 20,4 seg, focos nos túmulos e luz geral. GPIO.output(4, True) # T. Caveiro 9,8 seg. time.sleep(0.9) GPIO.output(4, False) time.sleep(0) GPIO.output(2, True) # T. Caveira 11,7 seg. time.sleep(1.7) GPIO.output(2, False) time.sleep(0) GPIO.output(7, True) # Cova aberta 13,4 seg. time.sleep(1.9) GPIO.output(7, False) time.sleep(0) GPIO.output(9, True) # T. cruz 15,3 seg. time.sleep(2.0) GPIO.output(9, False) time.sleep(0) GPIO.output(12, True) # Geral 17,3 seg. time.sleep(4.1) GPIO.output(12, False) time.sleep(0) # Encontro das caveiras | 20,4 - 45,6 seg, saída das caveiras. GPIO.output(2, True) # Foco nos túmulos dos dois aos 20,4 seg. GPIO.output(4, True) time.sleep(6.6) GPIO.output(2, False) GPIO.output(4, False) time.sleep(0) GPIO.output(12, True) # Geral 27,0 seg. time.sleep(12.8) GPIO.output(12, False) time.sleep(0) GPIO.output(8, True) # Ribalta 39,8 seg. time.sleep(5.8) GPIO.output(8, False) time.sleep(0) # Juras de amor até coruja | 45,6 - 95,1 seg. GPIO.output(1, True) # Foco na lousa fria aos 45,6 seg. GPIO.output(5, True) GPIO.output(6, True) time.sleep(25) GPIO.output(1, False) GPIO.output(5, False) GPIO.output(6, False) time.sleep(0) GPIO.output(8, True) # Foco na coruja aos 70,6 seg. time.sleep(5.5) GPIO.output(1, True) # Foco na lousa fria aos 76,1 seg + anterior. GPIO.output(5, True) GPIO.output(6, True) time.sleep(6.8) GPIO.output(1, False) # Apaga lousa fria 82,9 seg, mantém coruja. GPIO.output(5, False) GPIO.output(6, False) time.sleep(0) GPIO.output(12, True) # Luz geral aos 82,9 seg + coruja. time.sleep(5.5) GPIO.output(12, False) time.sleep(5.7) GPIO.output(8, False) # Apaga coruja aos 94,1 seg e blackout por 1 seg. time.sleep(1) # Surge o defunto | 95,1 - 170,9 seg. GPIO.output(1, True) # Foco na lousa fria aos 95,1 seg. GPIO.output(5, True) GPIO.output(6, True) time.sleep(9.2) GPIO.output(1, False) GPIO.output(5, False) GPIO.output(6, False) time.sleep(0) GPIO.output(12, True) # Luz geral aos 104,2 seg. time.sleep(9) GPIO.output(12, False) time.sleep(0) GPIO.output(3, True) # Foco na cova aberta aos 113,3 seg. GPIO.output(7, True) time.sleep(9.3) GPIO.output(3, False) GPIO.output(7, False) time.sleep(0.4) GPIO.output(12, True) # Luz geral aos 123,0 seg. time.sleep(28.6) GPIO.output(12, False) time.sleep(0) GPIO.output(2, True) # Túmulo caveira aos 151,6 seg. time.sleep(6.7) GPIO.output(2, False) # Blackout aos 158,3 seg. time.sleep(3.4) GPIO.output(11, True) # Luz interna túmulo da caveira aos 158,3 seg. time.sleep(6.9) GPIO.output(11, False) time.sleep(1.9) def loop(): try: while True: action() except KeyboardInterrupt: pass finally: pygame.mixer.music.stop() #Stop music. GPIO.cleanup() setup() loop() RE: Miniature theater - scidam - Mar-20-2020 I would use a parser and a specific format that describes the entire action. The following is a sketch, but is almost completed, and probably will be helpful for you. import RPi.GPIO as GPIO import time import random import pygame pygame.mixer.init() pygame.mixer.music.load("/home/pi/Music/Romance para teatro.mp3") class Theater: freq = 100 actors = { 'defunto': 1, # put comments here directional central etc... 'caveira': 2, # ... define the same way all 12 items/switches?! 'int_caveira': 11 'geral': 12 } takt_executors = { 'mplay': '_mplay_exec', 'mstop': '_mstop_exec', 'o': '_o_exec', 's': '_s_exec' } def __init__(self): self.iface = GPIO self.iface.setmode(self.iface.BCM) # do setup for actor, num in Theater.actors.items(): self.iface.setup(num) def output(self): """ Docstring needs be here. I didn't see that you use this function?! It seems to be never called in your code. """ # is this allowed, or you need to split # it into 2 separated for-loops? for actor, num in Theater.actors.items(): self.iface.output(num, False) self.iface.PWM(num, Theater.freq).start(0) def load_episode(self, episode): """ Docstring needs be here. """ self.episode = episode def play(self, mode=None): """ Docstring needs be here. """ if self.episode is None: # I don't know, where it will be printed in case of GPIO?! print("No episode was loaded. Load an episode first") try: if mode == 'always': while True: self._play() else: # you can define more modes using elif statement... self._play() # play only once except KeyboardInterrupt: pass finally: pygame.mixer.music.stop() #Stop music. GPIO.cleanup() def _parse(self): if self.episode is None: return [] result = [] for token in map(str.strip, self.episode.split('\n')): if token == 'mplay': result.append(("mplay", None, None)) elif token == 'mstop': result.append(("mstop", None, None)) elif token.startswith('s'): try: result.append(('s', float(token[1:]), None)) except (ValueError, IndexError): pass elif token.startswith('o'): try: result.append(('o', token[2:-2], True if token[-1] == 't' else False)) except (ValueError, IndexError): pass return result def _mplay_exec(self, *args): pygame.mixer.music.play() def _mstop_exec(self, *args): pygame.mixer.music.stop() def _o_exec(self, *args): channel = Theater.actors.get(args[1]) if ch is not None: self.iface.output(channel, args[-1]) def _s_exec(self, *args): time.sleep(args[1]) def _nothing_exec(self, *args): pass def _play(self): for takt in self._parse(): exec_name = self.takt_executors.get(takt[0], '_nothing_exec') getattr(self, exec_name)(*takt) # --------------------- Structure of episode description --------------- # This is your action, it is written as a string, so it can be saved # to a file, read and played again. episode = """ mplay s2.5 o_caveira_t s1.2 o_caveira_f s0 # complete full action; syntax is self-explanatory, i hope o_int_caveira_f s1.9 mstop """ # mstop, mplay -- stop and play music respectively theater = Theater() theater.load_episode(episode) theater.play(mode='always')I am sorry about too few comments ( I am tired), but I hope the code is self-explanatory and almost working... ==== UPD: I updated the code. It is not tested, however. The main idea is to use human understandable commands that describe the theatrical performance. If you look at episode variable, it is just a string. Each new line is a new command. Awesome invention, I think. Hope that helps. |