r/Python • • Oct 26 '14

[Help] Sending Bytes between Arduino and Python

Hey all,

I am new to python and am looking for a little guidance. My goal is pretty simple, I want to send data back and forth in the form of bytes (0 to 255). I have written some test code and it doesnt seem to be working well Here is my arduino code:

byte k;

void setup() {

Serial.begin(115200);

}

void loop() {

if(Serial.available() >0){

 k=Serial.read();
 Serial.print(k);

}

}

And here is my python code: (I'm using pyserial)

import serial

import time

print ("start")

ser = serial.Serial("COM3",115200)

time.sleep(1)

i=0

while i<21:

print(i)

ser.write(str(i).encode())

i=i+1

time.sleep(1)

print(ser.read())

and what is getting printed is this:

start

0

b'2'

1

b'4'

2

b'\xf0'

3

b'5'

and so one. I would like it to be:

start

0

0

1

1

2

2

3

3

and so on. Obviously at some point the data is not getting converted to the right datatype but I am not sure where. Can anyone help me?

0 Upvotes

5 comments sorted by

0

u/teenageguru self.__name__ = teenageguru Oct 26 '14

Did a bit of this recently. If I recall correctly, you could import struct and replace 'str(i).encode ()' with 'struct.pack('B',i)'. Sorry about the lack of an example, typing on a phone.

-1

u/GiantJacob Oct 26 '14

thank you, this seems to be working for sending the number from Python to Arduino. For recieving the data from arduino, using the struct.unpack is giving me slightly strange results though. For recieing data in Python I now have:

g=struct.unpack('B',ser.read(ser.inWaiting()))
print(g)

And I am getting the the right numbers for everything but 0 and 1 but they are in the format of: (3,)

For 0 and 1 I am getting: (240,) and (48,) respectively.

Any clue what the issue with 0 and 1 are? and what about the format of the numbers, how do I get them to be simple numbers?

0

u/teenageguru self.__name__ = teenageguru Oct 27 '14 edited Oct 27 '14

In your Arduino code you use 'print', which actually sends the data to serial as ASCII text. to unpack it, instead of argument 'B' use 's' for string. You'll get an answer that looks like (b'1',). The b before the '1' means it's stored as a byte (signed char), and the parenthesis are because it's stored in a tuple. You can access it and print it as an integer with:

int(struct.unpack('s',g)[0])    

int() obviously changes it to an integer, [0] accesses b'1'

-1

u/greenpin Oct 26 '14

Python 2 or 3? Unicode? Perhaps you need to convert the value sent from Python to byte like ser.write(b'1').

-3

u/vn2090 Oct 26 '14
import os
import eplib
import serial
import time

'''
Q <-> x
dQ/dt = I <-> v
dI/dt = (d^2)Q/dt^2 <-> a = dv/dt = d^2x/dt^2
∆V <-> F
R <-> b(damping)
C <-> 1/k
L <-> m

UL = 1/2*(L*I^2) <-> (1/2)*m*v^2
Uc = (Q^2)/C <-> (1/2)*k*x^2
rate of energy loss (I^2)*R <-> b*v^2
'''

def Gen_up(ProjectsDir, ProjectDir):
	#get to the base directory that contains all projects
	os.chdir(ProjectsDir)
	#make the project
	os.system('mkdir ' + ProjectDir)
	#switch inside that directory
	os.chdir(ProjectDir)
	#list of commands to give which launch ino
	cmds = ['ino init -t blink', 'ino build', 'ino upload','ino serial']
	for cmd in cmds:
		print ('current cmd: ' + cmd)
		os.system(cmd)

#conts=eplib.frd('/Users/evan/Dropbox/Career/Arduino_projects/S1/src/sketch.ino')
ProjectsDir = '/Users/evan/Dropbox/Career/Arduino_projects'
ProjectDir = '/Users/evan/Dropbox/Career/Arduino_projects/S1'
Gen_up(ProjectsDir, ProjectDir)
ser = serial.Serial('/dev/tty.usbmodem1411', 9600, timeout=1)
for x1 in range(100):
	line = ser.readline()
	print line
	time.sleep(1)