rickticktock
Posts: 25
Joined: Mon Aug 20, 2018 10:13 am

GPIO hindered by print statements.

Mon Mar 25, 2019 3:40 pm

I say chaps,
Here is a snippet of code:
Note that I had print statements and a colourful display to help get this right, but they caused the problems. The printed result and the display said it was all working fine, but an oscilloscope on the GPIO pins told another story, of missed pulses. After I commented all the monitoring stuff out, it worked fine. I expected some delays when printing, but not GPIO just not responding. Is this a known problem?
Note that I use 74HCT logic at 5V, because the input threshold is 1.2V, like old-skool TTL, and is a better match for the GPIO levels. It's not driving the other way; I would use potential dividers of course.

Code: Select all

                        for p in range(0, 25):
                            #x=(p%5)
                            #y=(p//5)
                            #a[x,y]=phi[p]%16  #the 5x5 array now has thevalues in it which are rolled over
                            #pt0=Point(x*100,y*100)
                            #pt1=Point((x+1)*100,(y+1)*100)
                            #square=Rectangle(pt0,pt1)
                        #square.setFill(color_rgb(rval,gval,bval))
                            #c=phi[p]%16        
                            #square.setFill(color_rgb(chroma[3*c],chroma[3*c+1],chroma[3*c+2]))
                            #square.draw(win)
    
   #The values are pruned to the last 4 bits and sent down the shift registers to the counters.
#logic levels are inverted because GPIO outputs drive 74HCT04 invertors.
                            z=BitArray(uint=phi[p]%16,length=4)
                            #print (z.bin)
                            #print (z[0],z[1],z[2],z[3])
                            if p==12:
                                continue #element 12 always has zero hard wired
                            if z[0]:
                                GPIO.output(36, GPIO.LOW)
                                #print ('DATAon')# Turn on
                            else:
                                GPIO.output(36, GPIO.HIGH)
                                #print ('DATAoff')# Turn off
                            GPIO.output(38, GPIO.LOW) # Turn off, one short shift clock pulse 
                            GPIO.output(38, GPIO.HIGH)
                            #print ('clock') # clock
                            if z[1]:
                                GPIO.output(36, GPIO.LOW)
                                #print ('DATAon')# Turn on
                            else:
                                GPIO.output(36, GPIO.HIGH)
                                #print ('DATAoff')# Turn off
                            GPIO.output(38, GPIO.LOW) # Turn off, one short shift clock pulse
                            GPIO.output(38, GPIO.HIGH)
                            #print ('clock') # clock
                            if z[2]:
                                GPIO.output(36, GPIO.LOW)
                                #print ('DATAon')# Turn on
                            else:
                                GPIO.output(36, GPIO.HIGH)
                                #print ('DATAoff')# Turn off
                            GPIO.output(38, GPIO.LOW) # Turn off, one short shift clock pulse
                            GPIO.output(38, GPIO.HIGH)
                            #print ('clock') # clock
                            if z[3]:
                                GPIO.output(36, GPIO.LOW)
                                #print ('DATAon')# Turn on
                            else:
                                GPIO.output(36, GPIO.HIGH)
                                #print ('DATAoff')# Turn off
                            GPIO.output(38, GPIO.LOW) # Turn off, one short shift clock pulse
                            GPIO.output(38, GPIO.HIGH)
                            #print ('clock') # clock
                        GPIO.output(40, GPIO.HIGH) # Turn off, one short pulse to load data from shift register into counters
                        GPIO.output(40, GPIO.LOW)
                        #print ('LOAD')
                        time.sleep(0.5)
                        #print('Reading MCP3008 values, press Ctrl-C to quit...')
                        value = mcp.read_adc(0)
    # Print the ADC values.
                        print (value)
                            # Pause for half a second.

This test script runs nicely, giving 4us pulses with 4us space before the pulse on the next pin:

Code: Select all

import RPi.GPIO as GPIO # Import Raspberry Pi GPIO library

#logic levels are inverted because GPIO outputs drive 74HCT04 invertors.
GPIO.setwarnings(False) # Ignore warning for now
GPIO.setmode(GPIO.BOARD) # Use physical pin numbering
GPIO.setup(36, GPIO.OUT, initial=GPIO.HIGH) # Set pin 36 to be an output pin and set initial value to low (off)

GPIO.setup(38, GPIO.OUT, initial=GPIO.HIGH) #  Set pin 38 to be an output pin and set initial value to low (off)
GPIO.setup(40, GPIO.OUT, initial=GPIO.LOW) #  Set pin 40 to be an output pin and set initial value to low (off)
while True:
    GPIO.output(36, GPIO.LOW) # Turn off, one short pulse
    GPIO.output(36, GPIO.HIGH)
    GPIO.output(38, GPIO.LOW) # Turn off, one short pulse
    GPIO.output(38, GPIO.HIGH)
    GPIO.output(40, GPIO.LOW) # Turn off, one short pulse
    GPIO.output(40, GPIO.HIGH)

[moderator added code tags]

rickticktock
Posts: 25
Joined: Mon Aug 20, 2018 10:13 am

Re: GPIO hindered by print statements.

Mon Mar 25, 2019 3:43 pm

The indents didn't paste across for some reason.

User avatar
B.Goode
Posts: 10191
Joined: Mon Sep 01, 2014 4:03 pm
Location: UK

Re: GPIO hindered by print statements.

Mon Mar 25, 2019 3:46 pm

rickticktock wrote:
Mon Mar 25, 2019 3:43 pm
The indents didn't paste across for some reason.
The forum Code tag markup, inserted by the Code button fifth from the left in the top bar, will rectify this. It can be applied to your code retrospectively.

User avatar
scruss
Posts: 3155
Joined: Sat Jun 09, 2012 12:25 pm
Location: Toronto, ON
Contact: Website

Re: GPIO hindered by print statements.

Mon Mar 25, 2019 4:08 pm

Screen I/O can be extremely slow relative to realtime GPIO port access, so you may need a separate process or even external microcontroller to manage the critical timings.
‘Remember the Golden Rule of Selling: “Do not resort to violence.”’ — McGlashan.
Pronouns: he/him

pcmanbob
Posts: 9298
Joined: Fri May 31, 2013 9:28 pm
Location: Mansfield UK

Re: GPIO hindered by print statements.

Mon Mar 25, 2019 4:20 pm

Or just edit your post and add the code tags manually

Add [code] at the top

code goes here

and [/code] at the bottom.

which is what I did to your code below

You also have to remember that assuming you are using raspbian, the OS is not a real time OS so it will stop running your program and go update the display , check the keyboard for input , read/write to the SD card etc, all in fractions of a second of course but it might be impacting on your timing.

rickticktock wrote:
Mon Mar 25, 2019 3:40 pm

Code: Select all

                        for p in range(0, 25):
                            #x=(p%5)
                            #y=(p//5)
                            #a[x,y]=phi[p]%16  #the 5x5 array now has thevalues in it which are rolled over
                            #pt0=Point(x*100,y*100)
                            #pt1=Point((x+1)*100,(y+1)*100)
                            #square=Rectangle(pt0,pt1)
                        #square.setFill(color_rgb(rval,gval,bval))
                            #c=phi[p]%16        
                            #square.setFill(color_rgb(chroma[3*c],chroma[3*c+1],chroma[3*c+2]))
                            #square.draw(win)
    
   #The values are pruned to the last 4 bits and sent down the shift registers to the counters.
#logic levels are inverted because GPIO outputs drive 74HCT04 invertors.
                            z=BitArray(uint=phi[p]%16,length=4)
                            #print (z.bin)
                            #print (z[0],z[1],z[2],z[3])
                            if p==12:
                                continue #element 12 always has zero hard wired
                            if z[0]:
                                GPIO.output(36, GPIO.LOW)
                                #print ('DATAon')# Turn on
                            else:
                                GPIO.output(36, GPIO.HIGH)
                                #print ('DATAoff')# Turn off
                            GPIO.output(38, GPIO.LOW) # Turn off, one short shift clock pulse 
                            GPIO.output(38, GPIO.HIGH)
                            #print ('clock') # clock
                            if z[1]:
                                GPIO.output(36, GPIO.LOW)
                                #print ('DATAon')# Turn on
                            else:
                                GPIO.output(36, GPIO.HIGH)
                                #print ('DATAoff')# Turn off
                            GPIO.output(38, GPIO.LOW) # Turn off, one short shift clock pulse
                            GPIO.output(38, GPIO.HIGH)
                            #print ('clock') # clock
                            if z[2]:
                                GPIO.output(36, GPIO.LOW)
                                #print ('DATAon')# Turn on
                            else:
                                GPIO.output(36, GPIO.HIGH)
                                #print ('DATAoff')# Turn off
                            GPIO.output(38, GPIO.LOW) # Turn off, one short shift clock pulse
                            GPIO.output(38, GPIO.HIGH)
                            #print ('clock') # clock
                            if z[3]:
                                GPIO.output(36, GPIO.LOW)
                                #print ('DATAon')# Turn on
                            else:
                                GPIO.output(36, GPIO.HIGH)
                                #print ('DATAoff')# Turn off
                            GPIO.output(38, GPIO.LOW) # Turn off, one short shift clock pulse
                            GPIO.output(38, GPIO.HIGH)
                            #print ('clock') # clock
                        GPIO.output(40, GPIO.HIGH) # Turn off, one short pulse to load data from shift register into counters
                        GPIO.output(40, GPIO.LOW)
                        #print ('LOAD')
                        time.sleep(0.5)
                        #print('Reading MCP3008 values, press Ctrl-C to quit...')
                        value = mcp.read_adc(0)
    # Print the ADC values.
                        print (value)
                            # Pause for half a second.
This test script runs nicely, giving 4us pulses with 4us space before the pulse on the next pin:

Code: Select all

import RPi.GPIO as GPIO # Import Raspberry Pi GPIO library

#logic levels are inverted because GPIO outputs drive 74HCT04 invertors.
GPIO.setwarnings(False) # Ignore warning for now
GPIO.setmode(GPIO.BOARD) # Use physical pin numbering
GPIO.setup(36, GPIO.OUT, initial=GPIO.HIGH) # Set pin 36 to be an output pin and set initial value to low (off)
GPIO.setup(38, GPIO.OUT, initial=GPIO.HIGH) #  Set pin 38 to be an output pin and set initial value to low (off)
GPIO.setup(40, GPIO.OUT, initial=GPIO.LOW) #  Set pin 40 to be an output pin and set initial value to low (off)
while True:
    GPIO.output(36, GPIO.LOW) # Turn off, one short pulse
    GPIO.output(36, GPIO.HIGH)
    GPIO.output(38, GPIO.LOW) # Turn off, one short pulse
    GPIO.output(38, GPIO.HIGH)
    GPIO.output(40, GPIO.LOW) # Turn off, one short pulse
    GPIO.output(40, GPIO.HIGH)
    
We want information… information… information........................no information no help
The use of crystal balls & mind reading are not supported

User avatar
joan
Posts: 14887
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: GPIO hindered by print statements.

Mon Mar 25, 2019 4:25 pm

What pulses were missed? A print would add a delay between the GPIO level changes, it would not stop the changes.

User avatar
scruss
Posts: 3155
Joined: Sat Jun 09, 2012 12:25 pm
Location: Toronto, ON
Contact: Website

Re: GPIO hindered by print statements.

Mon Mar 25, 2019 4:56 pm

Are you manually twiddling the bits on a shift register, such as a 74HC595? You probably want to avoid print delays in strobing bits, but they are fairly forgiving. Maybe try something like this (nicked from The Humble Shift Register):

Code: Select all

def shiftout(byte):
  GPIO.output(PIN_LATCH, 0)
  for x in range(8)
    GPIO.output(PIN_DATA, (byte >> x) & 1)
    GPIO.output(PIN_CLOCK, 1)
    GPIO.output(PIN_CLOCK, 0)
  GPIO.output(PIN_LATCH, 1)
(and yes, labelling the function of each pin in your code makes it way easier for you to understand.)
‘Remember the Golden Rule of Selling: “Do not resort to violence.”’ — McGlashan.
Pronouns: he/him

rickticktock
Posts: 25
Joined: Mon Aug 20, 2018 10:13 am

Re: GPIO hindered by print statements.

Tue Mar 26, 2019 10:54 am

I say chaps,
Thank you all for your useful responses. The effect I'm getting is that pulses are forgotten altogether while printing is in process. I might try a small "sleep" after each "print". Absolute timing is not important here, the shifting in of data just advances by the shift_clock, then, after the 96 bits are in, the "load" pulse does the next thing. Timing critical stuff is all hardware and a xtal oscillator. I guarding against, and looking for, line ringing, power supply bounce etc, hence the use of buffering invertors at the end of the ribbon cable from the pi, and a ground-grid. (Means I can get away without a ground plane so 2-layers only PCB) There's nothing like a decent Tek 'scope!
At least I've got the basic logic working now so I can get on with the more clever stuff, but it would be nice to get the coloured squares display going. I'll try separating that out from the main loop.
I take it that GPIO outputs have a suitable resistance which absorbs reflections, which is gratifying.
TTFN

hippy
Posts: 7459
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: GPIO hindered by print statements.

Tue Mar 26, 2019 2:10 pm

rickticktock wrote:
Tue Mar 26, 2019 10:54 am
The effect I'm getting is that pulses are forgotten altogether while printing is in process.
It's not clear what you mean by "forgotten", but the pulses won't happen while the program is executing print statements, or when something else takes time away from the executing program. This is expected and predictable behaviour.

Return to “Python”