-2

I have some matlab functions which I would like to translate into python 3.7. The functions calculate values for joint angles of a little robot from trossenrobotics and send those values via serial port to the robot which is controlled by an arduino board. The board runs a programm from Trossenrobotics, which interpretes the data send via the serial port and reacts accordingly.

I already managed to translate all the functions and they give the same outputs as the matlab functions, but the serial communication just doesn't work. In matlab fwrite(s, int_value) and fread(s) are used for the communication. The int_values represent a highbyte and a lowbyte of a joint position(0-1024) and are send seperately. In python I used pyserial and the functions s.write(byte) and s.read(). I converted the int values into bytes with chr(int).encode().

Since I was struggling with my actual objective, I first wanted to abstract it and make it simpler. Now I am just trying to turn on an LED on the arduino for 2 seconds, when a special byte is received and send the same byte back to python.

I noticed that as long as the value I am sending is smaller that 128 it works just fine, but when it's greater it won't work.

I printed the output of chr(255).encode() which is b'\xc3\xbf', what to me looked like it could be the problem. The I tried using chr(255).encode('charmap') and printed it which gives back b'\xff', what looks right to me, but it still doesn't work for numbers between 128 and 255. I also noticed, that when I send the data over the terminal with s.write(chr(115).encode()) It doesn't return a value, but when I use s.write(chr(255).encode('charmap')) it returns a 1.

Here's my python pogramm:

python
import serial
from time import sleep
port = 'COM4'
baudrate = 38400
s = serial.Serial(port,baudrate)
sleep(3)

m = 115
s.write(chr(m).encode())

while s.in_waiting == 0:
    print('#####   waiting     #####')
    sleep(2)

if s.in_waiting > 0:
    r = int.from_bytes(s.read(), byteorder = 'big')
    print(r)

s.close()

And here's the arduino programm:

C#
void setup() {
  pinMode(13, OUTPUT);
  digitalWrite(13,LOW);
  Serial.begin(38400);
}

void loop() {
  if (Serial.available() > 0)
  {
    if (Serial.read() == 's')
    {
      digitalWrite(13, HIGH);   
      Serial.write('s');
      delay(2000);
    }
  }
  else
  {
    digitalWrite(13, LOW);    
  }
}

My questions would be:

Regarding my primary problem (sending multiple bytes via matlab, python):

1) Does anybody know if there are any fundamental differences between serial communication in matlab and in python which could cause my problems?

Regarding my abstracted problem (sending one bye via python):

2) How can I send values greater than 128 (up to 255) via the serial port?

Marcos G.
  • 3,371
  • 2
  • 8
  • 16
  • It may not be related to the problem, but why are you using `s.write(chr(115).encode())` instead of `s.write("s".encode())`? Or simply `s.write("115".encode())`, since it seems like you only need numbers anyway. – tgikal Jun 19 '19 at 13:27
  • The problem you're describing looks a codec problem. Probably something like this going on: `chr(255).encode('charmap').decode() Traceback (most recent call last): File "", line 1, in chr(255).encode('charmap').decode() UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte` – tgikal Jun 19 '19 at 13:33
  • Nothing in the question suggest that you can't write bytes greater than 128, actually it looks like you are successfully writing 255. `s.write(chr(255).encode('charmap'))` is just a convoluted way of writing 255. – Stop harming Monica Jun 19 '19 at 18:09

2 Answers2

0

There is no fundamental difference between Python and Matlab on this regard.

But in your Matlab code it seems (I'm assuming because what you say):

The int_values represent a highbyte and a lowbyte of a joint position(0-1024) and are send seperately.

that you're sending an int16 to be able to fit up to 1024.

I have no idea what you're trying to do with chr but I have the feeling what you need is replace these lines:

m = 115
s.write(chr(m).encode())

With (on Python 3.x):

m=115
s.write(m.to_bytes(2, byteorder="big"))

That would write: b'\x00s', a mix of hex and ASCII, but you should not worry about that, because that is exactly the same as b'\x00\x73'

And if you do, then you can do: b'\x00s'==b'\x00\x73' and you'll get True.

Marcos G.
  • 3,371
  • 2
  • 8
  • 16
0

Thanks for your answer! And sorry for the late reply.

I already tried that right at the beginning but always got an exception. It took me a while to figure out why. It was because I was using numpy.uint8() for my integer values.

After I removed it I didn't get any exception but it didn't work either.

I used chr() because it didn't throw an exception with the numpy.uint8() and honestly because I did not know what else to do...

Today I finally found the solution.

Here is the link to where I found it: arduino.stackexchange.com

Using s.write(struct.pack('>B', int_value) works and seems to be the equivalent to matlabs fwrite(s, int_value).

Sorry If my question didn't make a lot of sense to you, I am just glad I finally figured it out.