Problem with repeated writing to String variable

I am doing a conditional write to a String variable (myUrl) based on input from a float switch. The first time I change the state of the float everything my String variable concatenates myChannel & "field1=" & bypstate (based on the status of the float switch). For every subsequent change in the position of the float my String is missing the myChannel &"field1=" and only shows bypstate when I Serial.println(myURL).

First time I move the float switch I see this on the monitor:
http://184.106.153.149/update?key=XXXXXXXXXXXXX&field1=0
every subsequent change I see this:
1
then this
0
and so on

I am very new to C++ and am probably missing something obvious but this has stumped me all day.

boolean bypassstate = false;

String bypdatarecord = "test"; //initializing variable

String myUrl;
String myChannel;


void setup() {

  

pinMode(floatPin,INPUT);
myChannel = "http://184.106.153.149/update?key=XXXXXXXXXXX"; //this is specific to Thingspeak channel
myUrl= "";

digitalWrite(floatPin,HIGH); // turn on internal pull-up on the floatPin


void loop() {

//read the float switch
int flt_switch = digitalRead(floatPin); //read input value
String bypstate;  
if (flt_switch == HIGH) {
  digitalWrite (ledPin,LOW);
  if (bypassstate == true) {
      bypstate = String(flt_switch);

    myUrl=String(myChannel + "&field1=" + bypstate);
    Serial.println(myUrl);

  }
}
else{
  digitalWrite (ledPin,HIGH);   //off to save memory

  if (bypassstate == false) {
    bypstate = String(flt_switch);

    myUrl=String(myChannel + "&field1=" + bypstate);
    Serial.println(myUrl);
}
}

Any feedback would be greatly appreciated.
Thanks

First suggestion, stop using String. All this concatenation will could a heck of a lot of memory allocation. Why not use a string? (See the difference?) And it depends a lit on what you want to do with the string afterwards but for a lot of applications it doesn't matter is you send a concatenated string or just the pieces after each other.

Serial.println("This is kind of a long string but okay");
//is the same as
Serial.print("This is ");
Serial.print("kind of a lo");
Serial.print("ng st");
Serial.print("ring b");
Serial.print("ut ok");
Serial.println("ay");

Next, how is bypassstate supposed to ever change?

And you don't act on the switch becoming high or low but you try to do this EVERY loop(). So thousands of times a second! Look for state change detection.

I'd recommend that you print MORE data. You have two identical print statements, so you haven't a clue which one was executed. Clear that up, and a clue by four just might whack you.

And, stop using Strings. They are for lazy people that think they have a couple of terabytes of SRAM. That's not you, is it?

Looking through my post I realize that in trying to focus on the String writing portion I cut out some other key things. I have a delay built in so this does not run thousands of times per second but it waits 60 seconds before running again. I am using bypassstate as a latch so it only tries to write to myUrl when the state of the float switch changes.

if (flt_switch == HIGH) {
if (bypassstate == true) {
    
    bypstate = String(flt_switch);
    Serial.println(bypdatarecord);
    bypassstate=false;
    
    myUrl=String(myChannel + "&field1=" + bypstate);
    Serial.println(myUrl);
  }
}

PaulS, yes, I am printing a lot right now as a way for me to watch progress and an attempt to track down the missing link. I can tell the difference in myUrl as bypstate changes from 1 to 0 and back each time I try to write to it.

I will try string instead but I guess my question still remains. I have enough memory to run my simple program but don't quite understand why the concatenation only works the first time.

bypassstate is always false. What is supposed to set it to true?

Hard to help troubleshoot your code when you don't give all of your code to troubleshoot.

There is a second chunk of code that does the inverse. Under the tips for posting it says to focus on the areas of concern rather than posting hundreds of lines of code so I was trying to just focus on the problem area (in my first post). My following post was just to clarify for Septillion's question. Again, my problem is not getting bypassstate to change when I want it to, my issue is getting the program to properly concatenate the String myUrl more than the first time it loops through. I know my program is going through the "if" statements ok because it is also updating a rtc variable I have and it modifies bypstate when ever the float changes position.

bberko34:
I have a delay built in so this does not run thousands of times per second but it waits 60 seconds before running again.

Why, do you like wasting resources? Or lag? Just only act when you need to but let it run so you can act directly if you want to.

bberko34:
I have enough memory to run my simple program but don't quite understand why the concatenation only works the first time.

How did you check? HINT: the compiler will NOT tell you :wink:

bberko34:
Under the tips for posting it says to focus on the areas of concern rather than posting hundreds of lines of code

It absolutely does not! Let me quote it for you:

Aka, zooming in on the problem is good. But do that by making a small compilable / workable sketch! Because the extra (free) tip that follows is

septillion:
How did you check? HINT: the compiler will NOT tell you :wink:

This comment reflects my low level of understanding. I was assuming that since the compiler says I am fine that I would be fine. I have no idea how to check so off to Google with this one.

septillion:
It absolutely does not! Let me quote it for you:
Aka, zooming in on the problem is good. But do that by making a small compilable / workable sketch! Because the extra (free) tip that follows is

Guess I should have read that more thoroughly.

I will dig into using string as opposed to String and how to check memory usage

About the memory, the compiler does give you a hint :wink:

Global variables use 238 bytes (11%) of dynamic memory, leaving 1810 bytes for local variables.

But, I agree it doesn't tell the complete story. What it should read in my opinion is

Global variables use 238 bytes (11%) of dynamic memory, leaving 1810 bytes for dynamic allocated variables.

Local variables are a form of dynamically allocated memory. But the good thing about a local variable is that is will be freed the moment the function it belongs to goes out of scoop. But a String has no fixed size. It will allocate what it need each time you add something. But if the meory after it is already used the whole string is moved to a new location where it does fit.

Look at the memory as a book case. Each thing you want to store is a book and you fill that book case in order, let's say from top left to bottom right. You place each book after the other. The moment you free the memory is like you throw away the book but you don't shift all the books to leave no gap. That would mean a heck of a lot of work! No, it leaves a gap.

String is like a encyclopedia, it takes up the space of multiple books. And each time you add something to the string you need to add an extra book to your encyclopedia. But if there is already a book after the encyclopedia that would not fit. So you move the whole encyclopedia to the end of you book case and you can add the book. But the gap it left a couple of shelf's above is never filled because you only fill it at the end. And this happens each time the encyclopedia isn't the last thing in the book case leaving multiple wholes. And if the encyclopedia or string is big you pretty fast run out of space at the end of the book case :wink:

A string on the other hand is like multiple book but even if you don't own the full series you already reserve the room for the rest of the books so you know it will fit. :smiley:

Thanks for taking the time to explain the memory allocation. The bookshelf analogy makes perfect sense. Off to edit with string and local variables.