Arduino/ RPI Serial Data Hangup

I am collecting data with a couple of different sensors connected to an Arduino Uno. I have the Arduino connected to a Raspberry Pi 4 via USB cable.

Goal: Send the sensor values to the raspberry pi whenever they are requested.

Problem: Data is successfully being received (by serial communication) by the RPi from Arduino but over time the values seem to hang up and not update. When I stop and restart the program suddenly the values change to more accurate values. To be clear: I keep receiving values but the values appear to be old or repeating values.

Example; I am measuring soil moisture with an analog sensor. I start the program and the values being received seem good, reasonable, and stable. I let the program run for a while (5-10 minutes) and the values seem too stable. So I remove the sensor from the wet soil and dry it off, this should cause the values to drastically change- but they do not, the values continue to read out as if the sensor is still in the soil. I stop the program and restart it. The new values are much more reasonable for a dry moisture sensor.

Possible Cause(??): Devices out of sync ( the only possible cause I have found online).

Possible solutions;

  • (Tried, Did not work) Add a delay in the arduino code. I have a delay(2000) at the end of the loop.

  • (Tried, Did not work) Try different data send triggers; I have tried both a serial Trigger (send serial communication from Rpi to Arduino asking for data). I Have also tried a more physical trigger of setting a Pin to HIGH when data is wanted.

  • Bypass the USB and use the TX/RX pins on the arduino/ RPI to send the data. This is my next step but it is a hardware solution (need level converter and need to wait for that to ship.)

Does this community have any experience with this? Any links to solutions or explanations you have seen?

RPI CODE:

#!/usr/bin/env python3

from __future__ import print_function
import datetime
from random import randint
from time import sleep
import Adafruit_DHT
import pickle
import os.path
import board
import busio
import socket
import adafruit_sgp30
import picamera
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
import csv
import os.path
import os
import time
import serial
import time

DHT_SENSOR = Adafruit_DHT.DHT22
DHT_PIN = 4

GPIO.setup(15, GPIO.OUT)
GPIO.output(15, GPIO.HIGH)

if __name__ == '__main__':
    ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1)
    ser.flush()
    
    while True:
        try:
            Time = '{:%D %H:%M}'.format(datetime.datetime.today())
            ser.flush()
        #Serial Components
#             ser.flush()
            GPIO.output(15, GPIO.HIGH)
#             ser.write(b"RequestFullData") #Sending request to Arduino- Doesn't matter what it says
            line = ser.readline().decode('utf-8').rstrip() #Recieve the data in line
            f = line.replace("'","") #Manipulate data
            f = f.split(',')
#             print(f)
            f2 = [float(i) for i in f] # Turn Data into a vector
            
        #Local Digital Components
            humidity, temperature = Adafruit_DHT.read_retry(DHT_SENSOR, DHT_PIN)
            
        #Data Organized
            AirTemp= round(temperature,1)
            AirHumid= round(humidity,1)
            valco2 = f2[0]
            SoiltempC = f2[1]
            SoiltempF = f2[2]
            SoilMoisture1= f2[3]
            SoilMoisture2= f2[4]
            SoilMoisture3= f2[5]
            
            print(AirTemp,AirHumid,valco2,SoiltempC,SoilMoisture1,SoilMoisture2,SoilMoisture3)
        
#Save Enviroment Data ##
    
            with open("/home/pi/MRUData.csv", "a") as log:
                log.write("{0},{1},{2},{3},{4},{5},{6},{7}\n".format(str(Time),str(AirTemp),str(AirHumid),str(valco2),str(SoiltempC),str(SoilMoisture1),str(SoilMoisture2),str(SoilMoisture3)))        
#         print(SoilMoisture1,SoiltempF,SoiltempC)
        
#Loop time
            GPIO.output(15, GPIO.LOW)
            time.sleep(10)
        except (ValueError, IndexError):
            print("Unexpected error:")
            time.sleep(5)

Arduino Code:

*/
#include <OneWire.h>
#include <DallasTemperature.h>

#include <SoftwareSerial.h>


#define ONE_WIRE_BUS 5
#define SensorPin1 A0 
#define SensorPin2 A1 
#define SensorPin3 A2 
//#define SensorPin4 A3 


OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);
SoftwareSerial K_30_Serial(12,13);  //Sets up a virtual serial port
                                    //Using pin 12 for Rx and pin 13 for Tx

 float Celcius=0;
 float Fahrenheit=0;
 float sensorValue1 = 0;
 float sensorValue2 = 0; 
 float sensorValue3 = 0; 
 float sensorValue4 = 0;  
 
byte readCO2[] = {0xFE, 0X44, 0X00, 0X08, 0X02, 0X9F, 0X25};  //Command packet to read Co2 (see app note)
byte response[] = {0,0,0,0,0,0,0};  //create an array to store the response

//multiplier for value. default is 1. set to 3 for K-30 3% and 10 for K-33 ICB
int valMultiplier = 1;
int Trigger = 9;
int TriggerState;

void setup() 
{
  // put your setup code here, to run once:
  pinMode(Trigger, INPUT);
  Serial.begin(9600);//Opens the main serial port to communicate with the computer
  
  K_30_Serial.begin(9600);    //Opens the virtual serial port with a baud of 9600
  sensors.begin();
}

// LOOP begins//////////////////////////////////////////////////
void loop() { 
 
  TriggerState = digitalRead(Trigger);
  if (TriggerState == HIGH)
{
  sendRequest(readCO2);
  unsigned long valCO2 = getValue(response);
//  Serial.print("Co2 ppm = ");
//  Serial.print(valCO2);
  sensorValue1 = analogRead(SensorPin1);
  sensorValue2 = analogRead(SensorPin2);
  sensorValue3 = analogRead(SensorPin3);
//  sensorValue4 = sensorValue4 + analogRead(SensorPin4);
  sensors.requestTemperatures(); 
  Celcius=sensors.getTempCByIndex(0);
  Fahrenheit=sensors.toFahrenheit(Celcius); 
  Serial.print(valCO2);
  Serial.print(",");
  Serial.print(Celcius);
  Serial.print(",");
//  Serial.print(" F  ");
  Serial.print(Fahrenheit);
  Serial.print(",");
//  Serial.print(" MC ");
//  sensorValue = sensorValue/100.0; 
  Serial.print(sensorValue1);
  Serial.print(",");
  Serial.print(sensorValue2);
  Serial.print(",");
  Serial.println(sensorValue3);
//  Serial.println(sensorValue1);
//  Serial.println(sensorValue1);
  delay(2000);
  


}
}

void sendRequest(byte packet[])
{
  while(!K_30_Serial.available())  //keep sending request until we start to get a response
  {
    K_30_Serial.write(readCO2,7);
    delay(50);
  }
  
  int timeout=0;  //set a timeoute counter
  while(K_30_Serial.available() < 7 ) //Wait to get a 7 byte response
  {
    timeout++;  
    if(timeout > 10)    //if it takes to long there was probably an error
      {
        while(K_30_Serial.available())  //flush whatever we have
          K_30_Serial.read();
          
          break;                        //exit and try again
      }
      delay(50);
  }
  
  for (int i=0; i < 7; i++)
  {
    response[i] = K_30_Serial.read();
  }  
}

unsigned long getValue(byte packet[])
{
    int high = packet[3];                        //high byte for value is 4th byte in packet in the packet
    int low = packet[4];                         //low byte for value is 5th byte in the packet

  
    unsigned long val = high*256 + low;                //Combine high byte and low byte with this formula to get value
    return val* valMultiplier;
}

Problem: Data is successfully being received (by serial communication) by the RPi from Arduino but over time the values seem to hang up and not update.

You must send data packages that are of different length than the USB buffer - most likely 64 bytes on USB2 + Arduino. Otherwise it looks like the data stream is frozen - which it is not, it's just buffered on the host side till a end of transmission condition is met - which happens to be receiving a data package shorter than the buffer size.

Understood, can you point me in a direction on how to solve this?

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.