3
votes

I can't correctly send data over serial from a Python script to an Arduino Uno. I'm using 9600 baud, and the Arduino correctly resets, but it does not read the char I'm sending from the Python script. I call time.sleep() to ensure the reset on the Arduino does not interfere, and I'm using Windows 7. I should clarify by saying that my desktop is running the python script and connected via USB to the Serial of my Arduino Uno. I then have the RX & TX pins (pins 0 & 1) of my Uno connected to my Mega's Serial1 (pins 18 & 19). I then use the Serial Monitor in the Arduino IDE on my laptop (which uses the Mega's regular Serial) to peek at what the Uno is seeing. Here is the code for the Mega:

void setup() {
  Serial1.begin(9600);
  Serial.begin(9600);
  Serial.println("Master Ready");
}

void loop() {
  if(Serial1.available() > 0) {
    char inByte = Serial1.read();
    Serial.write(inByte);
    Serial.write("\n");
  }
}

Here is the code for the Uno:

void setup() {
  Serial.begin(9600);
  Serial.println("Slave Ready");
}

void loop() {
 if(Serial.available() > 0) {
   char inByte = Serial.read();
   Serial.write(inByte);
   }
}

And finally, here is the python script:

import sys
import serial
import time

ser = serial.Serial("COM23",9600)
n = int(sys.argv[1])
print n

time.sleep(10)
print ser
print n == 41
if (n == 70):
    ser.write(chr(97))
    print 'a'
elif n == 41:
    ser.write('ggggggg')
    print 'b'
elif n == 42:
    ser.write('hello world')
    print 'c'
elif n == 25:
    ser.write(chr(100))
elif n == 26:
    ser.write(chr(101))
elif n == 22:
    ser.write(chr(102))
elif n == 10:
    ser.write(chr(103))
elif n == 4:
    ser.write(chr(104))
elif n == 14:
    ser.write(chr(105))
elif n == 7:
    ser.write(chr(106))
elif n == 11:
    ser.write(chr(105))
elif n == 5:
    ser.write(chr(106))
elif n == 17:
    ser.write(chr(107))

# head - a - 70
# right bicep - b - 41
# right forearm - c - 42
# left bicep - d - 25
# left forearm - e - 26
# chest - f - 22
# right thigh - g - 10
# left thigh - h - 4
# right shin - i - 11 - 14
# left shin - j - 5 - 7
# waist - k - 17

In case it helps, I'm essentially trying to write the hit locations in Doom3 to an Arduino over serial so that the Arduino can turn a motor on in the proper location on your body. The game code is in C++, and I first tried using a serial library for C++, but that didn't work either.

4
Can you pinpoint the problem further? For example, if you just let the Mega blink once it receives anything, does it blink? Can you verify that the Uno gets the commands?phihag

4 Answers

2
votes

I just came across something similar. The key here is that it worked when communicating with the arduino from the IDE and failed when using some other serial program. You have been bit by the auto-reset feature.

Check out this link on the Arduino Playground for a detailed description of what is going on and what to do about it. The site gives several solutions depending on you skill and comfort level.

I expect your C++ code will work once you implement one of the work arounds from this site.

1
votes

If I understand your physical setup correctly, there appears to be a conflict between the Arudino IDE and python. Only one program by default can open the serial port at a time (like opening a file for exclusive write). If you just use the python script, don't start the arduino IDE and change the ardiuno to turn on an LED when it gets a msg, that should work (if you serial port assignment is correct). The arduino's diagnostic LEDs should blink with normal serial traffic, but for a single msg you might be missing the short blink.

It looks like there is also a conflict between using the serial port between the IDE and between Arduinos. (I don't understand the reason for multiple Arduinos.) Each serial communication pair should be unique. Use the Arduino's SoftwareSerial library to use another pair of digital pins to communicate between the arduinos, not the d0/d1 pins currently used by the FTDI chip to talk to the IDE.

Might also include some diagnostic msgs in the python script if it can't open/communicate with the serial port.

1
votes

Problem:

Serial Communication is not always accurate. Sometimes you can notice that in the Serial Monitor, garbage data that you don't want appearing due to the overlapping of two or more pieces of data from Arduino. Similarly, try sending two values quickly and printing the value on the serial monitor, you will notice the same kind of overlapping. Arduino requires certain delays to work effectively and hence pyserial module is not the best way to use python with Arduino.



Solution:

1) In your python script use the ser.write() or ser.read() functions twice! If you find this irritating, use the next solution.


2 ) Use Arduino_Master_Delta module(python) to communicate with Arduino which is designed especially to ease the process and remove garbage values with advanced data science and visualization functions.

The link to the pip module is Arduino_Master_Delta

With this module installed you can use this statement instead:

import Arduino_Master_Delta as amd
writeSerial(23, msg=' Whatever you want to send to the serial monitor')
# Data will be encoded into bytes and hence use the Serial.readString() in Arduino code
# and then convert the string to your desired data type!

Read the documentation in the above link to learn more !!

BTW I'm the developer of this python module. Do share your view about it.

0
votes

I had a problem too with serial communication, i managed to resolve it by closing the serial monitor in the Arduino. I don't know if you open it when you run your program, but if you do then that might be the problem.