I'm working with Python on my PC, sending serial commands to an arduino which controls a certain number of stepper motors.
However, in this function:
# takes array of commands to send to motors (in order) and sends commmand arcodinlgy
# each element of commands is an absolute angle (rad) to give to one motor
def send_command(commands):
if not len(commands) > 0:
return
# make command string to send serial
# (with command separator and line termination)
command_string = "";
for i in range(len(commands) - 1):
command_string += f"{commands[i]:.4f}{COMMAND_SEPARATOR}"
command_string += f"{commands[-1]:.4f}{LINE_TERMINATOR}"
# make command string into bytes UTF-8
# print(command_string)
command_string = bytes(command_string, "utf-8")
# send command string serial
print(f"Sending command: " + str(command_string))
port.write(command_string)
# wait for arduino's return_code on serial
while True:
if port.inWaiting() > 0:
return_code = int(port.readline())
return return_code
# driving code
while True:
commands = [0, 0]
commands[0] = float(input("command 1: "))
commands[1] = float(input("command 2: "))
return_code = send_command(commands)
print(f"return code: {return_code}")
This code works correctly, but if I don't want user input for the commands :
while True:
commands = [float(random.random()*pi), float(random.random()*pi)]
# or even the following doesn't work for exemple:
# commands = [3.1415, 0.5555]
return_code = send_command(commands)
print(f"return code: {return_code}")
sleep(1)
This code doesn't.
I don't get why because in the first case, the line print(f"Sending command: " + str(command_string))
prints exactly the same as in the second case :
Sending command: b'3.1415:0.5555\n'
(when input those angles)
But in the second case, no return code is received, and the function doesn't work.
I tried totally hardcoding the values given.
I implemented that the commands are always formated the same way, and always converted with float()
(before the print("Serial command...
line.
So I expected the same behavior for the two codes, and I don't see what changes between the two (since the print("Serial command ...
line gives the same and is the last line before the command is sent over serial
Thanks !
After every new serial connection, the Arduino resets.
When it resets, it need a little time to start the loop()
function !
So when I was entering my commands manually, I gave it a little time without noticing, but when the commands were generated inside my Python code, the first command was sent so quickly that it wasn't interpreted by the Arduino, and the function didn't get a return code from the Arduino !
1. Adding a timeout
TIMEOUT = 2
TIMEOUT_ACTIVE = True
def send_command(commands):
### same code as above ###
port.write(command_string)
# wait for arduino's return_code on serial WITH TIMEOUT
init_time = time()
while (not TIMEOUT_ACTIVE) or (time() - init_time) <= TIMEOUT:
if port.inWaiting() > 0:
return_code = int(port.readline())
return return_code
2. Waiting before sending the first command
waiting 2 seconds (tested 1 seconds, was not enough) before begining to send commands
sleep(2)
while True:
commands = [float(random.random()*pi), float(random.random()*pi)]
return_code = send_command(commands)
print(f"return code: {return_code}")
# don't need the sleep(0.1) anymore