Hi. This is a tad embarrassing, but I'm having trouble with this apparently basic task. It seems that I'm missing something obvious in regards to returning and unpacking multiple values from a function.
There may be other issues with the below code, but for now I'm addressing this particular issue.
from machine import PWM, ADC, Pin import utime import math xAxisJoyPin = ADC(27) yAxisJoyPin = ADC(26) # Outputs to 2 IBT-2 h-bridge motor controllers RFpwmPin = PWM(Pin(6)) #RF = Right Forward RBpwmPin = PWM(Pin(8)) #RB = Right Backward LFpwmPin = PWM(Pin(7)) LBpwmPin = PWM(Pin(9)) # Set PWM frequency high in order to limit motor noise RFpwmPin.freq(10000) RBpwmPin.freq(10000) LFpwmPin.freq(10000) LBpwmPin.freq(10000) # Global variables joyMin = 0 joyMax = 65535 speedMin = 0 speedMax = int(65535 * 0.75) joyCentre = int(joyMax / 2) joyDeadZone = 4500 # (0-65535) joyCentrePlusDZ = joyCentre + joyDeadZone joyCentreMinusDZ = joyCentre - joyDeadZone RFmotorSpeed = 0 RBmotorSpeed = 0 LFmotorSpeed = 0 LBmotorSpeed = 0 # Below function code mostly copied from https://www.instructables.com/Joystick-to-Differential-Drive-Python/ def joystickToDiff(x, y, joyMin, joyMax, speedMin, speedMax): z = math.sqrt(x * x + y * y) rad = math.acos(math.fabs(x) / z) angle = rad * 180 / math.pi tcoeff = -1 + (angle / 90) * 2 turn = tcoeff * math.fabs(math.fabs(y) - math.fabs(x)) turn = round(turn * 100, 0) / 100 mov = max(math.fabs(y), math.fabs(x)) if (y > joyCentre): functOutLeft = mov functOutRight = turn elif (y < joyCentre): functOutRight = mov functOutLeft = turn return rightOut, leftOut while True: x = xAxisJoyPin.read_u16() y = yAxisJoyPin.read_u16() utime.sleep(0.01) # Zero point of joystick tends to jump around. Perhaps some electronic solution might be better? if x < 1000: x = 0 if y < 1000: y = 0 # Print for analysis print ("xAxis:", x, "yAxis:", y, end=' ') print ("RF:", RFmotorSpeed, "LF:", LFmotorSpeed, end=' ') print ("RB:", RBmotorSpeed, "LB:", LBmotorSpeed) # If joystick is in centre dead zone, motors off, return to top of loop # if ((x > joyCentreMinusDZ or x < joyCentrePlusDZ) and (y > joyCentreMinusDZ or y < joyCentrePlusDZ)): # RFmotorSpeed = 0 # RBmotorSpeed = 0 # LFmotorSpeed = 0 # LBmotorSpeed = 0 # continue # Send inputs to joystickToDiff function for processing joystickToDiff(x, y, joyMin, joyMax, speedMin, speedMax) # Save outputs from joystickToDiff function leftOut, rightOut = joystickToDiff() # Divide the 2 processed variables into 4 (relative to joystick position) # to send to motor controller inputs if y < joyCentreMinusDZ: if x < joyCentreMinusDZ: LBmotorSpeed = leftOut if x > joyCentrePlusDZ: LFmotorSpeed = leftOut if y > joyCentrePlusDZ: if x < joyCentreMinusDZ: RBmotorSpeed = rightOut if x > joyCentrePlusDZ: RFmotorSpeed = rightOut # Send PWM signals to motor controllers RFpwmPin.duty_u16(RFmotorSpeed) RBpwmPin.duty_u16(RBmotorSpeed) LFpwmPin.duty_u16(LFmotorSpeed) LBpwmPin.duty_u16(LBmotorSpeed)
I'm getting the message "TypeError: function takes 6 positional arguments but 0 were given" regarding the line
leftOut, rightOut = joystickToDiff()
which confuses me because I believe I've already sent the input arguments to the function with the line
joystickToDiff(x, y, joyMin, joyMax, speedMin, speedMax)
@dubbadan The eror message is right, I don't know how to explain it better, the function needs 6 inputs, you gave it 0.
I'm getting the message "TypeError: function takes 6 positional arguments but 0 were given" regarding the line
leftOut, rightOut = joystickToDiff()
The second line where you have 6 parameters is correct, but you can only return a single value. It can be a pointer to a structure, but in modern programming conventions that is a sure sign of a poor design.
At a 15 second glance, there are dozens of errors, a lot of the code is of unknown syntax.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
Hi @dubbadan,
In general, the 'full set' of arguments must be passed to a function on every call ... it does not 'remember' you sent them earlier.
Admittedly, some languages allow the programmer to make functions with default values that get substituted if a call is made to the function with less than the full set of arguments.
And also some languages allow the same function name to be defined more than once, each time with a different set of parameter types, and the compiler figures out which one is being called by matching the calling argument types to the parameter types.
Both of these cases imply the function definition is either more 'complex' or there is more than function definition with the same function name. I can't see either applying to the listed code.
So, I think you will need the full set of arguments every time.
Best wishes, Dave
Thanks for the patient replies.
So, I think you will need the full set of arguments every time.
The eror message is right, I don't know how to explain it better, the function needs 6 inputs, you gave it 0.
Forgive my noobiness, but what I thought I was doing with this line
leftOut, rightOut = joystickToDiff()
was retrieving the function outputs, not sending it input arguments. What I'm trying to work out is how I go about retrieving and unpacking the function outputs.
@dubbadan It happens in a single line, but there will only be one returned value.
From the reference manual, see pic.
EDIT: I just noticed its Python. I don't know python, so ignore what I said.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
Thanks for that reference, I have read that but also have read that it is possible to return more than one value from a function, eg via a tuple, list or dict.
Hi @dubbadan,
Python is not my forte either, but you can return more than one value ... however, you need to do it 'at the same time' as when you call it with the full set of arguments.
1st Google response I got is https://note.nkmk.me/en/python-function-return-multiple-values/ which kind of shows the answer .. if you don't like that one, there are plenty more for you to find yourself.
Best wishes, Dave
@dubbadan First learn to use the reply link so you cause an email to be sent to them to let them know a reply was posted.
That may be in Python, I don't know Python. In my decades of professional experience, we avoided things like that as they were proven to raise more bug reports than simple bool or integer return values. If you are using python, don't tag me any more as I can't help you.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
Your code does not show any indentation which makes it hard to guess the intent and of course would not actually run as presented as the indentation is critical in python coding blocks.
I expect the particular line of code you mention giving you the error is really meant to get the return values from your function call on the previous line - e.g.
leftOut, rightOut = joystickToDiff(x, y, joyMin, joyMax, speedMin, speedMax)
But also you cannot put
if y < joyCentreMinusDZ:
if x < joyCentreMinusDZ:
LBmotorSpeed = leftOut
The first if has now 'if' statements to perform and the second if fails, as all the rest of your code to indent e.g.
if x < joyCentreMinusDZ:
LBmotorSpeed = leftOut
Where you meaning to join the if y and if x with an 'and' or an 'or' ?
Maybe the lack of indentation is how the new coding works in this forum since its update the other day, lets see. I'll post a small snippet of your code with indents
def joystickToDiff(x, y, joyMin, joyMax, speedMin, speedMax): z = math.sqrt(x * x + y * y) rad = math.acos(math.fabs(x) / z) angle = rad * 180 / math.pi tcoeff = -1 + (angle / 90) * 2 turn = tcoeff * math.fabs(math.fabs(y) - math.fabs(x)) turn = round(turn * 100, 0) / 100 mov = max(math.fabs(y), math.fabs(x)) if (y > joyCentre): functOutLeft = mov functOutRight = turn elif (y < joyCentre): functOutRight = mov functOutLeft = turn return rightOut, leftOut while True: x = xAxisJoyPin.read_u16() y = yAxisJoyPin.read_u16() utime.sleep(0.01) # Zero point of joystick tends to jump around. Perhaps some electronic solution might be better? if x < 1000: x = 0 if y < 1000: y = 0 # Print for analysis print ("xAxis:", x, "yAxis:", y, end=' ') print ("RF:", RFmotorSpeed, "LF:", LFmotorSpeed, end=' ') print ("RB:", RBmotorSpeed, "LB:", LBmotorSpeed) # Send inputs to joystickToDiff function for processing # and # Save outputs from joystickToDiff function leftOut, rightOut = joystickToDiff(x, y, joyMin, joyMax, speedMin, speedMax)
That looks better 😀
But also you cannot put
if y < joyCentreMinusDZ:
if x < joyCentreMinusDZ:
LBmotorSpeed = leftOut
And another follow up comment, Of course the following is OK, and shows that unless you present properly formatted code its hard to follow.
if y < joyCentreMinusDZ: if x < joyCentreMinusDZ: LBmotorSpeed = leftOut
Apologies to all.
you can return more than one value ... however, you need to do it 'at the same time' as when you call it with the full set of arguments.
Thanks!
I'll post a small snippet of your code with indents
Did you add the indents manually after copy and pasting? I read the page https://forum.dronebotworkshop.com/add-code/ but it doesn't mention indents so I left it, presuming that was how it should happen.
I also made the error of pasting my whole sketch, I'll cut smaller sections in the future.
Did you add the indents manually after copy and pasting?
No, I just pasted the code into the code window. Of course to put some indents into your code I had to copy your text into the Thonny IDE and adjust it in that editor. But then to unload my code from Thonny I just cut and pasted it into the forum code window and the indentation was preserved OK.
This worked! Unpack the outputs and call the function with the input arguments ON THE SAME LINE! Who would've thought?
leftOut, rightOut = joystickToDiff(x, y, joyMin, joyMax, speedMin, speedMax)