Wifi Disconnecting in setup

Hi all,

This is my code running in photon,…
For some reason in the setup while running the selection in the knob the wifi keeps disconnecting.

#include "application.h"


//#include <servo.h>
Servo myServo;
int pos = 0;

int statusserv = 0;

int posit = 140;

#include "clickButton.h"

 #define outputA A5
 #define outputB A4
 int counter = 1; 
 int aState;
 int aLastState;  
 int function = 0;

const int buttonPin1 = A3;
ClickButton button1(buttonPin1, LOW, CLICKBTN_PULLUP);


const int  DripPin = A2;
int progress = 100;

int dropCount = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button


int counttoml = 0;  //keeps the count of ml dripped
int temp = 0;       // used for converting drop count to ml
int botml = 500;
int mlleft = 0;  //keeps the count of ml left in the bottle
int perc = 100;
char stats;

unsigned long previousledMillis = 0;
const long ledinterval1 = 500;  // for below 50 ml
const long ledinterval2 = 250; // for below 25 ml
int ledState = LOW; 


unsigned long previousMillisdata = 0;

void pushdata()
{
    String deviceID = "deviceNum1";
    int value1 = perc, value2 = dropCount; 
    char value3 = stats;
    
    String data = String::format("{ \"id\": \"%s\", \"perc\": %d, \"dropCount\": %d, \"status\": \"%c\", \"botml\": %d }",
                                    deviceID.c_str(), perc, dropCount, stats, botml);

    Particle.publish("status", data, PRIVATE);
}


void knobselect()
{
       aState = digitalRead(outputA); // Reads the "current" state of the outputA
   // If the previous and the current state of the outputA are different, that means a Pulse has occured
   if (aState != aLastState){     
     // If the outputB state is different to the outputA state, that means the encoder is rotating clockwise
     if (digitalRead(outputB) != aState) { 
       counter ++;
     } else {
       counter --;
     }
           if (counter == 31) 
   {
       counter = 1;
   }
    if(counter == -31)
   {
       counter = -1;
   }
     Serial.print("Position: ");
     Serial.println(counter);
     String myString = String(counter);
     Particle.publish(myString,"myString");
     
    if (counter <= 3)
    {

    }
    if ((counter > 3)  && (counter <= 8))
    {
        botml = 50;
    }
    if ((counter > 8)  && (counter <=13))
    {
        botml = 100;
    }
        if ((counter> 13)  && (counter <= 18))
    {
        botml = 250;
    }
        if ((counter> 18)  && (counter <=23))
    {
        botml = 1000;
    }
        if (counter> 23)  
    {
        botml = 500;
    }
   } 

   aLastState = aState; // Updates the previous state of the outputA with the current state
   
}

void selectml()
{
  pinMode(D1, INPUT_PULLUP);
  // Setup button timers (all in milliseconds / ms)
  // (These are default if not set, but changeable for convenience)
  button1.debounceTime   = 20;   // Debounce timer in ms
  button1.multiclickTime = 250;  // Time limit for multi clicks
  button1.longClickTime  = 3000; // time until "held-down clicks" register
  

  while(function != 2)
  {
    button1.Update();
    function = button1.clicks;
        if (function == -1)
    {
        System.reset();
    }
  }
    Particle.publish("Double click");
      counter = 1;
      digitalWrite(D7,HIGH);
      
      
      while(function != 1)
    {
      
      knobselect();
      button1.Update();
      function = button1.clicks;
          if (function == -1)
    {
        System.reset();
    }
    }
    Particle.publish("Single click");
    String myString1 = String(botml);
    Particle.publish(myString1,"myString");
    digitalWrite(D7,LOW);
    
} 

void mainprog()

  {
    

  // read the pushbutton input pin:
  buttonState = digitalRead(DripPin);

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH) {
      // if the current state is HIGH then the button went from off to on:
      dropCount++;
      temp++;
     String myString2 = String(dropCount);
     Particle.publish(myString2,"myString");
    } 
    else {
      // if the current state is LOW then the button went from on to off:
   //   Serial.println("off");
    }
        // Delay a little bit to avoid bouncing
    delay(50);
  }
    // save the current state as the last state, for next time through the loop
  lastButtonState = buttonState;

  if (temp == 12)
  {
    counttoml++;
//    mlleft = 500 - counttoml;
    mlleft = botml - counttoml;
     if (mlleft <= 49)
  {
      myServo.write(140);
  }
    perc = (mlleft*100)/botml;
         String myString3 = String(mlleft);
     Particle.publish(myString3,"mlleft");
          String myString4 = String(perc);
     Particle.publish(myString4,"percentage");
   // Serial.print("The amount of liquid left: ");
   // Serial.print(mlleft);
   // Serial.println("ml");
    temp = 0;
    progress = mlleft;
  }
 

  
  if (perc >= 20)
  {
    ledState = LOW;  
    stats = 'G';
   }
  if (perc <= 19 )
  {
    unsigned long currentledMillis = millis();
    if (currentledMillis - previousledMillis >= ledinterval1) {
    // save the last time you blinked the LED
    previousledMillis = currentledMillis;
    stats = 'Y';

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }
  }
  }
   if (perc <= 10 )
  {
    unsigned long currentledMillis = millis();
    if (currentledMillis - previousledMillis >= ledinterval2) {
    // save the last time you blinked the LED
    previousledMillis = currentledMillis;
    stats = 'R';
    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }
  }
  }
  digitalWrite(D7, ledState);
  
  }




void setup() {
 pinMode(DripPin,INPUT);
 pinMode(D7,OUTPUT);
 digitalWrite(D7,1);
 Serial.begin(115200);
 myServo.attach(D0);
 myServo.write(0);
 
 //knob code init
   pinMode (outputA,INPUT);
   pinMode (outputB,INPUT);
   aLastState = digitalRead(outputA);
   selectml();
 //  myServo.write(0);  
 
}

void loop() {
    
    
    button1.Update();
    function = button1.clicks;
    if (function == -1)
    {
        System.reset();
    }

     if (function == 3){
         if (posit == 140)
         {
         posit = 0;
          /*  for (posit = 140; posit >= 0; posit -= 1) { 
            myServo.write(posit);              
            delay(5); 
        }*/
         
         }
          else if(posit == 0){
 //             else{
             posit= 140;
          /*  for (posit = 0; posit <= 140; posit += 1) { 
            myServo.write(posit);              
            delay(5);  
        }*/
             }
     String myString6 = String(posit);
     Particle.publish(myString6,"myString");
               myServo.write(posit);
         }
   
     
     
     mainprog();
        unsigned long currentMillisdata = millis();
    if (currentMillisdata - previousMillisdata >= 10000)
    {
    previousMillisdata = currentMillisdata;
    pushdata();
    }
}

How do I rectify this
Thank You
AKshay

That’s a lot of code to plough through (especailly with off indendations).
But one thing I see (or rather can’s see) is that the Particle.publish() rate limit doesn’t seem to be taken care of.

One off-the-rack solution against dropping connections is SYSTEM_THREAD(ENABLED), but you should still try to locate the block that keeps the code flow occupied for extended periods which is usually the reason for dropping connections.
Especially your while() loops would be my main suspects.

2 Likes

Sorry for being less specific,
Even I guess the while loop is the issue though,can we use Particle.connect() in the loop to keep it connected?
is there any alternative for while loop? because the applications need the user to choose using the encoder in the beginning before running the actual setup.

Thanks

Actually Particle.process() would be the command you need to be calling when your code is trapped in a loop for extended periods.
But it would actually be best to adopt non-blocking coding schemes.

Thanks good to know that such a function exists!
But the Particle.process() is a blocking function(Just Found out).
In my application I am running the selection code,..
Can do the selection part without a while loop?

Also I guess the connection lasts some 20 secs..
https://docs.particle.io/reference/firmware/photon/#automatic-mode

Why can't I use a millis based delay function to call Particle.process() every 19 seconds or so...

Thanks for the support!

Not sure what you mean by that. Paricle.process() isn't really blocking but takes up to 1ms to execute (due to potentially pending cloud requests).
If you consider this blocking you'd need to consider every function blocking while it's running straight through.

Particle.process() is meant to keep the connection from breaking off due to failing to report back to the cloud at least every 10 seconds (more ofthen = better). So calling it only every 19 seconds is not really helping the once-per-10-seconds, is it?
The 20 second statement goes (AFAIK) for the actual loss of connection, but the device will "fell orphaned" already after half that time and hence not perform "undistracted" :wink:

Sure, you can.

BTW, the ClickButton sampel code shows that the library can full well be used in a non-blocking manner. And that's the way it is meant to be used.

3 Likes