Legal Removal Request This form is for reporting content posted on the AB Electronics UK forums that you believe violates your personal legal rights or applicable local laws for your country. Post: Normally you wouldn't kill a thread directly as it may have some garbage collection to do which could result in memory leaks and crashing so the best way is to have a variable called exitRequested which can be set to True when you want the thread to exit. In your thread, you will need to check the exitRequested variable and manually end the thread by jumping to the end of the code in that function. I have written a small program based on the description of what you need. [pre][code]import time from threading import Thread from threading import Event import RPi.GPIO as GPIO from IOPi import IOPi bus1 = None runningThreads = [] # used to store a list of the running threads class State1Thread(Thread): exitRequested = False def run(self): print("Mode 1: midi_player") i = 0 while i < 5: print("Mode 1 running - " + str(i)) time.sleep(1) if self.exitRequested: break i = i + 1 # thread cleanup - run this before returning from the thread for t in runningThreads: if t.name == "State1": runningThreads.remove(t) return def exit(self): self.exitRequested = True print("Mode 1: exit") class State2Thread (Thread): exitRequested = False def run(self): self.hasStarted = True self.isRunning = True print("Mode 2: midi_maker") i = 0 while i < 5: print("Mode 2 running - " + str(i)) time.sleep(1) if self.exitRequested: break i = i + 1 # thread has finished so remote the thread from the runningThreads Arrary for t in runningThreads: if t.name == "State2": runningThreads.remove(t) return def exit(self): self.exitRequested = True print("Mode 2: exit") class State3Thread (Thread): exitRequested = False def run(self): self.hasStarted = True self.isRunning = True print("Mode 3: midi_live") i = 0 while i < 5: print("Mode 3 running - " + str(i)) time.sleep(1) if self.exitRequested: break i = i + 1 # thread has finished so remote the thread from the runningThreads Arrary for t in runningThreads: if t.name == "State3": runningThreads.remove(t) return def exit(self): self.exitRequested = True print("Mode 3: exit") def button_pressed(interrupt_pin): global bus1 """ this function will be called when GPIO 23 falls low """ # read the interrupt capture for port 0 and store it in variable intval intval = bus1.read_interrupt_capture(0) # compare the value of intval with the IO Pi port 0 # using read_port(). wait until the port changes which will indicate # the button has been released. # without this while loop the function will keep repeating. while (intval == bus1.read_port(0)): time.sleep(0.2) # loop through each bit in the intval variable and check if the bit is 1 # which will indicate a button has been pressed for num in range(0, 8): if (intval & (1 << num)): # print("Pin " + str(num + 1) + " pressed") if str(num + 1) == '1': return state0_pressed() elif str(num + 1) == '2': return state1_pressed() elif str(num + 1) == '3': return state2_pressed() elif str(num + 1) == '4': return state3_pressed() def state0_pressed(): print("Main Menu - stopping tasks") bus1.write_port(1, 0x01) # call exit for each thread in runningThreads for t in runningThreads: t.exit() def state1_pressed(): bus1.write_port(1, 0x04) # check if a thread is already running for state 1 for t in runningThreads: if t.name == "State1" and t.is_alive(): return # create a new state 1 thread and append it to the runningThreads array state = State1Thread() state.name = "State1" runningThreads.append(state) # start the thread state.start() def state2_pressed(): bus1.write_port(1, 0x10) # check if a thread is already running for state 2 for t in runningThreads: if t.name == "State2" and t.is_alive(): return # create a new state 2 thread and append it to the runningThreads array state = State2Thread() state.name = "State2" runningThreads.append(state) # start the thread state.start() def state3_pressed(): bus1.write_port(1, 0x40) # check if a thread is already running for state 3 for t in runningThreads: if t.name == "State3" and t.is_alive(): return # create a new state 3 thread and append it to the runningThreads array state = State3Thread() state.name = "State3" runningThreads.append(state) # start the thread state.start() def main(): """ Main program function """ global bus1 bus1 = IOPi(0x20) bus1.set_port_direction(1, 0x00) bus1.write_port(1, 0x00) bus1.set_port_pullups(0, 0xFF) bus1.set_port_direction(0, 0xFF) bus1.invert_port(0, 0xFF) bus1.set_interrupt_polarity(0) bus1.mirror_interrupts(0) bus1.set_interrupt_defaults(0, 0x00) bus1.set_interrupt_type(0, 0xFF) bus1.set_interrupt_on_port(0, 0xFF) bus1.reset_interrupts() # set the Raspberry Pi GPIO mode to be BCM GPIO.setmode(GPIO.BCM) # Set up GPIO 23 as an input. The pull-up resistor is disabled as the # level shifter will act as a pull-up. GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_OFF) # when a falling edge is detected on GPIO 23 the function # button_pressed will be run GPIO.add_event_detect(23, GPIO.FALLING, callback=button_pressed, bouncetime=300) input("Press enter to exit program \n") if __name__ == "__main__": main()[/code][/pre] At the top of the program is an array called runningThreads, this is used to store a list of the threads that are running. A thread can only be started once so you need to create a new instance of the thread each time you want it to start. There are three classes State1Thread, State2Thread, and State3Thread. These are where you would put the code that you want to run on each button press. Each class has two functions, the run function is called automatically when the thread is started. The exit function sets the exitRequested variable to True which you will need to monitor in your code so you know when to exit the thread early. There is a small amount of thread cleanup code that needs to be run before exiting a thread, it removes the current thread from the runningThreads array before calling return. Each button calls its own function, state0_pressed(), state1_pressed(), state2_pressed() and state3_pressed(). state0_pressed() loops through the runningThreads array and calls exit for each thread. This is the cleanest way of making all of the threads exit. For the other three functions, they first check to see if the thread for that function is in the runningThreads array and if it is currently alive. The for loop is needed to make sure you don't accidentally start more than one instance of the thread. If the thread is not running then it creates a new instance of the thread, gives it a name, appends it to runningThreads and starts it. I moved the GPIO code back into the main function as it does not need to be in its own thread. Using threads in python is fairly complicated but hopefully, this code will get you started with your program. Select the country where you are claiming legal rights. Albania Algeria American Samoa Andorra Angola Anguilla Antarctica Antigua and Barbuda Argentina Aruba Australia Austria Bahamas Bahrain Bangladesh Barbados Belarus Belgium Belize Benin Bermuda Bhutan Bolivia Bosnia And Herzegovina Botswana Bouvet Island Brazil British Indian Ocean Territory British Virgin Islands Brunei Bulgaria Burkina Faso Burundi Cambodia Cameroon Canada Canary Islands Cape Verde Cayman Islands Central African Republic Chad Channel Islands Chile Christmas Island Cocos (Keeling) Islands Colombia Comoros Congo Cook Islands Costa Rica Croatia Cuba Cyprus Czech Republic Denmark Djibouti Dominica Dominican Republic East Timor Ecuador Egypt El Salvador Equatorial Guinea Estonia Ethiopia Falkland Islands (Malvinas) Faroe Islands Federated States of Micronesia Fiji Finland France French Guiana French Polynesia French Southern Territories Gabon Gambia Georgia Germany Ghana Gibraltar Greece Greenland Grenada Guadeloupe Guam Guatemala Guyana Haiti Heard Island and McDonald Islands Honduras Hong Kong Hungary Iceland India Indonesia Ireland Israel Italy Jamaica Japan Jordan Kazakhstan Kenya Kiribati Kuwait Kyrgyzstan Laos Latvia Lesotho Liechtenstein Lithuania Luxembourg Macau Macedonia Madagascar Malawi Malaysia Maldives Mali Malta Marshall Islands Martinique Mauritania Mauritius Mayotte Mexico Micronesia, Federated States Of Moldova, Republic Of Monaco Mongolia Montenegro Montserrat Morocco Mozambique Myanmar Namibia Nauru Nepal Netherlands Netherlands Antilles New Caledonia New Zealand Nicaragua Niue Norfolk Island Northern Mariana Islands Norway Oman Palau Panama Papua New Guinea Paraguay Peru Philippines Pitcairn Poland Portugal Puerto Rico Qatar Reunion Romania Russia Rwanda Samoa San Marino Sao Tome and Principe Saudi Arabia Serbia Seychelles Singapore Slovakia Slovenia Solomon Islands South Africa South Georgia and the South Sandwich Islands South Korea Spain Sri Lanka St. Helena St. Kitts and Nevis St. Lucia St. Pierre and Miquelon St. Vincent and the Grenadines Suriname Svalbard and Jan Mayen Islands Swaziland Sweden Switzerland Syria Taiwan Tajikistan Tanzania Thailand Togo Tokelau Tonga Trinidad and Tobago Tunisia Turkey Turkmenistan Turks and Caicos Islands Tuvalu U.S. Virgin Islands Uganda Ukraine United Arab Emirates United Kingdom United States United States Minor Outlying Islands Uruguay Uzbekistan Vanuatu Vatican City Venezuela Vietnam Wallis and Futuna Islands Western Sahara Yemen Yugoslavia Zambia What legal issue or problem do you wish to report? Please select Privacy / Erasure under GDPR Defamation Intellectual Property Hate Speech Other Please enter the following information so we can process your report. Contact Name: Contact Email: Details of complaint: Submit Complaint