# elements.py Updated on 14 Dec. 16 and renamed from new_main12fast_corr.py # A project of the Las Cruces Academy: work by the students in grades 4-8 # from Dec. 2013 to Dec. 2016, withe support and various kinds of direction # by Dr. Vince Gutschick, teacher and Chair of the Board # # Written by Vince and students Louis Pate and Ayanna Leal, with contributions # by Alegra Reinhold and suggestions for user-interface design elements from # Arabella Camunez. The audio files (approximately 450) that the program play # ("*_narration.wav") were created and recorded primarly by Arabella Camunez # with some assistance from Alegra Reinhold, Tianna Armendariz, and Louis Pate # # A program to run a user's choice of any of 5 different presentations about # the chemical elements, using LEDs to highlight the elements' positions on # the periodic table and offering narrations on each element created and # recorded by the students. # # The program runs on a Raspberry Pi Model B running a version of Debian Linux # (Raspbian Wheezy). The program uses 14 of the 26 GPIO pins on the PI to # receives users' choices via 4 momentary-contact buttons (designated green, # red, amber, and white). The program uses 10 other GPIO pins as outputs to # send signals to a logic board that sets LEDs behind the element cells either # on or off. # The 5 presentations and the user's possible selections within them are: # The elements in order of atomic number - 112 individual selections # (elements, of course). (We started the construction and programming # before the elements to no. 118 were named officially) # The elements in order of discovery - one selection as the 13 elements # known to the ancients as a single entity, and 99 other selections # for the remaining 99 elements # The elements in order of nucleosynthesis - in the Big Bang, in the Sun # currently, in the Sun at the end of its life, and in supernovae # The elements in order of abundance in the Earth's crust, for the first # 78 (the others being present in trace amounts or transiently in labs) # The elements in order of abundance in the (average) human body - 14 # selections have been recorded to date # # At the start of the program, the program writes instructions to the user # on a small 4" x 6" TFT monitor, noting the 5 choices of presentations and # indicating how to navigate among them - the green pushbutton advances the # choice (say, from atomic number to discovery), the red button moves # backward or upward in the list. Both actions wrap around, e.g., from # the 5th presentation back to the 1st or vice versa. Pushing the amber # button starts the chosen presentation. # The presentation subroutine writes instructions to the user, similarly. # The green button advances the selection (say, from hydrogen to helium # or from potassium to calcium in the atomic number presentation), while # the red button moves the selection backward. The amber button makes the # presentation of the selection - e.g., it lights up the LED behind the # chosen element and plays the narration recorded for the element. Note # that, for any given element, say, nitrogen, the narrations differ for it # among the 5 presentations (nitrogen by atomic number, nitrogen's # discovery, etc.). # # How the LEDs are controlled by the logic board: # Each LED has positive 5V applied to one pin from a master regulated 5V # supply. The other pin has a current-limiting resistor (chosen to limit # the current 18 mA) and a connection to a drain on one pin of one # addressable latch with memory. The fundamental action of the program is # to set various GPIO pins in a sequence (explained shortly) so that the # drain on the latch is set either low (allowing current to sink and light # the LED) or high (off). # The latch can retain the setting on each of its 8 drains independently of # the settings on its other 7 drains. # The overall logical connectivity is: # There are 2 level-1 latches, each controlling 8 others for a total of # 64 drains or LEDs each. The drains on these level-1 latches are used simply # to enable or disable any or all of the 8 level-2 latches controlled by # this level-1 latch. We need 2 level-1 latches to be able to control # 112 (or more) LEDs. # Example: we want to set the LED for the 45th drain to be on. (This is not # likely element 45; there is a complicated mapping, for good reasons that # are presented shortly). Since the numbering starts from 0, not 1, this is # drain 44. This is in the first 64 drains, so it is controlled by the # first level-1 latch (1A); a drain numbered between 64 and 111 would be # controlled bh the second level-1 latch (1B). Given that there are 8 drains # per level-2 latch, this drain is found on the 6th of those latches # (controlled then by drain 5 on latch 1A). On that level-2 latch, drain # 44 is its drain 4. # Each latch has 3 selector inputs, S0, S1, S2 on its pin-out, to select # which of its own drains is to be set hi or lo. We call these S0, S1, and S2 # on the level-2 latches but S3, S4, and S5 on the level-1 latches. # We set as an address the decimal number 44 in binary, which is 101100. The # highest 3 bits, 1, 0, and 1, are the values to which selectors S3, S4, and # S5 are set - that is, latch 1A is going to use its drain 5 to control # the 6th level-2 latch. The lowest 3 bits, 1, 0, and 0, are the values to # which selectors S0, S1, and S2 are set on the level-2 latches (drain 4) - # to ALL the level-2 latches in parallel, though only one of them (number 5) # will be made active to change its settings. # In addition to its selector inputs, each latch has an enable pin (0 or low # voltage on it keeps it inactive or nonresponsive, 1 makes it active) and # a pin we call Value; if Value is hi, the selected drain goes lo (LED on), # and it Value is lo, the selected drain goes hi (LED off). There is a # chain of 21 commands to disable all writing (all drain setting), then # set the 6 selectors S0 through S5, then set a Value for the final (level-2) # drain, then write this (enable both the level-1 and level-2 latch), then # disable all writing to preserve the state. These commands are seen in # the subrouting LEDturn(), with comments to explain them. # # How the narrations are selected and played: # The narrations are all WAV files created in the Audacity application. They # are named in a logical way - e.g., the narration for hydrogen is # hydrogen_narration.wav to use in the presentation by atomic number; it is # discovery_of_hydrogen_narration.wav to use in the presentation of elements # in order of discovery, and so on. # When the user selects calcium in the presentation in order of atomic number, # this is atomic number 20 or element number 19 (again, recall that the # numbering starts from 0). The program goes to an array elname, finding # that entry 19 is the string "calcium". It composes a full string, # "aplay calcium_narration.wav" and passed this string as the argument to the # system call os.system(string); that makes the narration play through the # Raspberry Pi's audio port # # One more hardware issue: the Raspberry Pi GPIO pins run on 3.3V (and 5V in # would be damaging!), but the latches use a 5V signal. Even with the # tolerance for lower than nominal input voltages, the latch would need at # least 3.5V to respond to a high signal. So, we have to take a 3.3V (or 0V) # signal from the Pi and create a 5V (or 0V) signal. We do this by using # op amps as comparators. Each GPIO output pin goes to the noninverting input # of an op amp. The inverting input is held at a reference 2.7V. If the # GPIO pin goes hi to 3.3V, the op amp output goes to the full 5V (we use # rail-to-rail op amps). # # Functional parts of the program: # # An array, atnoselec[], with 112 entries. The LEDs are not connected to drains # in order. Hydrogen is connected to drain 95, helium to drain 11, and so on. # This happened because we wanted short runs of wires from the LEDs to the # drains, with minimal crossing of wires. Hydrogen and helium are at opposite # ends of the chart, so thay wre grouped with very different sets of elements. # Thus, when the program needs to find which selector addresses element of # atomic number N, which is element number N-1 (elno = N-1), it fetches the # entry atnoselec[N-1] and passes this to the subroutine LEDturn() for # setting the element's LED on or off. # # An array, elname[], with 112 entries. The program finds the string that is # entry N-1 for the element of atomic number N and uses this to, first, # present the name on the TFT monitor for the user, and second, to generate # the string that will make the correct narration play in the audio port # of the Pi (see above). # # An array, orderdiscov[], with 100 entries. The first entry is itself an # array, the atomic numbers of 13 elements that were known to the ancient. # The other 99 entries are the atomic numbers of the other elements, in # chronological order of discovery. # # An array, elabun_atno[], with 78 entries. The entries are the atomic numbers # of the elements in order of abundance, highest to lowest, taken from a # table of the Royal Chemical Society. # # An array, HBabun[], with 14 active entries (having corresponding narrations), # though we have included entries for the first 40 (beyond that, the elements # are in such trace quantities as to make the estimates too "soft"). # # A section of nonexecutable code that sets up the GPIO pins to be used as # inputs or outputs. The functions are: # S0, S1, ... S5: sending signals to latch selectors, which have been noted # En1, En2: sending enable/disable signals to level-1 latches 1A, 1B # V1: sending a signal to both level-1 latches 1A, 1B, to make a drain # on them hi (enabling a selected level-2 latch for writing) or lo # V2: sending a signal to all the level-2 latches to set a selected drain # hi or lo; only one enabled latch among these actually acts on the signal # B1: receive signals from the green button when it's pushed by the user; # B2, B3, B4 correspondingly from the red, amber, and white buttons # # LEDturn(elno, onoff), the subroutine that accepts a command to turn on or off # the LED for the element whose selector number is elno (this really might be # called selecno in consistent terminology) # The steps that it takes are all described in comments therein. In brief, it # first disables all level-2 latches so that nothing is written accidentally # while setting the selectors. Then it generates all the selector values # S0 through S5 as bits extracted from the elno expressed in binary, using # bitwise AND. It sets these values on the selector pins, then enables the # associated level-1 latch to write the value V2 to the final drain on the # level-2 latch to which the LED is attached. Finally, it disables all writing # to preserve the chosen state. Note that prior on-off settings for LEDs are # not affected in all this, so that a sequence of LEDs can be lit. # # atno(), the subroutine that handles the presentation of elements in order of # atomic number. It begins by turning off any LEDs lit by another presentation. # Then it enters an indefinite loop (a while True loop), waiting for the user to # press any button. Inside, another while True loop looks for those button # pushes. If it's on the green button, it increments the element number; if # it's on the red button, it decrements it. If it's on the amber button, it # sends a command to LEDturn() to turn the LED on for the currently chosen # element number, then play the corresponding narration (see above for how the # command to os.sys is created), and finally turn the LED off. # # discov(), the subroutine that handles the presentation of elements in order of # discovery. It acts very similarly to atno(), though it has a special loop # to run through 13 elements known to the ancients, if this has been chosen. # To play the appropriate narration, it composes a longer string than does # atno(), "aplay discovery_of_xxx_narration.wav", with xxx=name of the element. # # syn(), the subroutine that handles the presentation of elements in order of # their nucelosynthesis in any of 4 scenarios - Big Bang, Sun currently, Sun at # the end of its life, and supernovae. Again, it acts similarly to atno(), # though every one of its options needs a loop over several (or many!) elements: # 3 elements for the Big Bang, up to all 112 for a supernova. # # abun(), the subroutine that handles the presentation of elements in order of # abundance in the Earth's crust, as reported by the Royal Society of Chemistry. # It acts similarly to atno(), though it has two steps to identify the proper # element: first, it looks up the element number: the atomic number of the # element that is rank N in abundance is found as entry number N-1 in the # array elabun_atno[]; second, it finds the appropriate selector number and # the appropriate narration. The string for playing the appropriate # narration is now "aplay xxxEC_narration.wav", with xxx=name of the element. # # hb(), the subroutine that handles the presentation of elements in order of # abundance in the (average?) human body. It acts similarly to abun(), while # looking for the appropriate atomic number in the array HBabun[]. The string # for playing the appropriate narration is now "aplay xxxEC_narration.wav", # with xxx=name of the element. # # And, finally, the MAIN program. First, it turns off all LEDs that may have # been set on by a previous run. It presents the choices of presentations # to the user, then enters an indefinite loop (a while True loop), waiting for # a button to be pushed. The choice of presentation, linenow, originally set to 0 # (which is for that in the order of atomic number), can be incremented or # decremented with the green or red buttons. Pressing the amber button # sends the program to a set of cases; depending on the value of linenow, the # program calls one of the five presentation subroutines. From any presentation, # control can return here by pressing the white button. We did not set any # option to terminate the whole program here; one simply uses a keyboard # interrupt, ^C. That sets the "administrator" up to re-initiate this program # at will or to initiate one of our other demo programs, such as one that # lights up 10 elements at random, then a randomly chosen sequence (such as the # lanthanides, or the noble gases), repeating this indefinitely. Another demo # program spells out LCA with the LEDs, erases it, and repeats this indefinitely. atnoselec=['']*120 atnoselec=[96, 11, 104, 99, 6, 10, 12, 23, 5, 21, 90, 91, 16, 20] #els. 1-14 atnoselec=atnoselec+[14, 18, 2, 31, 103, 92, 88, 93, 97, 83, 77] # els. 15-25 atnoselec=atnoselec+[34, 70, 65, 47, 1, 4, 15, 8, 0, 19, 13, 94] # els. 26-37 atnoselec=atnoselec+[95, 98, 109, 101, 106, 64, 36, 39, 37, 35, 71] # els. 38-48 atnoselec=atnoselec+[9, 115, 7, 22, 3, 17, 111, 105, 74, 86, 73, 67] # els. 49-60 atnoselec=atnoselec+[87, 72, 30, 44, 117, 45,113 , 25, 61, 28, 24, 110] #els. 61-72 atnoselec=atnoselec+[107, 43, 33, 78, 38, 79, 46, 42, 69, 119, 27, 63] # els. 73-84 atnoselec=atnoselec+[62, 58, 108, 89, 82, 75, 81, 80, 85, 57, 26, 116] # els. 85-96 atnoselec=atnoselec+[29, 59, 56, 114, 118, 60, 112, 102, 100, 84, 66] # els. 97-107 atnoselec=atnoselec+[68, 40, 41, 76, 32] # els. 108-112 # Have the names of the elements in order of atomic number, to use in all the subroutines elname=['']*120 elname=["hydrogen", "helium", "lithium", "beryllium", "boron", "carbon", "nitrogen", "oxygen"] elname=elname+["fluorine", "neon", "sodium", "magnesium", "aluminum", "silicon", "phosphorus", "sulfur"] elname=elname+["chlorine", "argon", "potassium", "calcium", "scandium", "titanium", "vanadium", "chromium"] elname=elname+["manganese", "iron", "cobalt", "nickel", "copper", "zinc", "gallium", "germanium"] elname=elname+["arsenic", "selenium", "bromine", "krypton", "rubidium", "strontium", "yttrium", "zirconium"] elname=elname+["niobium", "molybdenum", "technetium", "ruthenium", "rhodium", "palladium", "silver", "cadmium"] elname=elname+["indium", "tin", "antimony", "tellurium", "iodine", "xenon", "cesium", "barium"] elname=elname+["lanthanum", "cerium", "praseodymium", "neodymium", "promethium", "samarium", "europium", "gadolinium"] elname=elname+["terbium", "dysprosium", "holmium", "erbium", "thulium", "ytterbium", "lutetium", "hafnium"] elname=elname+["tantalum", "tungsten", "rhenium", "osmium", "iridium", "platinum", "gold", "mercury"] elname=elname+["thallium", "lead", "bismuth", "polonium", "astatine", "radon", "francium", "radium"] elname=elname+["actinium", "thorium", "protactinium", "uranium", "neptunium", "plutonium", "americium", "curium"] elname=elname+["berkelium", "californium", "einsteinium", "fermium", "mendelevium", "nobelium", "lawrencium", "rutherfordium"] elname=elname+["dubnium", "seaborgium", "bohrium", "hassium", "meitnerium", "darmstadtium", "roentgenium", "copernicium"] # Below is for use in discov() subroutine ancients=[51,83,6,29,79,26,82,80,78,47,16,50,30] # Present these all at once in a group - # antimony, bismuth, ...zinc, in alphabetical order orderdiscov=['']*100 orderdiscov=[0,33, 15, 27, 28, 1, 7, 17, 25, 8, 42] # Order taken from list in CRC Handbook orderdiscov=orderdiscov+[52, 74, 92, 40, 38, 22, 39, 4, 24, 41] # Array created nicely in Excel, then Vim orderdiscov=orderdiscov+[23, 73, 58, 77, 76, 46, 45, 19, 11, 56] orderdiscov=orderdiscov+[5, 20, 12, 44, 53, 48, 3, 34, 14, 13] orderdiscov=orderdiscov+[35, 90, 57, 68, 65, 55, 37, 81, 49, 31] orderdiscov=orderdiscov+[67, 70, 62, 21, 69, 64, 60, 59, 66, 9] orderdiscov=orderdiscov+[32, 18, 2, 36, 10, 84, 88, 54, 89, 86] orderdiscov=orderdiscov+[63, 71, 91, 72, 75, 43, 87, 85, 93, 94] orderdiscov=orderdiscov+[95, 96, 61, 97, 98, 99, 100, 101, 102, 103] orderdiscov=orderdiscov+[104, 105, 106, 107, 109, 108, 110, 111,112] # Below is for use in abun() subroutine elabun_atno=['']*78 elabun_atno=[8,14,13,26,20,11,19,12,22,1,15,25,9,56,6,38] # Data from website of Royal Soc. Chemistry elabun_atno=elabun_atno+[16,40,74,23,17,24,37,28,30,29,58,60,57,39,7,27] # Array created nicely using elabun_atno=elabun_atno+[3, 41, 31, 21, 82, 62, 90, 59, 5, 64, 66, 72, 68, 70, 55, 4] # Excel and Vim elabun_atno=elabun_atno+[50, 63, 92, 73, 32, 42, 33, 67, 65, 69, 35, 81, 71, 51, 53, 48] elabun_atno=elabun_atno+[47, 80, 34, 49, 83, 52, 78, 79, 44, 46, 75, 77, 45, 76] # \/ HB ORDERS \/ HBabun_atno=['']*40 HBabun_atno=[8,6,1,7,20,15,16,19,11,17,12,14,9,26,30,13,37,38,35,82] HBabun_atno=HBabun_atno+[29,5,48,56,25,50,53,28,79,33,34,40,3,23,24,55,4,27,92,88] # ----------------------------SET UP GPIO PINS-- import RPi.GPIO as GPIO import sys, os, subprocess GPIO.setmode(GPIO.BOARD) GPIO.setwarnings(False) GPIO.setup(5,GPIO.OUT) # En1 GPIO.setup(3,GPIO.OUT) # En2 GPIO.setup(8,GPIO.OUT,pull_up_down=GPIO.PUD_DOWN) # V1 GPIO.setup(26,GPIO.OUT,pull_up_down=GPIO.PUD_DOWN) # S0 GPIO.setup(24,GPIO.OUT,pull_up_down=GPIO.PUD_DOWN) # S1 GPIO.setup(23,GPIO.OUT,pull_up_down=GPIO.PUD_DOWN) # S2 GPIO.setup(21,GPIO.OUT,pull_up_down=GPIO.PUD_DOWN) # S3 GPIO.setup(19,GPIO.OUT,pull_up_down=GPIO.PUD_DOWN) # S4 GPIO.setup(10,GPIO.OUT,pull_up_down=GPIO.PUD_DOWN) # S5 GPIO.setup(7,GPIO.OUT,pull_up_down=GPIO.PUD_DOWN) # V2 GPIO.setup(22,GPIO.IN) # B1 GPIO.setup(18,GPIO.IN)# B2 GPIO.setup(16,GPIO.IN) # B3 GPIO.setup(15,GPIO.IN) # B4 import os, sys, math, subprocess, time from colorama import init #https://pypi.python.org/pypi/colorama init() from colorama import Fore, Back, Style # # --------------------SUBROUTINE TO TURN ANY ONE LED ON OR OFF ---- # def LEDturn(i, onoff): if i<64: # We're using one of the first 8 latches, 2A through 2H, En1pin=5 # This is the enable pin, En1, for latch 1A else:# We're using one of the last 8 latches, 2I through 2P, connected to En1pin=3 # This is the enable pin, En2, for latch 1B (should I have called it EnB?) time.sleep(0.0001) GPIO.output(5,1) # This is En1, to the En input on latch 1A high, disabling it time.sleep(0.0001) GPIO.output(3,1) # This is En2; it does the same for latch 1B time.sleep(0.0001) GPIO.output(8,0) # Set V1 to 1, which will set a drain on L1A or B off (hi), time.sleep(0.0001) GPIO.output(5,0) # Now enable writing on latch 1A time.sleep(0.0001) GPIO.output(3,0) # And enable writing on latch 1B time.sleep(0.0001) for j in range (0,8): # Run through all possible Latch 2x, connected to 1A and 1B S3=(j&1) S4=(j&2)/2 S5=(j&4)/4 GPIO.output(21,S3) time.sleep(0.0001) GPIO.output(19,S4) time.sleep(0.0001) GPIO.output(10,S5) time.sleep(0.0001) GPIO.output(5,1) # Disable latch 1A now, to begin setting the LED chosen in the argument time.sleep(0.0001) GPIO.output(3,1) # Disable latch 1B, too time.sleep(0.0001) S0=(i&1) # Compute value for selector S0, on final latch, with bitwise AND GPIO.output(26,S0) # Set this value on all latches L2x (only 1 will be written to) time.sleep(0.0001) S1=(i&2)/2 # Compute value for selector S1, on final latch GPIO.output(24,S1) # Set this value time.sleep(0.0001) S2=(i&4)/4 # Compute value for selector S2, on final latch GPIO.output(23,S2) # Set this value time.sleep(0.0001) S3=(i&8)/8 # Now select the proper drain on latches 1A and (really, or) 1B GPIO.output(21,S3) time.sleep(0.0001) S4=(i&16)/16 GPIO.output(19,S4) time.sleep(0.0001) S5=(i&32)/32 GPIO.output(10,S5) time.sleep(0.0001) GPIO.output(7,onoff) # Pre-set the chosen LED off (onoff=0; drain hi) or on (onoff=1, drain lo) time.sleep(0.0001) GPIO.output(8,0) # V1 = 0 sets drain on L1x lo (on) -> sends lo setting to L2x En, which is enabled time.sleep(0.0001) GPIO.output(En1pin,0) # Wait 0.01 s to be sure all the settings take place down the line time.sleep(0.0001) # This might work with delays as short at 0.0001 # Set V1 to 1 to disable further writing on latch 2x GPIO.output(8,1) # V1 =1 sets drain on L1x hi (off) -> sends hi setting to L2x En, disabling L2x time.sleep(0.0001) GPIO.output(En1pin,1) # Disable all further writing; Note that the other latch, 1A or 1B, stays disabled time.sleep(0.0001) return # #---------------------SUBROUTINE TO PRESENT EL. IN ORDER OF AT. NO.--- # def atno(): delay=0.2 for elno in range (0,112): # Turn off any LEDs left from an earlier run, if any selec=atnoselec[elno] LEDturn(selec,0) elno=0 while True: os.system('clear') # Present a clean screen print(Fore.WHITE + Back.BLACK + Style.BRIGHT + "Elements in order of at. no.") print (Fore.RED + ' el. no.='),elno+1,', = ',elname[elno] # Current selection is in bold red print(Fore.WHITE + Back.BLACK + 'Green button --> next element') print("Red button --> one earlier") print("Press amber to play narration") print("Press white button to exit") print(" and choose another program") print '' # n=raw_input() # Take button input to choose which element to present (or to # revert to choosing a different program, such as elements by order of discovery while True: # Simply poll the button switches until one is pushed time.sleep(0.0001) # reduce polling burden on CPU if GPIO.input(22)==1: # pin 22 is normally lo; green button; increment the element number elno=(elno+1)%112 # print 'el. no.=',elno,', which is ',elname[elno] # redundant time.sleep(delay) break elif GPIO.input(15)==0: # pin 3 is normally hi; white button; leave this subroutine os.system('clear') return elif GPIO.input(18)==1: # pin 18 is normally lo; red button; decrement the element number elno=(elno-1)%112 time.sleep(delay) break elif GPIO.input(16)==0: # pin 16 is normally hi; amber button; light LED & play narration LEDturn(atnoselec[elno], 1) # print ("Turn on selected LED") #### Here: disable writing to screen to suppress "Playihg WAVE..."/ doesn't work yet! # string='aplay '+elname[elno]+'_narration.wav > /dev/null' string='aplay '+elname[elno]+'_narration.wav' # print string # time.sleep(3) # old_stdout=sys.stdout # f=open(os.devnull,'w') # sys.stdout=f os.system(string) # sys.stdout=old_stdout LEDturn(atnoselec[elno], 0) # LED stays on only until the narration finishes break # #-------------------------SUBROUTINE TO PRESENT EL. IN ORDER OF DISCOVERY--- # def discov(): delay=0.2 for elno in range (0,112): # Turn off any LEDs from last run, if any selec=atnoselec[elno] LEDturn(selec,0) N_discov=100 elno=0 # PLAY AN INTRODUCTORY AUDIO XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX while True: os.system('clear') print(Fore.WHITE + Back.BLACK + Style.BRIGHT + "Elements in order of discov.") if elno==0: print (Fore.RED + 'Elements known to the ancients') # An array, not a single element else: kk=orderdiscov[elno] # Find the name of the element discovered as the elno-th print (Fore.RED + 'Discovery #'+str(elno+13)+','+elname[kk-1]) print(Fore.WHITE + Back.BLACK + 'Green button --> next element') print("Red button --> one earlier") print("Press amber to play narration") print("Press white button to exit") print(" and choose another program") print '' # n=raw_input() while True: # Simply poll the button switches until one is pressed time.sleep(0.0001) # reduce polling burden on CPU if GPIO.input(22)==1: # pin 22 is normally lo; green button; increment element number elno=(elno+1)%N_discov kk=orderdiscov[elno] print 'discov. no.=',str(elno),', which is ',elname[kk-1] time.sleep(delay) break elif GPIO.input(15)==0: # pin 15 is normally hi; white button; leave this subroutine return elif GPIO.input(18)==1: # pin 18 is normally lo; red button; decrement element number elno=(elno-1)%N_discov time.sleep(delay) break elif GPIO.input(16)==0: # pin 16 is normally hi; amber button; light LED & start narration if elno==0: # POSSIBLY ADD INTRO. - RUNNING THROUGH 13 EL. KNOWN TO ANCIENTS for jj in range (0,13): #Light LEDs and play narr. for 13 el. kk=ancients[jj] LEDturn(atnoselec[kk-1],1) string='aplay discovery_of_'+elname[kk-1]+'_narration.wav' os.system(string) time.sleep(5) # Keep the LEDs lit for 5 seconds for user to absorb the information for jj in range (0,13): #Turn off these LEDs now kk=ancients[jj] LEDturn(atnoselec[kk-1],0) break else: # print ("Turn on selected LED") #### Here: disable writing to screen to suppress "Playihg WAVE..." kk=orderdiscov[elno] LEDturn(atnoselec[kk-1], 1) string='aplay discovery_of_'+elname[kk-1]+'_narration.wav > /dev/null' # Not working yet old_stdout=sys.stdout f=open(os.devnull,'w') sys.stdout=f os.system(string) sys.stdout=old_stdout LEDturn(atnoselec[kk-1],0) break # #------------------------SUBROUTINE TO PRESENT EL. IN ORDER OF NUCLEOSYN. # # print ' please try another option' def syn(): delay=0.2 bigbang=[1,2,3] # Only hydrogen, helium, and lithium sun=[2,6,7,8] # Sun makes He, C, N, and O, no significant B, Be, and it destroys Li supernova=[2] # Supernova makes all elements (really, not much above about 100, fermium for n in range (3,113): # Add all the elements above He with a few statements supernova.append(n) # This could go at the beginning of the whole program, note syn_name=["Big Bang","our Sun, over its life","a supernova"] for elno in range (0,112): # Turn off any LEDs from last run, if any selec=atnoselec[elno] LEDturn(selec,0) syn_no=0 # PLAY AN INTRODUC while True: os.system('clear') print(Fore.RED + Back.BLACK + Style.BRIGHT + syn_name[syn_no]) print(Fore.WHITE + Back.BLACK + 'Green button --> next event') print("Red button --> one earlier") print("Press amber to play narration") print("Press white button to exit") print(" and choose another program") print '' # n=raw_input() while True: # Simply poll the button switches until one is pressed time.sleep(0.0001) # reduce polling burden on CPU if GPIO.input(22)==1: # pin 22 is normally lo; green button; increment number of the set syn_no=(syn_no+1)%3 # print 'Formed in ',syn_name[syn_no] time.sleep(delay) break elif GPIO.input(15)==0: # pin 15 is normally hi; white button; leave this subroutine time.sleep(delay) return elif GPIO.input(18)==1: # pin 18 is normally lo; red button; decrement number of the set syn_no=(syn_no-1)%3 time.sleep(delay) break elif GPIO.input(16)==0: # pin 16 is normally hi; amber button; light LEDs & play narration if syn_no==0: # Run through H, He, Li made in Big Bang for jj in range (0,3): #Light LEDs and play narr. for 3 el. kk=bigbang[jj] LEDturn(atnoselec[kk-1],1) string='aplay big_bang_narration.wav' os.system(string) time.sleep(5) # Leave the display lit for 5 sec. for user to grasp it for jj in range (0,3): #Turn off these LEDs now kk=bigbang[jj] LEDturn(atnoselec[kk-1],0) break elif syn_no==1: for jj in range (0,4): #Light LEDs and play narr. for 4 el. kk=sun[jj] LEDturn(atnoselec[kk-1],1) string='aplay sun_narration.wav' os.system(string) time.sleep(5) # Leave the display lit for 5 sec. for user to grasp it for jj in range (0,4): #Turn off these LEDs now kk=sun[jj] LEDturn(atnoselec[kk-1],0) break elif syn_no==2: for jj in range (0,111): #Light LEDs and play narr. for 111 el. (or 92?) kk=supernova[jj] LEDturn(atnoselec[kk-1],1) string='aplay supernova_narration.wav' os.system(string) time.sleep(5) # Leave the display lit for 5 sec. for user to grasp it for jj in range (0,111): #Turn off these LEDs now kk=supernova[jj] LEDturn(atnoselec[kk-1],0) break # ------------------SUBROUTINE TO PRESENT THE ELEMENTS IN ORDER OF ABUNDANCE IN EARTH'S CRUST def abun(): os.system('clear') for elno in range (0,112): # Turn off any LEDs from last run, if any selec=atnoselec[elno] LEDturn(selec,0) elno=0 delay=0.2 string='aplay introEC_narration.wav' # n=raw_input() while True: os.system('clear') print(Fore.WHITE + Back.BLACK + Style.BRIGHT + "Elements in order of abundance") print("In Earth's crust") kk=elabun_atno[elno] string='Number '+str(elno+1)+' in abundance, '+elname[kk-1] print (Fore.RED + string) print(Fore.WHITE + Back.BLACK + 'Green button --> next element') print("Red button --> one earlier") print("Press amber to play narration") print("Press white button to exit") print(" and choose another program") print '' while True: # Simply poll the button switches until one is pressed time.sleep(0.0001) # reduce polling burden on CPU if GPIO.input(22)==1: # pin 22 is normally lo; green button; increment number of element elno=(elno+1)%78 print 'New elno=',elno time.sleep(delay) break if GPIO.input(18)==1: # pin 18 is normally lo; red button; decrement number of element elno=(elno-1)%78 print 'New elno=',elno time.sleep(delay) break if GPIO.input(16)==0: # pin 16 is normally hi; amber button; light LED & start narration kk=elabun_atno[elno] LEDturn(atnoselec[kk-1], 1) # print ("Turn on selected LED") ##### Here: disable writing to screen to suppress "Playihg WAVE..." # string='aplay '+elname[kk-1]+'_narration.wav > /dev/null' string='aplay '+elname[kk-1]+'EC_narration.wav' # print string # time.sleep(3) # old_stdout=sys.stdout # f=open(os.devnull,'w') # sys.stdout=f os.system(string) # sys.stdout=old_stdout LEDturn(atnoselec[kk-1], 0) break if GPIO.input(15)==0: # pin 15 is normally hi; white button; leave this subroutine string='aplay closingEC_narration.wav' os.system(string) return # "break" only gets us out of the inner while True loop; "return" gets us back to MAIN() # #----------------ABUNDANCE IN HUMAN BODY------------------------------ # def hb(): os.system('clear') for elno in range (0,112): # Turn off any LEDs from last run, if any selec=atnoselec[elno] LEDturn(selec,0) N_HBabun=14 # Ultimately, we'll have 40 narrations elno=0 delay=0.2 while True: os.system('clear') print(Fore.WHITE + Back.BLACK + Style.BRIGHT + "Elements in order of abundance") print("In the human body") kk=HBabun_atno[elno] string='Number '+str(elno+1)+' in abundance, '+elname[kk-1] print (Fore.RED + string) print(Fore.WHITE + Back.BLACK + 'Green button --> next element') print("Red button --> one earlier") print("Press amber to play narration") print("Press white button to exit") print(" and choose another program") print '' while True: if GPIO.input(22)==1: elno=(elno+1)%N_HBabun print 'New elno=',elno time.sleep(delay) break if GPIO.input(18)==1: elno=(elno-1)%N_HBabun print 'New elno=',elno time.sleep(delay) break if GPIO.input(16)==0: kk=HBabun_atno[elno] LEDturn(atnoselec[kk-1],1) string='aplay '+elname[kk-1]+'HB_narration.wav' # Old stuff for test 346, to test APLAY # YouTube channel: youtube.com/louispate os.system(string) LEDturn(atnoselec[kk-1], 0) break if GPIO.input(15)==0: return # #------------------------MAIN PROGRAM--------------------------------- # # This is the main program os.system('clear') # Start with a clean screen for elno in range (0,112): # Turn off any LEDs from last run, if any selec=atnoselec[elno] LEDturn(selec,0) linenow=0 # This is index of the program to be run (0 = by atomic number, ...) numprog=5 # We currently have "only" 4 program choices...but each was very much work! delay=0.4 linetext=['']*4 linetext=[' --Atomic number',' --Discovery',' --Synthesis in universe'] linetext=linetext+[" --Abundance in Earth's crust"," --Abundance in Human Body"] print(Style.BRIGHT + '') while True: os.system('clear') print(Style.BRIGHT + Back.BLACK + Fore.WHITE + "Press a key and then ENTER\nto advance the highlighted row " ) print (Style.BRIGHT + "Green moves down, Red moves up") print ("When your choice is highlighted,") print (" press amber to start") print ("Elements in order of:") for line in range (0,5): if line==linenow: print(Fore.BLUE + Style.BRIGHT + Back.WHITE + linetext[line]) else: print(Fore.WHITE + Back.BLACK + Style.BRIGHT + linetext[line]) print (Fore.WHITE + Back.BLACK + '') print (Fore.RESET + Style.RESET_ALL) # n=raw_input() while True: # Simply poll the button switches until one is pressed time.sleep(0.0001) # reduce polling burden on CPU if GPIO.input(22)==1: # pin 10 is normally lo; green button; increment number of subroutine linenow=(linenow+1)%numprog time.sleep(delay) break elif GPIO.input(18)==1: # pin 8 is normally lo; red button; decrement number of subroutine linenow=(linenow-1)%numprog time.sleep(delay) break elif GPIO.input(16)==0: # pin 5 is normally hi; amber button; start the chosen subroutine if linenow==0: atno() break elif linenow==1: discov() break elif linenow==2: syn() break elif linenow==3: abun() break elif linenow==4: hb() break else: # This can't happen anymore, now that all the subroutines have been written print '\nThe program number "',progname[prognum],'" is not yet active\n' time.sleep(2) # Let's print this for 2 sec., then clear the screen continue # print('') # We do not want the option below, which is to exit the whole program; it would be tedious to # restart it without a keyboard and mouse already attached and with a tiny screen to view # elif GPIO.input(15)==0: # pin 3 is normally hi; white button; exit the program # break # Exit the python program entirely # # # Still to consider adding: # * Random display after x minutes idle time # * Intro and closing for all subroutines (abundance has location tagged) # * HB narrations for 20 more elements # * Wiring of the full logic board, of course --> Done, March 2016, with much testing # afterward. Found in Nov. 2016 that one latch, G, was bad or miswired; moved # connections to latch O. # Found on 3 Dec. 16 that there was still a lot of # migration from old test board to do: (1) In atno() and in abun() change from # GPIO pin 10 for green button to pin 22; (2) Critical!: vs. old board with 16 # elements in same order as selectors, we have to use atnoselec array to set # which selector is used for each element; (3) Vs. test latches (16-pin, 3.3 V): # the enable level is hi (1), not lo (0); change calls to LEDturn()