Frustrated with response time

Hoping someone has a moment to look at this.

I’m using a Photon to control an LED strip. To help map out patterns and such, I’m trying to write a VERY simple sketch that increases or decreases the number of LEDs lit by adjusting start and end values updated by button taps from a MIT App Inventor project.

The app has 5 buttons: Start -, Start +, End -, End +, Refresh. The first 4 increase or decrease the head or tail of the section of LEDs and that works great. From there, I added two text fields that, via a GET operation, reads the values exposed on the device. In this case: startLit and endLit. The Refresh button executes the GET, reads the values and updates the two text fields. Again, this seems to work really well. The command even works to get the values with no hiccups as the screen initializes on the phone.

Where it starts to get hairy is when I try to add the GET function to pull the values immediately after the POST function changes the value. Sometimes it works. More often though I either get an error or nothing happens, even though the values have indeed increased and I can see that properly if I hit the Refresh button. Should I expect a reasonable amount of delay in communications between a POST and a GET function? At first I thought it was an issue with the app’s block structure, but I’m starting to think it’s Particle related.

// This #include statement was automatically added by the Particle IDE.
//#define FASTLED_ALLOW_INTERRUPTS 0
#include <FastLED.h>
#include "Particle.h"

/*
  LED Map
*/
FASTLED_USING_NAMESPACE;

#define LED_PIN     D4
#define COLOR_ORDER GRB
#define CHIPSET     WS2812B
#define NUM_LEDS 300 //88 for testing, 300 for prodction
#define BRIGHTNESS  200
#define FRAMES_PER_SECOND 24

int startLit = 0;
int endLit = 0;

NSFastLED :: CRGB leds[NUM_LEDS];

void setup() {
  delay(3000); // sanity delay
  FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  FastLED.setBrightness( 10 );
  FastLED.clear();
  fill_solid(leds,NUM_LEDS,CRGB::Black);
  //leds[0] = CHSV(255,255,255);
  set_max_power_in_volts_and_milliamps(5, 1000);
  FastLED.show();
  
  Particle.variable("startLit", startLit);
  Particle.variable("endLit", endLit);
  
  Particle.function("startUpdate", startUpdate);
  Particle.function("endUpdate", endUpdate);
  
  Particle.function("addStart", addStart);
  Particle.function("subStart", subStart);
  
  Particle.function("addEnd", addEnd);
  Particle.function("subEnd", subEnd);
  }


void loop() {
    
}

int addStart(String i){
    if(startLit<endLit){
        startLit++;
    }
    updateStrip();
}

int subStart(String i){
    if(startLit>=0){startLit--;}
    updateStrip();
}

int addEnd(String i){
    if(endLit<NUM_LEDS-1){endLit++;}
    updateStrip();
}

int subEnd(String i){
    if(endLit>startLit){endLit--;}
    updateStrip();
}

int startUpdate(String newStart){
    startLit = newStart.toInt();
    updateStrip();
}

int endUpdate(String newEnd){
    endLit = newEnd.toInt();
    updateStrip();
}

void updateStrip(){
    for(int i=0;i<NUM_LEDS;i++){
        if((i>=startLit) && (i<=endLit)){
            leds[i] = CHSV(255,255,255);
        }else{
            leds[i] = CHSV(0,0,0);
        }
    }
    FastLED.show();
}

One contributing factor may be that your function callback are not returning an int which they should do.
It would be clever to return the just updated value and catch that instead of needing another request to get what you could already have.

BTW, instead of four dedicated functions I’d rather have one that actually uses the parameter to tell which action you want.
Also one single string variable that wraps both values in one request may save one extra round trip.

Another way to reduce response time would be to decouple the function calls from the actual LED update. If you let loop() take care of the update once either startLit or endLit has changed the functions could return immediately without having to wait for the LED update.

e.g.

bool needUpdate = true;
...
void loop() {
  if (!needUpdate) return;
  needUpdate = false;
  updateStrip();
}

int startUpdate(const char* newStart) {
  startLit = constrain(atoi(newStart), 0, NUM_LEDS);
  needUpdate = true;
  return startLit;
}
2 Likes

I typed this whole reply out, then you changed your response :smiley:

I was trying to avoid constant processing by adding anything into the loop, but I see how it could be useful here. I should clarify though that startUpdate and endUpdate are there strictly for being able to type a value into the Particle console and have no bearing on the function of the app and its buttons, so I could remove those entirely. The situation I’m describing with the delay between sending the function and then requesting the variable is the issue I’m concerned with.

I’ve no doubt what you’re describing is a better way to optimize the code, but it doesn’t have any effect on the speed of the add/subtract functions. startLit and endLit are both integers and those 4 functions do simple math.

Based on my observations, I can do a bajillion POST requests in a row with zero delay. Same with a bunch of GET requests. It’s just when I do a POST immediately followed by a GET, that everything just decides I’m not worthy of a response.

I still need to stress that your function callbacks don’t return a value.
While older device OS versions “accept” this (with undetermined consequences tho’) newer versions will trigger a SOS panic when you fail to do so.

I’ll give it a shot. I didn’t realize returning a value was necessary if it wasn’t strictly being used somewhere. Then again, I’m not much of a coder, I’m a visual designer and keep up on font usage more than C++ workflows.

Thanks.

With a function like this

int foo();

you are telling the compiler: "This function will return an int".
When you then don’t return that int bad things may happen :wink:

BTW, are you sure this delay is not caused by App Inventor?
Have you tried sending a bunch of requests via CLI and take the time used with that?

1 Like

good to know. Frankly, this is the first time I’ve used int, rather than void for doing anything (which also might be part of my problem, but I digress)

With regard to App Inventor, no, I’m not. Their forums are my next stop, but I’d lay money on responses there being “Are you sure this delay isn’t caused by the Particle?”. I’ll look into using the CLI. That’ll be another new thing for me. I had a reason for believing it had more to do with the Particle rather than AI, but my brain is fried and I can’t remember why now.

EDIT: for the record, I added in the returns and there was no change. /shrug

When I run a bunch of requests via CLI like this

particle call <yourDeviceName> addStart
particle call <yourDeviceName> addStart
particle call <yourDeviceName> addStart
particle call <yourDeviceName> subEnd
particle get  <yourDeviceName> startLit
particle get  <yourDeviceName> endLit
particle call <yourDeviceName> subEnd
particle call <yourDeviceName> subEnd
particle get  <yourDeviceName> startLit
particle get  <yourDeviceName> endLit

I cannot make out a lot of difference between the individual requests.

BTW, this is a slightly reworked version of your code to illustrate what I meant with my other suggestions
https://go.particle.io/shared_apps/5fcaf335483a480009a30106

I see. Thanks for the share.

I just consolidated a bit more on my own so that there’s only a single function

int doUpdate(String command){
    if(command=="addStart"){
        if(startLit<endLit){
            startLit++;
        }
    }else if(command=="subStart"){
        if(startLit>=0){
            startLit--;
        }
    }else if(command=="addEnd"){
        if(endLit<NUM_LEDS-1){
            endLit++;
        }
    }else if(command=="subEnd"){
        if(endLit>startLit){
            endLit--;
        }
    }
    updateStrip();
    return 1;
}

I should probly go a step further and do a switch case method, but that’ll happen when everything else is working so I’m not stepping on my own toes. I’ll install and play with the CLI, but based on all this conversation, it’s looking more and more like an issue with the App Inventor.

1 Like