Python function return variable

Hello
using python-function i'm not able to get get the variable value

import sys
sys.path.append("/home/pi/.local/lib/python3.9/site-packages")
from pigpio_encoder.rotary import Rotary
import threading
import time
global my_counter
my_counter = 0

def sw_short():
    pass

def up_callback(counter):
    global my_counter
    if counter%40==0:
        my_counter+=1
        msg['payload'] = {'pos_x':my_counter}
        print(msg)
        #print(my_counter)

def down_callback(counter):
    global my_counter
    if counter%40==0:
        my_counter-=1
        msg['payload'] = {'pos_x':my_counter}
        return msg
        #return my_counter
        #print(my_counter)
    
def pippo():
    global my_counter
    print(my_counter)
    time.sleep(0.3)
    pippo()


my_rotary = Rotary(clk_gpio=13, dt_gpio=12,sw_gpio = 17)
my_rotary.setup_rotary( min=-1000000,
                        max=1000000,
                        debounce = 1,
                        up_callback=up_callback,
                        down_callback=down_callback,)
                    #rotary_callback=rotary_callback,
my_rotary.setup_switch(sw_short_callback=sw_short)
return msg

This is the code, i'm not able to desplay the value of my_counter

[
    {
        "id": "f23f10101329d95f",
        "type": "python-function",
        "z": "a2713db36e62f1e7",
        "name": "Encoder",
        "func": "import sys\nsys.path.append(\"/home/pi/.local/lib/python3.9/site-packages\")\nfrom pigpio_encoder.rotary import Rotary\nimport threading\nimport time\nglobal my_counter\nmy_counter = 0\n\ndef sw_short():\n    pass\n\ndef up_callback(counter):\n    global my_counter\n    if counter%40==0:\n        my_counter+=1\n        msg['payload'] = {'pos_x':my_counter}\n        print(msg)\n        #print(my_counter)\n\ndef down_callback(counter):\n    global my_counter\n    if counter%40==0:\n        my_counter-=1\n        msg['payload'] = {'pos_x':my_counter}\n        return msg\n        #return my_counter\n        #print(my_counter)\n    \ndef pippo():\n    global my_counter\n    print(my_counter)\n    time.sleep(0.3)\n    pippo()\n\n\nmy_rotary = Rotary(clk_gpio=13, dt_gpio=12,sw_gpio = 17)\nmy_rotary.setup_rotary( min=-1000000,\n                        max=1000000,\n                        debounce = 1,\n                        up_callback=up_callback,\n                        down_callback=down_callback,)\n                    #rotary_callback=rotary_callback,\nmy_rotary.setup_switch(sw_short_callback=sw_short)\nreturn msg\n# x = threading.Thread(target=pippo)\n# x.start()\n\n",
        "outputs": 1,
        "x": 220,
        "y": 100,
        "wires": [
            [
                "393990a61c77173e"
            ]
        ]
    }
]

Hard to test without the required hardware.
Function throws at least some error's so there's is happening something :wink:
Strip your code and see where it's going wrong.

If you installed node-red via the script, it gave you an option to install Pi specific nodes, one of which are the GPIO nodes if I am not mistaken, you can install them separately too. No need for external python scripts if you can do it all inside node-red.

i get no error, simply i never get the msg

i will try but i don't understand why if i run the script outside node-red i get the needed value, inside node-red i'm not able to get the needed value in the msg objects

when you run python are you using the -u parameter to ensure it flushes any results to the output ?

no i never put the -u, where i have to put it ?

image

this is what i see when i run the flow but i have no output

Ah sorry didn’t spot you were using a custom node. I usually just call python -u from an exec node

I remember that others have had problems using that node, as Dave suggests, you might be better using an exec node to call your script. If you do that make sure you put the full path to the script in the exec node.

Hello
Now i'm in this situation but no output:
image

inject

image

exec

Debug

image

Python code

import RPi.GPIO as GPIO
from time import sleep
 
counter = 10
 
Enc_A = 13  
Enc_B = 12  
 
 
def init():
    print("Rotary Encoder Test Program")
    GPIO.setwarnings(True)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(Enc_A, GPIO.IN)
    GPIO.setup(Enc_B, GPIO.IN)
    GPIO.add_event_detect(Enc_A, GPIO.RISING, callback=rotation_decode, bouncetime=10)
    return
 
 
def rotation_decode(Enc_A):
    global counter
    sleep(0.002)
    Switch_A = GPIO.input(Enc_A)
    Switch_B = GPIO.input(Enc_B)
 
    if (Switch_A == 1) and (Switch_B == 0):
        counter += 1
        print("direction -> ", counter)
        while Switch_B == 0:
            Switch_B = GPIO.input(Enc_B)
        while Switch_B == 1:
            Switch_B = GPIO.input(Enc_B)
        return
 
    elif (Switch_A == 1) and (Switch_B == 1):
        counter -= 1
        print("direction <- ", counter)
        while Switch_A == 1:
            Switch_A = GPIO.input(Enc_A)
        return
    else:
        return
def main():
    try:
        init()
        while(True) :
            sleep(1)
    except KeyboardInterrupt:
        GPIO.cleanup()
 
if __name__ == '__main__':
    main()

I really don't know why i never see any value in the debug.

Check all outputs of the exec node, set the debug nodes to show the full message.

Add some debug output to your script to see what is happening and what is not happening.

hello i start from easy test just for understand the problem
if i do so:


image

as you can see in the debug i have the return value
but how can do if the return value is inside a def
for example:

def test()
    msg = 'test'
   return test
while True:
    test()

it run but i don't have any return value

i have solved this issue doing this:

global pippo
def test():
    global pippo
    pippo = 'test'
    return pippo
while True:
    test()
    msg['payload'] = {'pippo':pippo}
    return msg

but i don't understand why in node-red i have the msg one time and not repeated.
But my big problem is this:

from pigpio_encoder.rotary import Rotary
global my_counter
my_counter = 0

def sw_short():
    pass

def up_callback(counter):
    global my_counter
    if counter%40==0:
        my_counter+=1
        print(my_counter)
        return my_counter

def down_callback(counter):
    global my_counter
    if counter%40==0:
        my_counter-=1
        print(my_counter)
        return my_counter
    

my_rotary = Rotary(clk_gpio=13, dt_gpio=12,sw_gpio = 17)
my_rotary.setup_rotary( min=-10000,
                        max=10000,
                        debounce = 1,
                        up_callback=up_callback,
                        down_callback=down_callback,)
                    #rotary_callback=rotary_callback,
my_rotary.setup_switch(sw_short_callback=sw_short)
msg['payload'] = {'my_counter':my_counter}
return msg

Always return
image
it return my_counter = 0 because he get the value from the beginning but not when the value change
can you tell me where is my mistake
Thanks

I am not at home in python, but aren't variables global by default if they are defined outside a function ? ie. can you remove all the "global" definitions ?

sorry guys but i really don't understand:

from pigpio_encoder.rotary import Rotary
global my_counter
my_counter = 0

def sw_short():
    pass

def up_callback(counter):
    global my_counter
    if counter%40==0:
        my_counter+=1
        print(my_counter)
        msg['payload'] = {'my_counter':my_counter}
        return msg

def down_callback(counter):
    global my_counter
    if counter%40==0:
        my_counter-=1
        print(my_counter)
        msg['payload'] = {'my_counter':my_counter}
        return msg
    

my_rotary = Rotary(clk_gpio=13, dt_gpio=12,sw_gpio = 17)
my_rotary.setup_rotary( min=-10000,
                        max=10000,
                        debounce = 1,
                        up_callback=up_callback,
                        down_callback=down_callback,)
                    #rotary_callback=rotary_callback,
my_rotary.setup_switch(sw_short_callback=sw_short)
msg['payload'] = {'my_counter':my_counter}
return msg

i get only the first msg object with my_counter = 0
then when i move the encoder in the node-red shell i get all the print message :
image
but i get no return object.

dear bakman2 in node-red if i never set as global the my_counter variable i get:
NameError: name 'my_counter' is not defined

Any help will be appreciated

Your script does the following:

  • set your counter variable to the value of 0
  • create an instance of Rotary and set a few properties of it
  • set your msg['payload'] to a value
  • return this msg

After the return command the script is terminated because there are no more commands. Therefore you get once the value of msg.

The two function (the callback functions for the Roraty object) will never have been called, because the script is finished before the Rotary object can fire any event.

I have solved in this way :

from pigpio_encoder.rotary import Rotary
global my_counter
my_counter = 0

def sw_short():
    pass

def up_callback(counter):
    global my_counter
    if counter%40==0:
        my_counter+=1
        #print(my_counter)
        msg['payload'] = {'my_counter':my_counter}
        #return msg
        node.send(msg)

def down_callback(counter):
    global my_counter
    if counter%40==0:
        my_counter-=1
        #print(my_counter)
        msg['payload'] = {'my_counter':my_counter}
        node.send(msg)
    

my_rotary = Rotary(clk_gpio=13, dt_gpio=12,sw_gpio = 17)
my_rotary.setup_rotary( min=-10000,
                        max=10000,
                        debounce = 1,
                        up_callback=up_callback,
                        down_callback=down_callback,)
                    #rotary_callback=rotary_callback,
my_rotary.setup_switch(sw_short_callback=sw_short)
#msg['payload'] = {'my_counter':my_counter}
#return msg

Regards

Hello Oliver
the lib used pigpio do in backgroud the work (treading etc...) but i have solved usin the nod.sed(msg)
regards

Okay, I see.
BTW: your problem was the fact, that callback functions cannot return anything by definition. So your solution is the right way.

Just linking in case you find this easier

1 Like