GPIO Code Problem

Could someone help me, please?

My problem is when I call a GPIO function it freezes the program like it is in some endless loop. The following line of code shows how I am calling the GPIO functions.

GPIO.output(Run_Pin,GPIO.HIGH)

I tracked the problem to the GPIO function ( both input and output) by commenting out the GPIO functions; the code runs correctly and does not freeze.
.
Yes, I import RPi.GPIO as GPIO and set up the GPIO pis correctly.

Thank you for sharing your wisdom with me. :grinning: :grinning:

Hi,

I take it this is a Rasberry you’re working on? Referencing this tutorial:

https://sourceforge.net/p/raspberry-gpio-python/wiki/BasicUsage/

Should Run_Pin be the pin number? As in the tutorial:

To set the output state of a GPIO pin:

GPIO.output(channel, state)  # channel refers to the pin #

What does Run_Pin reference or which pin does it reference?

So, you would set the pin as:

GPIO.output(channel, GPIO.HIGH)   # set the channel pin high

However, you would first have to set up the pin as either an input or an output.

Yes, you are correct I am using Rasberry PI 3B running Python. My project is a stepper motor controller. Since Python can not handle the micro-second timing needed for the proper operation of the motor I am using a logic controller ( Adafruit ItsyBitsy 32u4 - 3V) to provide the required timing. I am using the Rasberry GPIO pins to tell the logic controller what task to run. Plus a GUI user interface to select what function the user wants to run.

Right now the Rasberry is not connected to the logic controller, so I can ensure the Python code is working ( which is not and need help.

The fowling code shows that I have set up the GPIO correctly Run_Pin is defined as GPIO pin 23 and set up as an output


#=== Set GPIO Pins ===
Toy_Sel_Pins = (14, 15)
Abort_Pin =18
Run_Pin = 23
DIR_Pin = 24
IntensitySelect_Pins = (1, 7, 8, 25)   # Tell contrler ieinIntensity value
Busy_Pin = 12
BUZZER_Pin = 16
PWR_LED_Pin = 20
Ready_LED_Pin = 21
PUSH_BUTTON_Pin = 37



#Initize the GPIO pins		
GPIO.setmode(GPIO.BCM)
GPIO.setup(BUZZER_Pin, GPIO.OUT)
GPIO.setup(IntensitySelect_Pins, GPIO.OUT)
GPIO.setup(Ready_LED_Pin, GPIO.OUT)
GPIO.setup(PWR_LED_Pin, GPIO.OUT)
GPIO.setup(PUSH_BUTTON_Pin, GPIO.IN)
GPIO.setup(Busy_Pin, GPIO.IN)
GPIO.setup(Run_Pin, GPIO.OUT)
GPIO.setup(DIR_Pin , GPIO.OUT)
GPIO.setup(Abort_Pin, GPIO.OUT) 
GPIO.setup(Toy_Sel_Pins, GPIO.OUT)



def Run_Task():
    global Run_Pin
    global Busy_Pin
    global Stop_LED_Flashing
    global Abort_Pin

# First start the LED flashing thread
#	Stop_LED_Flashing = False
#	Ready_LED_Flashing = Thread(Set_Ready_LED_Flashing)
#	Ready_LED_Flashing.daemon = True
#	Ready_LED_Flashing.start()

# Debug Statement
    print("Run_Task Telling controller to excute task")
    print(" TEST TEST TEST")
    print(" TEST TEST TEST TEST")

# Tell controler to excute the task
    GPIO.output(Run_Pin,GPIO.HIGH) 

#Debug Statement
    print(" Run Pin >> " , GPIO.input(Run_Pin))
    print(" Checking Busy_Pin >>",GPIO.input(Busy_Pin),)

# Wait until stepper controler has started the task
    while(not GPIO.input(Busy_Pin)): # Wait for controller to start tesk

#Debug Statement
        print("Waiting Busy Pin >> false")
        sleep(1) #Wait 1 mS to allow logic controler time to respond

# Now wait until stepper controler has finish the task

#Debug Statment
    print(" Waiting for Busy_Pin to return to false", GPIO,input(Busy_Pin) )	
    while(GPIO,input(Busy_Pin)):
#Debug Statement
        print("Waiting Busy Pin >> True")
        sleep(1)
		
 Control has finshed so return Run pin to false to telling the controller the PI has 	
    GPIO.output(Run_Pin, False)	
    GPIO.output(Abort_Pin, False)
    Stop_LED_Flashing = True

# Debug Statement
    print("Controller comleted task Retuning")

#**********************************************

If you want to see the entire code here is Dropbox link o it

SmakerCode_V8

To truly zoom in on whether it is the IO pin or not, you can create a simple
empty while loop with just the IO pin script by where you toggle the pin between the two states continuously. Something roughly like this (start with one pin only for simplicity and then build from there):

# Pin set-up code here (only include the code for the desired pin)
-
-
-
while True:
    
    GPIO.output(channel, GPIO.HIGH) 
    GPIO.output(channel, GPIO.LOW) 
    GPIO.output(channel, GPIO.HIGH) 
    GPIO.output(channel, GPIO.LOW) 

Do you have access to an o-scope? If not, how are you verifying that the pin is toggling and at the required frequency?

Correction:

Ok, so you’re really not toggling the pin at a frequency. I take it the Rasberry pins provide a binary address (let’s say three pins) 0b011, and the logic controller, based on this input read, ... tell the logic controller what task to run. Ok. Understood. But testing it as per the recommended script above is still valid. We can test for all of the output pins that are providing the code to the controller on an individual basis. If verified, then we can move to the next verification step.

Yes, you are very correct on the controller interface’ I set up the task info then tells the controller to run taken by setting Run_Pin high. The controller sets busy pin high telling Python it is busy doing a task. Python then waits for the Busy_Pin to go low to continue the rest of program…

OK, the following test code hangs up on the first GPIO operation. Also, the pin does not go high!!!

import RPi.GPIO as GPIO
from time import sleep

GPIO.setmode(GPIO.BCM)
GPIO.setup(14, GPIO.OUT)

while(True):
    print("High")
    GPIO.output(14,GPIO.HIGH)
    sleep(500)
    print("LOW")
    GPIO.output(14,GPIO.LOW)
    sleep(500)

Can you try:

GPIO.setmode(GPIO.BOARD)

From the tutorial (in section Pin numbering):
The advantage of using this numbering system is that your hardware will always work, regardless of the board revision of the RPi.

OK. I have done your suggested using BOARD with the same result.

Can you try without using the timer and sleep function. Let’s test it with bare bones.

Comment out all references.

OK, commenting out the sleep statement it ran as expected.
Back to the original code, there are no sleep operations.

You tested pin 14. Can you retest pin 23 since this was the pin in question. Also check physically if this pin is routed correctly to the logic controller. That is, if this pin goes to, say, pin 25 of the controller, check and verify this.

By the way, the unit of the argument to the timer is in seconds and not milliseconds. So, 500 refers to 500 seconds (8.3 minutes) and not 0.5 s. To test it with the timer you could have used:

sleep(1)  # One second increments

or, if you wanted half a second increments:

sleep(0.5)

I have tested several pins and they all do not output a voltage. I have even hooked up an LED and it does not turn on even with 2-second delay.

As for sleep, I thought it was in milliseconds. Maybe I am thinking of a delay instead.

Why is this test work but not in the run function?

Depending on the internals of the GPIO module of the Rasberry, you might have to add a pull-up resistor to each of the pins. That is, if the GPIOs have an open-collector configuration without the option of providing one internally ,then you will have to provide your own external pull-up resistor.

See the following figure

Take a look a the Rasberry datasheet or user manual for details.

If a pull-up resistor is provided by default, then check that there are no shorts to whatever it is you’re connecting it to. If you have a multimeter, disconnect the pin from everything and test it by checking the voltage at that pin (just set the pin to HIGH without toggling it for test purposes).

Always ensure that there is a current limiting resistor in series so the LED (make sure it is placed with the correct polarity) does not burn up and provide a different kind of light show. :boom:

Did you leave it as(?):

GPIO.setmode(GPIO.BOARD)

You shouldn’t connect the raspberry pi pin directly to the LED and then to ground without a current-limiting resistor.

fyi …

I briefly looked your script from the link that you provided on GIT. I would recommend replacing these lines:

from tkinter import *
from tkinter import _setit

with:

import tkinter as tk

Then, all the names from this library that you are using would need to be prefixed with tk. As in:

tk.label ... etc.
tk._setit ... etc.

This will avoid name collision with native names that you may have or add at a later date. There was actually a user last week whose script was malfunctioning and it was due to name collision.

1 Like

Since the argument to the sleep function is in seconds instead of milliseconds, you will want to update this line (and others with units in seconds):

sleep(1) #Wait 1 mS to allow logic controler time to respond

to 

sleep(0.001) #Wait 1 mS to allow logic controller time to respond

I think this might be the problem (round these neck of the woods it is referred to as a typo, I reckon’ :wink: ):

while(GPIO,input(Busy_Pin)):  # has a comma instead of a period

update to:

while(GPIO.input(Busy_Pin)):
2 Likes

Good morning :smiley: :smiley:

You would think that with over twenty years of experience, I should know to connect the DVM ground lead to the circuit ground to get an acrate voltage… DADADA (LOL). Once I connect the ground lead all the GPIO pins are working properly (High = 3.3V and LOW = 0 V).

I have changed from BCM to BOARD pin numbers.

I did not write the GUI so I will pass your tkinter suggestions to them.

Thank you for pointing out my syntax error.

Your correct on the sleep function being is in seconds instead of milliseconds. I think I was thinking in Arduno delay fnctuin my bad.

I discovered a possible clue as to why the Run_Task function is crashing. One of the logic controllers function is called Alignment(). In this function, there are GPIO functions that do not crash. Also, this function calls another function called ChangeToyType, which also has GPIO statements that do not crash. So why is the Run_Task function GPIOs crashing and locking up the program?

I have updated the source code. I changed from BCM to BOARD pin numbering. and other changes. The ChangeToyType function is at line 477 and the Alignment is at line 723.
SmakerCode_TST.py

If you want to enter values in milliseconds, you can. Just create a function off of the original as in:

from time import sleep, time

def delay_ms(time_ms):

    sleep(time_ms/1000)

start = time()
delay_ms(375)
elapsed = time() - start

print(f'Time elapsed in seconds: {round(elapsed, 3)} s')

I do not need milliseconds in the main script. I only use sleep to debug the code.

I think I found the error in the Run Task function. Yes, it is stuck in an endless loop tiring to read a GPIO (Busy_Pin) Since the controller is not hooked up there is no signal on that pin means it is floating. Commenting out the read GPIO pin the code runs properly. I just have to correct the logic flow of the program.

Thank you for sharing your great wisdom with me.