Serial/USB Connectivity Issues

I did a quick prototype of a box dimensioner (measures boxes to be inputted into our shipping software), using some basic ultrasonic sensors. For the most part, it works very well, here is a screenshot:

http://jarrodchristman.com/cubiscan_project.jpg

The issue we have is that the serial communication craps out every few days, sometimes more. The device is still operating, and the status screen still updates with the latest measurement... but the serial communication is not sent, unless the device is hard reset (unplug and plug the USB back in). Any ideas as to what the issue may be?
I can post the code later if needed (it's on another computer).

P.S. Forgive me if this is the wrong forum section. Not sure which section a box dimensioner fits it, lol.

jarrod1937:
I did a quick prototype of a box dimensioner (measures boxes to be inputted into our shipping software), using some basic ultrasonic sensors. For the most part, it works very well, here is a screenshot:

http://jarrodchristman.com/cubiscan_project.jpg

The issue we have is that the serial communication craps out every few days, sometimes more. The device is still operating, and the status screen still updates with the latest measurement... but the serial communication is not sent, unless the device is hard reset (unplug and plug the USB back in). Any ideas as to what the issue may be?
I can post the code later if needed (it's on another computer).

P.S. Forgive me if this is the wrong forum section. Not sure which section a box dimensioner fits it, lol.

Arduino based ? What board? So when problem appears Arduino doesn't send or doesn't receive?
Maybe a block diagram to see what all devices are involved in the system would help.

Yes, sorry, Arduino Mega 2560. The Arduino receives the serial communication because it starts the measuring process, however, I don't receive any output via software. The LCD screen is updated after the serial output from the Arduino showing the last output. I have no been able to tell if it's the Arduino, or the drivers in the process. However, monitoring the COM port reveals no output even being seen from the Arduino.
Basically the flow is:

Arduino power up, measures distances to calibrate.
Shipping software --> Serial "D" --> Arduino sees "D", staggers the sensor activations and calculates any offsets from the calibration readings --> Serial {concatenation string of sensor offsets} --> Updates LCD with same string --> Shipping software monitors COM port, parses manipulates data.

When I experience an issue, the Arduino seems to get the "D" input, measures the box, updates the LCD screen, but I get no COM port output.

Well PaulS our resident software guru would say you are asking for trouble if you use String functions in a SRAM limited environment like a microcontroller has. He would say you should use zero terminated string (small s ) arrays. Not saying that is your problem but the long intervals between failure sure sounds like his advice might apply.

Ah, interesting, I will give that a try later this week. To be quite honest, this issue has been on the backburner for a while, so I'll need to review my code. However, that sounds plausible, and will see what affect that has. I would like to do a test to see if the failure happens over a specific time period, or if it occurs after a certain amount of iterations... or maybe it's just random :wink:

As promised, below is the code:

#include <stdio.h>


/* Font */
/* font pixels */
byte Font5x9Mono[535] =
{
// Bytes removed from code brevity
}; /* 535 bytes */

/* 4-bit serial communication LDS183 LCD module */
const int SCOMMAND = 0;
const int SDA2TA = 1;
const int DC = 4;
const int CS = 2;
const int SDA2 = 6;
const int RESET = 3;
const int CLK = 5;

byte gr;
byte gg;
byte gb;




char inData[20]; // Allocate some space for the string
char inChar; // Where to store the character read
byte index = 0; // Index into array; where to store the character
char diminput[3];
float sensor1_cal = 0.0;
float sensor2_cal = 0.0;
float sensor3_cal = 0.0;
float sensor4_cal = 0.0;

void setup() {
  
  //Open up a serial connection
  Serial.begin(9600);
   sensor1_cal = sensor_cal(30, 32);
   delay(200);
   sensor2_cal = sensor_cal(22, 24);
   delay(200);
   sensor3_cal = sensor_cal(34, 36);
   delay(200);
   sensor4_cal = sensor_cal(26, 28);
   
  pinMode(DC, OUTPUT);
  pinMode(CS, OUTPUT);
  pinMode(SDA2, OUTPUT);
  pinMode(RESET, OUTPUT);
  pinMode(CLK, OUTPUT);
  
  lcdInit();
  //Wait for the serial connection
  delay(500);
    // background color
    sendCMD(0x2C);
      int i, j, k, l;
    for (i=0; i<5504; i++) {
      setPixel(0, 0, 0);
    }
    
    for (i=5504; i<128*128; i++) {
      setPixel(0, 255, 0);
    }
   setColor(255, 255, 255);
   printString("Device is Ready...", 0, 0);
   printString("Last Read:", 0, 20); 
   printString("000000000", 0, 30); 
}

// sensor1, pins 22-trig, 24-echo
// sensor2, pins 26-trig, 28-echo
// sensor3, pins 30-trig, 32-echo
// sensor4, pins 34-trig, 36-echo
//Refer to diagram below for sensor arrangement

////////BACK////////
//2     3       4//
//               //
//      1        //
void loop()
{  

  
if(Comp("D") == 0)
{
//read sensor 1
String sensor1_rd = sensor_read(30, 32, sensor1_cal);
//String sensor1_rd = "333";
//Wait between sensor readings to prevent interaction between sensors
delay(100);
String sensor3_rd = sensor_read(34, 36, sensor3_cal);

delay(100);
String sensor_combined_rd = sensor_read_dual(22, 24, 26, 28, sensor2_cal, sensor4_cal);

Serial.print('0');
String composite =  sensor_combined_rd  + sensor1_rd + sensor3_rd;

Serial.print(composite);

Serial.println();
char charBuf[10];
composite.toCharArray(charBuf, 10);
setColor(255, 255, 255);
printString(charBuf, 0, 30);
sendCMD(0x2C);
}
}


String sensor_read_dual(int pingPin1,int inPin1, int pingPin2,int inPin2, float initial_distance1, float initial_distance2)
{

float inches1 = sensor_cal(pingPin1, inPin1);
delay(100);
float inches2 = sensor_cal(pingPin2, inPin2);
  
  float combined_initial= (initial_distance1 + initial_distance2)/2;
  float combined_inches = inches1 + inches2;
  
  
  
  
  
float  inches_width = (combined_initial-combined_inches);
float  inches_modulo = fmod(combined_inches,1);
 
 
int inches_width_rounded = 0;
 
  if(inches_modulo >= 0.27)
  {
   inches_width_rounded = (inches_width-inches_modulo)+1;
  }
  else
  {
   inches_width_rounded = (inches_width-inches_modulo);
  }

  if(inches_width_rounded < 0)
  {
  inches_width_rounded = 0; 
  }



String sensor_rd = String(inches_width_rounded);

if(sensor_rd.length() == 0)
{
 sensor_rd = "000";

}
else if(sensor_rd.length() == 1)
{
 sensor_rd = "00" + sensor_rd; 
}
else if(sensor_rd.length() == 2)
{
 sensor_rd = "0" + sensor_rd; 
}



return sensor_rd; 
}




String sensor_read(int pingPin,int inPin, float initial_distance)
{
  // establish variables for duration of the ping,
  // and the distance result in inches and centimeters:
  float duration, inches, cm, inches_modulo, inches_width;
 int inches_width_rounded = 0;
  // offset by 0.82 inches from 11
  //float initial_distance = 10.18;
 
  // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
  // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(pingPin, LOW);
 
  // The same pin is used to read the signal from the PING))): a HIGH
  // pulse whose duration is the time (in microseconds) from the sending
  // of the ping to the reception of its echo off of an object.
  pinMode(inPin, INPUT);
  duration = pulseIn(inPin, HIGH);
 
  // convert the time into a distance
  inches = (duration / 73.746) / 2;
  inches_width = (initial_distance-inches);
  inches_modulo = fmod(inches_width,1);
  
  if(inches_modulo >= 0.36)
  {
   inches_width_rounded = (inches_width-inches_modulo)+1;
  }
  else
  {
   inches_width_rounded = (inches_width-inches_modulo);
  }
  
  if(inches_width_rounded < 0)
  {
   inches_width_rounded = 0; 
  }

String sensor1_rd = String(inches_width_rounded);

if(sensor1_rd.length() == 0)
{
 sensor1_rd = "000";

}
else if(sensor1_rd.length() == 1)
{
 sensor1_rd = "00" + sensor1_rd; 
}
else if(sensor1_rd.length() == 2)
{
 sensor1_rd = "0" + sensor1_rd; 
}

return sensor1_rd; 
}

float sensor_cal(int pingPin,int inPin)
{
  // establish variables for duration of the ping,
  // and the distance result in inches and centimeters:
  float duration, inches, cm, inches_modulo, inches_width;
 int inches_width_rounded = 0;
  // offset by 0.82 inches from 11
  //float initial_distance = 10.18;
 
  // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
  // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(pingPin, LOW);
 
  // The same pin is used to read the signal from the PING))): a HIGH
  // pulse whose duration is the time (in microseconds) from the sending
  // of the ping to the reception of its echo off of an object.
  pinMode(inPin, INPUT);
  duration = pulseIn(inPin, HIGH);
 
  // convert the time into a distance
  inches = (duration / 73.746) / 2;

return inches; 
}

char Comp(char* This){

  while(Serial.available() > 0) // Don't read unless
    // there you know there is data
  {
    if(index < 19) // One less than the size of the array
    {
	inChar = Serial.read(); // Read a character
        if(inChar != '\r')
        {
	inData[index] = inChar; // Store it
	index++; // Increment where to write next
	inData[index] = '\0'; // Null terminate the string
        }
    }
  }
String convchar = String(inData);
  if(convchar==This){
    for(int i=0;i<19;i++){
	inData[i]=0;
    }
    index=0;
    return(0);

  }
  else{
   for(int i=0;i<19;i++){
	inData[i]=0;
    }
    index=0;
    return(1);


  }
}



void shiftBits(byte b, int dc) {
    digitalWrite(CLK, 0);
    if ((b&128)!=0) 
      digitalWrite(SDA2, 1);
    else
      digitalWrite(SDA2, 0);
    digitalWrite(CLK, 1);

    digitalWrite(CLK, 0);
    if ((b&64)!=0) 
      digitalWrite(SDA2, 1);
    else
      digitalWrite(SDA2, 0);
    digitalWrite(CLK, 1);
    
    digitalWrite(CLK, 0);
    if ((b&32)!=0) 
      digitalWrite(SDA2, 1);
    else
      digitalWrite(SDA2, 0);
    digitalWrite(CLK, 1);
    
    digitalWrite(CLK, 0);
    if ((b&16)!=0) 
      digitalWrite(SDA2, 1);
    else
      digitalWrite(SDA2, 0);
    digitalWrite(CLK, 1);
    
    digitalWrite(CLK, 0);
    if ((b&8)!=0) 
      digitalWrite(SDA2, 1);
    else
      digitalWrite(SDA2, 0);
    digitalWrite(CLK, 1);
    
    digitalWrite(CLK, 0);
    if ((b&4)!=0) 
      digitalWrite(SDA2, 1);
    else
      digitalWrite(SDA2, 0);
    digitalWrite(CLK, 1);
    
    digitalWrite(CLK, 0);
    if ((b&2)!=0) 
      digitalWrite(SDA2, 1);
    else
      digitalWrite(SDA2, 0);
    digitalWrite(CLK, 1);
    
    digitalWrite(CLK, 0);
    if ((b&1)!=0) 
      digitalWrite(SDA2, 1);
    else
      digitalWrite(SDA2, 0);
    
      if (dc == SDA2TA)
        digitalWrite(DC, 1);
      else
        digitalWrite(DC, 0);
    digitalWrite(CLK, 1);
}

//send data
void sendData(byte data) {
  shiftBits(data, SDA2TA);
}

//send cmd
void sendCMD(byte data) {
  shiftBits(data, SCOMMAND);
}

void setXY(byte x, byte y, byte dx, byte dy) {
  sendCMD(0x2A);
  sendData(x);
  sendData(x+dx-1);

  sendCMD(0x2B);
  sendData(y);
  sendData(y+dy-1);

  sendCMD(0x2C);
}

//converts a 3*8Bit-RGB-Pixel to the 2-Byte-RGBRGB 565 Format of the Display
void setPixel(byte r,byte g,byte b) {
   sendData((r&248)|g>>5);
   sendData((g&7)<<5|b>>3);
}

void printString(char *st, byte x, byte y) {
  int stl, i;
  
  stl = strlen(st);
  
  for (i=0; i<stl; i++)
    printChar(*st++, x + (i*6), y);
}
void printChar(byte c, byte x, byte y) {
  byte bitmask, *pf, bitstart = 128;
  int cindex, iFont, count;
  
  setXY(x, y, 5, 9);
  
  iFont = (c - ' ') * 45 / 8;

  bitstart = 128 >> (((c - ' ') * 45) % 8);
  
  pf = &Font5x9Mono[iFont];
  
  count = 0;
  
  for (cindex=0; cindex<6; cindex++) {
    for (bitmask=bitstart; bitmask>0; bitmask=bitmask>>1) {
       if (count > 45) return;
       if (*pf&bitmask)
         setPixel(gr, gg, gb);
       else
         setPixel(0, 0, 0); 
       count++;
    }
    bitstart = 128;
    pf++;
  }
}

void setColor(byte r, byte g, byte b) {
  gr = r;
  gg = g;
  gb = b;
}

void lcdInit() {

  digitalWrite(CS, 0);
  digitalWrite(SDA2, 0);
  digitalWrite(CLK, 1);

  digitalWrite(RESET, 1);
  digitalWrite(RESET, 0);
  digitalWrite(RESET, 1);

  digitalWrite(CLK, 1);
  digitalWrite(SDA2, 1);
  digitalWrite(CLK, 1);

  delay(10);

  //Software Reset
  sendCMD(0x01);

  // Write Contrast
  sendCMD(0x25);
  sendData(64);

  //Sleep Out and booster on
  sendCMD(0x11);

  // Booster on
  //sendCMD(0x03);

  delay(10);

  // Display Inversion off
  sendCMD(0x20);

  // Idle Mode off
  sendCMD(0x38);

  // Display on
  sendCMD(0x29);

  // Normal Mode on
  sendCMD(0x13);

  // Memory Data Access control
  sendCMD(0x36);
  sendData(0x60);
  // sendData(0x00);
  //sendData(8|128);

  sendCMD(0x3A);
  sendData(5);   //16-Bit per Pixel

 // Color set
  // sendCMD(0x2D);
  // sendDATA(0x00);

  // X_Address or Column Address Area
  sendCMD(0x2A);
  sendData(0);
  sendData(127);

  // Frame Frequency Select
  sendCMD(0xB4);
  sendData(0x03);
  sendData(0x08);
  sendData(0x0b);
  sendData(0x0e);

  // Display Control
  sendCMD(0xBA);
  sendData(0x07);
  sendData(0x0D);

  //Page Adress Set
  sendCMD(0x2B);
  sendData(0);
  sendData(127);
}

This looks identical to the problem I'm posting about here:
http://forum.arduino.cc/index.php?topic=238351.0

While it might be a software issues (Strings, etc), my feeling is that there's a hardware problem. Are you using a USB hub?

Tomorrow I'm going to try with and without a USB hub to see if I can identify the source of the problem.

My other thought is that there's an issue with power/ground....

I have no been able to tell if it's the Arduino, or the drivers in the process. However, monitoring the COM port reveals no output even being seen from the Arduino

May find this a project to build...
http://www.hackster.io/rayburne/the-qbf-signal-generator

I would also consider a totally independent SD-card recorder to save log (debug) info from the second com port on the 2560 (or use Nick Gammon software send only lib).
http://www.hackster.io/rayburne/sd-card-serial-logger

And, put freeRam() on the diagnostic channel just to keep track of weird issues. Source: playground.arduino.cc/Code/AvailableMemory

Ray