Migrating from Arduino Nano to Particle - Issues with Delay commands

Hello Everyone - First post.

I’ve been using Particle Photons for a while with simple projects like temperature sensing, servo control, etc. I have a sorting machine that is currently running on a Arduino Nano and wanted to port it Particle Photon to be able to monitor the machine conditions remotely.

The code below verifies fine and flashes to the Photon fine but I have issues with the Photon losing connectivity to the Cloud (Periodic Green flashing). I suspect that it’s due to the numerous delay statements. I need the delays for the machine to function properly. Any suggestions?

--------------------------------CODE--------------------------------

// This #include statement was automatically added by the Particle IDE.
#include <LiquidCrystal_I2C_Spark.h>
#include <Wire.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal_I2C lcd(0x27,16,2);

Servo servo1;
Servo servo2;

/*
 * Input pins for the color sensor & servos
 */
const int s0 = D5;
const int s1 = D4; //Dispenser Servo
const int s2 = A4; //Color Sensing Servo
const int s3 = A5;
const int out = D2;
const int servo1_pin = D6;
const int servo2_pin = D7;

/*
 * Vars
 */
const int tot_colors = 5; // 4 colors + 1 empty "color"
const int rep = 8; // repeat xx color reads
const int d = 5;   // add range of XX to the read

//Added 10/29/18 Set Integers for Color and Total Count at Zero
int c1Total = 0;
int c2Total = 0;
int c3Total = 0;
int c4Total = 0;
int c5Total = 0;
int totTotal = 0;
//<--

volatile unsigned de = 1;  // delay servo movement

/*
 * Servo positions  
 * Set the positions in degree where the servo 
 * has to stop to drop the ball
 */
const int s1pos[] = { 125, 87, 55 ,0 ,180};
const int s2pos[] = { 180, 34, 58, 79, 102}; // first item = unknown color was 180,34,58,80,104

int colors_found = 0;
unsigned long red, green, blue = 0;

typedef struct{
  int red;
  int green;
  int blue;
}  colors_type;

colors_type colors[tot_colors]; // length of array:  sizeof(colors)/sizeof(colors_type)

void setup() {
  
  Serial.begin(9600);
  servo1.attach(servo1_pin);
  servo2.attach(servo2_pin);
  pinMode(s0, OUTPUT);
  pinMode(s1, OUTPUT);
  pinMode(s2, OUTPUT);
  pinMode(s3, OUTPUT);
  pinMode(out, INPUT);
  digitalWrite(s0, HIGH);
  digitalWrite(s1, HIGH);
  
// initialize the lcd
  lcd.init();     
  lcd.backlight();
  lcd.begin(16, 2);
  Serial.begin(9600);
  
//Boot Message  
  lcd.print("Saturn Candy Inc");
  lcd.setCursor(0,1);
  lcd.print("Plant 2, Mach 12");
  delay(100); //ADDED DELAY 3/28/19 WAS 200
  lcd.clear();
  
//Product Message
  lcd.setCursor(0,0);  
  lcd.print("Smart Connected");
  lcd.setCursor(0, 1);
  lcd.print("Candy Machine");
  delay(100); //ADDED DELAY 3/28/19 WAS 200
  lcd.clear();
  
//Initialize Machine
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Initializing");
  lcd.setCursor(0,1);
  lcd.print("Sorting Machine");
  delay(100); //ADDED DELAY 3/28/19 WAS 200
  lcd.clear();

//Begin Calibration
  lcd.setCursor(0,0);
  lcd.print("Begin Calibration");
  lcd.setCursor(0,1);
  lcd.print("Now");
  delay(100); //ADDED DELAY 3/28/19 WAS 200
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Green Blue Purple");
  lcd.setCursor(0,1);
  lcd.print("Pink Orange");
  delay(100); //ADDED DELAY 3/28/19 WAS 200
  lcd.clear();
  initCalibration(); 
}

// Loop multiple functions
void loop(){
    load();
    pos();
    readColor();
    checkColor();    
}

void initCalibration(){
  gopos(0,2);  // empty the loader for calibration
  delay(100); // //ADDED DELAY 3/28/19 WAS 200
  eject();  //delay(500);
  pos();    
  delay(150);   // Original delay was 700

  //Read Empty Color
  readColor();
 
  colors[0].red   = red;
  colors[0].green = green;
  colors[0].blue  = blue;
  
  //Serial.println("Empty: ");
  //Serial.println(String(red) + " "+ String(green) + " " + String(blue));
}

void checkColor(){

  for (int i = 0 ; i < 5 ; i++) { //5

    //  Serial.println(String(i) + ": "+ String(colors[i].red) + " " + String(colors[i].green) + " "+ String(colors[i].blue));
      
        if (  
              inRange(red,   colors[i].red   - d, colors[i].red   + d) &&
              inRange(green, colors[i].green - d, colors[i].green + d) &&
              inRange(blue,  colors[i].blue  - d, colors[i].blue  + d)   
           )
        {   
   // Color match!
          if (i==0) {
            delay(100); // Original Delay was 100
          //  eject();
            return; 
                    } 
   //Serial.println(String(red) + " "+ String(green) + " " + String(blue));
            Serial.println("Matched Color " + String(i));
        //    lcd.setCursor(0,0);
        //    lcd.print("Matched Color " + String(i));
            gopos(i,2);

            
   // Increment total pieces sorted
            ++totTotal;

   // Increment Total per Color 
          if (i==1) 
          {
              c1Total++ ;
              Serial.println("Total Sorted: " + String(totTotal));
              Serial.println("Color 1: " + String(c1Total));
              lcd.setCursor(0,0);
              lcd.clear();
              lcd.print("Tot:" + String(totTotal) +" C1 Tot:" + String(c1Total));
          }
          
          else if (i==2) 
          {
              c2Total++ ;
              Serial.println("Total Sorted: " + String(totTotal));
              Serial.println("Color 2: " + String(c2Total));
              lcd.setCursor(0,0);
              lcd.clear();
              lcd.print("Tot:" + String(totTotal) +" C2 Tot:" + String(c2Total));
          }
          
          else if (i==3) 
          {
              c3Total++ ;
              Serial.println("Total Sorted: " + String(totTotal));
              Serial.println("Color 3: " + String(c3Total));
              lcd.setCursor(0,0);
              lcd.clear();
              lcd.print("Tot:" + String(totTotal) +" C3 Tot:" + String(c3Total));
          }
          
          else if (i==4) 
          {
              c4Total++ ;
              Serial.println("Total Sorted: " + String(totTotal));
              Serial.println("Color 4: " + String(c4Total));
              lcd.setCursor(0,0);
              lcd.clear();
              lcd.print("Tot:" + String(totTotal) +" C4 Tot:" + String(c4Total));
          }
          
          eject();
          return;

          }
  }
  
  if (colors_found < tot_colors){ // Color not found, adding color to the array
    
    colors_found++;
    Serial.print("New color found! Total Colors Found: ");
    Serial.print(colors_found);
    lcd.setCursor(0,0);
    lcd.print("Colors Found: ");
    lcd.print(colors_found);
    delay(100);
    if (colors_found >= 5){ //5
      gopos(0,2);
      delay(100); //ADDED DELAY 10/9 WAS 200
      eject();
      return;
    
    }
    gopos(colors_found,2 );
    eject();
    colors[colors_found].red   = red;
    colors[colors_found].green = green;
    colors[colors_found].blue  = blue;
    return;
  }
    gopos(0,2);
    delay(100); //ADDED DELAY 10/9 Was 200
    {
              totTotal++;
              c5Total++ ;
              Serial.println("Total Sorted: " + String(totTotal));
              Serial.println("Color 5: " + String(c5Total));
              lcd.setCursor(0,0);
              lcd.clear();
              lcd.print("Tot:" + String(totTotal) +" C5 Tot:" + String(c5Total));
          }
    eject(); 
}

void readColor(){

  red = green = blue = 0;
  
  for (int i = 1; i <= rep ; i++) {
    
    digitalWrite(s2, LOW);
    digitalWrite(s3, LOW);
    red   += pulseIn(out, digitalRead(out) == HIGH ? LOW : HIGH);
    
    digitalWrite(s3, HIGH);
    blue += pulseIn(out, digitalRead(out) == HIGH ? LOW : HIGH);
    
    digitalWrite(s2, HIGH);
    green += pulseIn(out, digitalRead(out) == HIGH ? LOW : HIGH);
    
     delay(3);
  }
  
  red = red / rep;
  blue = blue / rep;
  green = green / rep;

  int sum = red + green + blue;

  red = red * 100 / sum;
  blue = blue * 100 / sum;
  green = green * 100/ sum;
  
//  Bottom of LCD Display, current sensed RGB values
  Serial.println(" ");
  Serial.println(String(red) + " " + String(green) + " " + String(blue) + " ");
  lcd.setCursor(0,1);
  lcd.println("Color: " + String(red) + " " + String(green) + " " + String(blue) + " ");
}
   
void load() {
  gopos(0,1);
}
void pos() {
  gopos(1,1);
}
void eject() {
  gopos(2,1);
  delay(100); //ADDED DELAY 3/28/19 WAS 200
  
}

bool inRange(int val, int minimum, int maximum) {
  return ((minimum <= val) && (val <= maximum));
}

void gopos(int p, int z){

  int r  = (z == 1) ? servo1.read() : servo2.read();  
  int go = (z == 1) ? s1pos[p] : s2pos[p];

  if (r == go ) return;
  
  if (go > r){

    for (int s = r; s <= go ;s++){
      if (z == 1)   servo1.write(s);
      if (z == 2)   servo2.write(s);
      delay(de);
    }
    
  }
  else{

      for (int s = r; s >= go ; s--){
        if (z == 1)   servo1.write(s);
        if (z == 2)   servo2.write(s);
        delay(de);
      } 
  }
  delay(10); //ADDED DELAY 3/28/19 WAS 90
}

I’d suggest enabling the system thread:

SYSTEM_THREAD(ENABLED);

https://docs.particle.io/reference/device-os/firmware/photon/#system-thread

I’d also suggest using a function like this to replace some of the delays:

inline void softDelay(uint32_t t) {
  for(uint32_t ms = millis(); millis() - ms < t; Particle.process());
}

It will make many calls to Particle.process(), which will maintain the connection to the Particle cloud.

2 Likes

@nrobinson2000 is correct. Another way is to not wait or delay but rather implement a finite state machine where certain states merely test for the end of a millis() based time check or you could use timers. Like this you can keep the loop cadence high.

2 Likes

@nrobinson2000 @armor Thank you for your suggestions, very much appreciated!