0
votes

This is a complex bug I have been having for a few weeks and I don't know how to fix it. I have a thermistor array plugged in the four first analog pins and they are returning a temperature on a Python script that communicates with the Arduino on a serial port. Here is the Arduino code:

float R1 = 2000;
float c1 = 8.7956830817e-4, c2 = 2.52439152444e-04, c3 = 1.94859260345973e-7;

void setup() {
  Serial.begin(9600);
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);
  delay(1000);
  digitalWrite(13, LOW);
}

int getVoltage(int i) {
  return analogRead(i);
}

float getTemp(int i) {
  int V = getVoltage(i);
  float R2 = R1 * (1023.0 / (float)V - 1.0); \\minus 1 for 1 index based
  float logR2 = log(R2);
  float T = (1.0 / (c1 + c2*logR2 + c3*logR2*logR2*logR2));
  return T - 273.15;
}

String getTempString(int i) {
  float temp = getTemp(i);
  String result;
  if(temp > 99.99){
    return String(temp, 2);
  } else {
    return String(temp, 3);
  }
}

void loop() {
  if (Serial.available() > 0) {
    digitalWrite(13, HIGH);
    // read the incoming byte:
    String input = Serial.readStringUntil('\n');
    digitalWrite(13, LOW);
    //send the temperature
    char* response = new char[6];
    int channelNumber = String(input[0]).toInt() - 1;//-1 to make it index based 1
    getTempString(channelNumber).toCharArray(response, 6);
    //delay(20);
    Serial.write(response, 6);
    Serial.write('\n');
  }
}

and here is the Python code:

from serial import Serial
import time

ser = Serial('COM5', 9600, timeout=1)

def readTempChannel(i):
    global ser
    
    ser.write(i+b'\n')
    raw = str.rstrip(ser.readline())
    try:
        return float(raw)
    except Exception:
        ser.close()
        ser = Serial('COM5', 9600, timeout=1)
        return 5.0[![enter image description here][1]][1]

if __name__ == "__main__":
    while 1:
        channel1 = readTempChannel('1')
        channel2 = readTempChannel('2')
        channel3 = readTempChannel('3')
        channel4 = readTempChannel('4')
        print('%.2f, %.2f, %.2f, %.2f' % (channel1, channel2, channel3, channel4))

The problem is that I get values for the first 10 seconds but after that I get either empty strings or I get random characters that are not numbers from the Arduino.

I tried closing and reopening the serial port and that works (sometimes) but it adds a delay to the stream and I need the communication to happen at high speeds for my application without any delays. I added a screenshot to this post showing the error on a PuTTY terminal (the Python code is running on a Beaglebone and it is Python 2.7).

So if any of you can help me solve this bug I would be very thankful.

enter image description here

1
Hi! I am also James B! I don't see any screenshots of the error? Would you mind sending an image of the random junk that it sends, also check if the serial terminal is set to the right frequency (the same frequency you set in your arduino program 9600 baud rate) I think you tried to include the screenshot, but there was a formatting issue, I see the image link in the python code.James Barnett
One other possibility is that you have the serial terminal settings setup wrong, for example there are multiple settings that you have to set to communicate with an arduino. This includes the Data Bits, Stop Bits, Parity and Flow Control.James Barnett

1 Answers

3
votes

This is a difficult problem to solve without having all the physical hardware to hand but I can share with you my experiences of using pyserial with arduino:

on the python side I didn't bother with the new line:

ser.write(b'{}'.format(command)) 
## writes the command as bytes to the arduino

I also used the following line to pause the python program until the it receives a response - this is quite important for flow control

while(ser.inWaiting()==0):pass ## waits until there is data

On the arduino side i used the following to read in the serial and carry out commands:

void loop() {
  switch(Serial.read()){
    case '0': ## when command (in python) = 0
              do_command_1()
              break;
    case '1': ## when command (in python) = 1
              do_command_2()
              break;
    default: break; # default - do nothing if I read garbage
  }
}

try integrating some of the above into the code and get back to me - like I said it's difficult to solve a hardware problem without the hardware and the code I have here is from a project a long time ago