delay on bridge not working

So I'm trying to delay the bridge looking at a client for 20 seconds while it continues to run the rest of the code in the while loop but when I test it, it immediately is looking for new clients and when I try to check elapsed time on serial print it doesn't show up. I'm not sure how to fix it this is my entire code

#include <Bridge.h>
#include <BridgeServer.h>
#include <BridgeClient.h>

BridgeServer server;

void setup() {
  Bridge.begin();
  server.listenOnLocalhost();
  server.begin();
  
  
}
void loop() {
BridgeClient client = server.accept();
  if (client) {
    process(client);
    client.stop();
  }
}
void process(BridgeClient client) {
  String command = client.readStringUntil('/');
  if (command == "analog") {
    analogCommand(client);
  }
}
unsigned long starttime = millis();
void analogCommand(BridgeClient client) {
  int pin, value;
  pin = client.parseInt();
  if (client.read() == '/') {
    value = client.parseInt();
    float P = 80; // period of the pulse (dont go below 50)
    float DC = {value / 255.00}; // duty cycle
    while (value >= 0) {
      if(value == 0){
      analogWrite(pin,0);}
      else{
      analogWrite(pin, 255);
      delay(P * DC);
      analogWrite(pin, 0);
      delay(P * (1 - DC)); 
      }
      unsigned long currenttime = millis();
      unsigned long elaspedtime = currenttime - starttime;
      Serial.println (elaspedtime);
      //LOOKING FOR a new client
      if (elaspedtime >= 20000)
      {
      BridgeClient client = server.accept();
      if (client) {
        process(client);
        client.stop(); }
      }
    }
  }

So I managed to get it to work a few times but it stops working after only a couple of changes and I'm not sure why or how to fix it this is my new code.

#include <Bridge.h>
#include <BridgeServer.h>
#include <BridgeClient.h>
#include <Console.h>

BridgeServer server;

void setup() {
  Bridge.begin();
  server.listenOnLocalhost();
  server.begin();
  Console.begin();
  
}

void loop() {
while (!Console){}
BridgeClient client = server.accept();
  if (client) {
    process(client);
    client.stop();
  }
}
void process(BridgeClient client) {
  
  String command = client.readStringUntil('/');
  if (command == "analog") {
    analogCommand(client);
  }
}

void analogCommand(BridgeClient client) {
  unsigned long starttime = millis();
  int pin, value;
  pin = client.parseInt();
  if (client.read() == '/') {
    value = client.parseInt();
    float P = 40; // period of the pulse (dont go below 50)
    float DC = {value / 255.00}; // duty cycle
    while (value >= 0) {
      if(value == 0){
      analogWrite(pin,0);}
      else{
      analogWrite(pin, 255);
      delay(P * DC);
      analogWrite(pin, 0);
      delay(P * (1 - DC)); 
      }
      unsigned long currenttime = millis();
      unsigned long elaspedtime = currenttime - starttime;
      Console.println(elaspedtime);
      //LOOKING FOR a new client
      if (elaspedtime >= 10000)
      {
      BridgeClient client = server.accept();
      if (client) {
        process(client);
        client.stop(); }
      }
    }
  }

}[code]

rcvolley:
So I'm trying to delay the bridge

Why would you want to do that? In general, using delay() is a bad thing. And the way you have it here, it seems to be even worse.

rcvolley:
So I managed to get it to work a few times but it stops working after only a couple of changes

What do you mean by "a couple changes?" Code changes? Or making a few client connections to change the duty cycle value? If the latter, I'm sure it's because of the recursive nature of your client process calls.

As mentioned in one of your other threads, accepting a client connection and calling the process() function while you are already in the process() function is a really bad idea. When you get the first connection, loop() calls process(), which calls analogCommand(), which then stays there while you are in your loop making delay() calls and checking for another connection. When a connection comes in, you are still inside all of these functions and you call process() again, which calls analogCommand() again, and stays in that function in the while loop. This continues each time another connection is made: each connection adds another set of calls to these functions. So every time you make another connection, it uses up a good chunk of stack space, and it won't take too many iterations to overflow the stack and crash the application.

After just three client updates, your stack will have:

  • loop(), called from main()
  • process(), called from loop()
  • analogCommand(), called from process()
  • process(), called from analogCommand()
  • analogCommand(), called from process()
  • process(), called from analogCommand()
  • analogCommand(), called from process()
    After just three client connections, you will have 7 function call contexts on the stack. Each context will have the function return information, plus a copy of any local variables for each call - process() has a String variable, while analogCommand() will have three unsigned longs (starttime, currenttime, and elapsedtime), two integers (pin, value), and two floats (p, and DC.) That's a lot of data for each context, and you will have multiple copies of each context on the stack. Each time you make a client connection, you will add two more function call contexts and another copy of all of that local data. You are guaranteed to quickly run out of memory and crash the sketch.

I think you need to take a step back and reconsider the logic and layout of your sketch.

A general rule of thumb is that you should design things so that it doesn't spend a significant amount of time in the loop() function. When loop() is called, it should do what it needs to do, and then get out. A general rule of thumb is that you shouldn't have any lengthy() loops or delay() calls in you loop() function or in any function called from loop(). Also, you shouldn't have recursive calls where a function calls itself, either directly or indirectly, unless you are experienced and you really know what you are doing. Used with care, recursion can get you out of a difficult situation in some cases, but in general it can cause lots of problems.

Your process() function, and the helper functions it calls, like analogCommand(), should parse the incoming data, set up some variables to keep track of the requested operation, and then get out. If it's a trivial operation, like setting the state of an output pin, it can be handled directly in the helper function. But if it's a more lengthy operation like your while loop with the delay() calls, it should not be done in the helper function. Instead, the function should set a global variable with the requested duty cycle, and then return. A separate function called from the loop() function should then use that duty cycle value to control the output, preferably without the use of the delay() function, but instead using the concepts from the BlinkWithoutDelay tutorial. If you decide you simply must use delay(), then only do one iteration of the loop - the loop() function is called repeatedly from a while loop that you can't see. Rather than add your own while loop, you should make use of the fact that the loop() is already called over and over again, and you should do at most one iteration of you loop per loop() call. (It would be better if you used the BlinkWithoutDelay model and do even less per loop() call.)

Long story short: if you keep trying to process another client connection from inside an existing client connection, I don't think you will ever be able to get this sketch working properly. This is especially true if that is being done inside a while loop with the delay() calls in it. You really do need to redesign this sketch from scratch, using the advice in the previous paragraph.

So I'm now trying to get it to work with the blinky example instead and its not working when I plug in a number into the bridge command http://192.168.240.1/arduino/analog/5/23 (the purple number is the number I change the 5 is the pin number) it will emit a very dim light that comes up with the same no matter what I enter at first or what I change it to later I cant tell where I'm going wrong and am hoping someone else might be able to see it.

here's my full code

#include <Bridge.h>
#include <BridgeServer.h>
#include <BridgeClient.h>


BridgeServer server;
int value;
int pin;
unsigned long previousmillies = 0;
int ledState = LOW;
void setup() {
 Bridge.begin();
 server.listenOnLocalhost();
 server.begin();
 Console.begin();
}  
unsigned long currentmillies = millis();

void loop() {
 BridgeClient client = server.accept();
 if (client) {
   process(client);
   client.stop();
 }
 if (currentmillies - previousmillies <= value) {
   analogWrite(pin, HIGH);
   
 }
 if (currentmillies - previousmillies >= value) {
  analogWrite(pin, LOW);
  previousmillies = currentmillies;
 }
 
 
}
void process(BridgeClient client) {

 String command = client.readStringUntil('/');
 if (command == "analog") {
   analogCommand(client);
 }
}
void analogCommand(BridgeClient client) {
 pin = client.parseInt();
 if (client.read() == '/') {
   value = client.parseInt();
   client.println("always use pin 5");
 }
}

rcvolley:

 if (currentmillies - previousmillies <= value) {

analogWrite(pin, HIGH);
 
}
if (currentmillies - previousmillies >= value) {
 analogWrite(pin, LOW);
 previousmillies = currentmillies;
}

This code looks suspicious.

Let's work out what happens: when the sketch starts executing, previousmillies will be zero, as it is initialized to that value when it is declared. currentmillies will also be zero (or very close to it) since it is initialized to millis() when it is declared as a global variable between the setup() and loop() functions. the pin and value variables are also declared as a global variable, but it is not initialized, so we don't know what value they will have on startup. Since they will have random values, strange things may happen until the first time you make a request to the Yun.

With value being an unpredictable number between 0 and four billion, the odds are high that it will be larger than the very small (probably zero) value of currentmillies which was assigned during startup. The difference between currentmillies (which is very small) and previousmillies (which is zero) is likely to be less than the unknown value of value, therefore analogWrite() will be called to set the pin (unknown value) to HIGH (which is a defined constant with the value 1. analogWrite() generates a PWM signal where the duty cycle can range from 0 (always off) to 255 (always on.) With the value of HIGH, it will result in a waveform that is on for 1/255 of the time, which equates to a very dim light.

Now, the real problem is that while currentmillies is set to millis() during system startup, this only happens once (because the call to millis() is outside of any function call) so currentmillies never changes. Therefore, currentmillies will never change, and you won't hit the clause where the difference is greater than value.

To get that part working, you will need to set currentmillies to millis() at the beginning of the loop() function, before you do any of your comparisons.

But that will probably not be enough. If currentmillies() keeps advancing due to assigning it inside the loop() function, you will be repeatedly calling analogWrite(pin, HIGH) until the difference between currentmillies and previousmillies becomes equal to value. When it does, you will call analogWrite(pin, HIGH) one last time, and then it will satisfy the second IF statement: this will call analogWrite(pin, LOW) to set the output to zero percent duty cycle (off) and then update previousmillies.

On the next pass through loop(), the difference between currentmillies and previousmillies will once again be below value, so it will once again call analogWrite(pin, HIGH). The net result is that the output will be off for one pass through the loop() function, which is likely to be a fraction of a microsecond. You will never see the effect of that.

To fix this:

  • you need to add currentmillies = millis(); to the beginning of the loop() function
  • you probably want to be using digitalWrite() instead of analogWrite(). If that's the case, you will also need to add a call to pinMode() in your setup() function to make the pin an output since digitalWrite() doesn't force output mode like is done with analogWrite()
  • you probably want to have the output off for more than a fraction of a microsecond, so you will probably want to rework that logic

What is it that you are actually trying to do? It seems like you want to blink an LED with a specific on time in milliseconds, but how long is your intended off time?