First, I apologize if this question is in the wrong place.
I am making a device which pulls a fiber optics thread from a spool and cuts and polishes the fiber. I’ve made a GUI in python where the user can send a length to be cut between 1"-6" with 0.01" tolerance. Essentially, the Python program sends the action (cut, polish, or both), the number of fibers to be cut and polished, the integer part of the length of the fibers, the number of decimal points in the fractional part, and then each decimal place. (This might seem overcomplicated, and if you have a better way of doing it please let me know.)
Problem: The program behaves exactly as it is supposed to behave with the serial monitor open. With the serial monitor closed I can only send the program lengths with a tolerance of 0.1. So for example, if I send the length 1.15" nothing happens, but if I send 1.1" the program works correctly.
First partial solution: Previously, I wasn’t able to send anything without the serial monitor open. I noticed the program restarted every time a serial connection was made. So I fixed this by adding (which was suggested in an older thread)
ser.dsrdtr=False
ser.setDTR(level=False)
Adding these lines allows me to send numbers of the form X.X but not X.XX.
Second partial solution: If I add a delay of 0.001 second in between ANY of my ser.write commands in Python, the program works correctly. You will see a few commented lines #time.sleep(.001) in my Python code. If I uncomment one of them, and it doesn’t matter which one, the program works without the serial monitor.
Why? What is happening? I assume that without the delay the Arduino is not receiving all of the information sent by the GUI. (Not sure how to test this idea since opening the serial monitor will change the behavior.) But what about having the serial monitor open allows this to happen correctly?
Here is part of my Python code (I removed the lines I thought were unnecessary):
# above this line is the GUI code
def OnClose(self, event):
action = 0 # 0 = do nothing, 1 = cut, 2 = polish, 3 = both
# here is some code that sets the action from the user's input, removed to make more readable
decimal, integer = math.modf(self.length.GetValue())
decimalList = list(str(decimal))
# send input to arduino
ser.write(chr(int(action))) # send action
#time.sleep(.001)
ser.write(chr(int(self.number.GetValue()))) # send number of fibers
#time.sleep(.001)
ser.write(chr(int(integer))) # send length, int part
#time.sleep(.001)
ser.write(chr(int(len(decimalList)))) # send number of digits of frac
time.sleep(.001)
for i in range(2,len(decimalList)): # send length, frac part
ser.write(chr(int(decimalList[i])))
#time.sleep(.001)
ser.close()
self.Close()
# search serial ports for arduino by VID:PID and SNR
# VID:PID and SNR for DFRduino RoMeo V1.1
# VID:PID = 2341:0001
try:
ports = list(serial.tools.list_ports.comports())
portIndex = [x[2] for x in ports].index("USB VID:PID=2341:0001 SNR=7523733353635130F171")
except:
print "Arduino not found."
print "Plug in Arduino."
sys.exit()
SERIALPORT = "/dev/" + str(ports[portIndex][1])
# open serial port
try:
ser = serial.Serial(SERIALPORT, 9600)
ser.dsrdtr=False
ser.setDTR(level=False)
# above line is needed to run code without Ardiuno IDE and Serial Monitor
except serial.SerialException:
print "Failed to write to port %s." % SERIALPORT
print "Plug in Arduino or connect to different port."
sys.exit()
app = wx.App(0)
MyDialog(None, -1, 'cut_polish.py')
app.MainLoop()
Here is part of my Arduino code (I only included what I thought was important):
void getIncomingData()
{
int i = 0;
int j = 0;
int flag = 1;
while (flag == 1)
{
if(Serial.available() > 0) {
if(j < 4){
inComingData[j] = Serial.read();
//Serial.print(inComingData[j]);
j++;
}
if(i < inComingData[3] - 1 && j > 1) {
inComingFraction[i] = Serial.read();
if(i == (inComingData[3]-2)){
flag--;
}
i++;
}
}
}
}