Passing std::string, getting same value each time

Hi good people,

fairly new to the party, also not sure if I should be posting this here or in an R Pi forum, but here goes...

Using Arduino MBED on a Raspberry Pi Pico, and struggling with strings.... Essentially I have a vector of std::string, used for storing lines of text, which are displayed on an LCD screen for a data logger type of situation.

My problem is whenever I pass a new log event to my function, the value of the text shows is always the same as the first log entry.

I am sure it's due to how I am (probably wrongly) using strings, or not using pointers... I am not sure and hoping if someone can point out the error of my ways, I will be back on track...

Here's the pertinent code:

std::vector<std::string> vLogs;
const int displayRows = 29;


void loop() {

  // read from port 0:
  if (Serial1.available()) {
    String logStr = Serial1.readStringUntil('\r');
    appendLog(logStr.c_str());
  }
  updateDisplay();
}


std::string timeNow()
{
return padZeros(uptime::getMinutes()) + ":" + padZeros(uptime::getSeconds());
}

void appendLog(std::string eventLog) {
vLogs.insert(vLogs.begin(), timeNow() + " " + eventLog);
//vLogs.insert(vLogs.begin(), eventLog);
if (vLogs.size()>=displayRows)
{
vLogs.pop_back();
}
}

In practice, I can send the following lines in over UART:

"Here is log event 1"
"Here is log event 2"
"Here is log event 3"

and my display will show:

00:30 Here is log event 1
00:21 Here is log event 1
00:00 Here is log event 1

Any advise greatly appreciated.

Please post a small, complete code that compiles and demonstrates the problem.

I have omitted the libs for the TFT LCD panel, and commented out the code that relies on them in order to get it to compile:

#include <Arduino.h>
#include <string>
#include <vector>
#include "uptime.h"
//#include <SPI.h>
//#include <TFT_eSPI.h> // Hardware-specific library


std::vector<std::string> vLogs;
const long intervalUpdate = 100;
const long intervalTimer = 200;
unsigned long previousMillisUpdate = 0;
unsigned long previousMillisTimer = 0;
unsigned long currentMillis = millis();
const int displayRows = 29;


void setup(void) {
  Serial1.begin(57600); // UART0 serial at TX=GP0, RX=GP1
  tftSetup();
  appendLog("Ross2D2 Body control started");
 
  }

void loop() {
tftLoop();

  // read from port 0:
  if (Serial1.available()) {
    String logStr = Serial1.readStringUntil('\r');
    appendLog(logStr.c_str());
  }

  //printTest();
  updateDisplay();
}


std::string padZeros(unsigned long input)
{
std::string result;
result = std::to_string(input);
unsigned int number_of_zeros = 2 - result.length();
result.insert(0, number_of_zeros, '0');
return result;
}


void printTest(){
if (currentMillis - previousMillisTimer >= intervalTimer) {
  previousMillisTimer = currentMillis;
appendLog("New log entry");
}
}


void updateDisplay(){
  if (currentMillis - previousMillisUpdate >= intervalUpdate) {
  previousMillisUpdate = currentMillis;
 // tft.setCursor(0, 0, 2);

for (auto & element : vLogs) {
 //   tft.println(element.c_str());
}

//write update

//tft.setCursor(0, 465, 2);
  //First call calculate_uptime() to calculate the uptime
  //and then read the uptime variables.
  char buf[50];
  sprintf(buf,"Ross2D2 Uptime %d Hrs %d Mins %d Secs",uptime::getHours(),uptime::getMinutes(),uptime::getSeconds());
//tft.println(buf);

}//end if
}//end updateDisplay


std::string timeNow()
{
return padZeros(uptime::getMinutes()) + ":" + padZeros(uptime::getSeconds());
}

void appendLog(std::string eventLog) {
vLogs.insert(vLogs.begin(), timeNow() + " " + eventLog);
//vLogs.insert(vLogs.begin(), eventLog);
if (vLogs.size()>=displayRows)
{
vLogs.pop_back();
}
}

void tftLoop()
{
currentMillis = millis();
uptime::calculateUptime();
}


void tftSetup()
{
 // tft.init();
//  tft.setRotation(2);
  //tft.invertDisplay(1);//comment out for DFRobot board
//  tft.fillScreen(TFT_BLACK);
  
  // Set the font colour to be white with a black background, set text size multiplier to 1
 // tft.setTextColor(TFT_WHITE, TFT_BLACK);
 // tft.setTextSize(1);
}

But now your (poorly-indented) code doesn't do anything with the vLogs vector except insert at the beginning and pop out the back. No attempt to print the log entries ... which I thought was the original problem.

Please pare this down to the bare minimum code that actually demonstrates the problem. Don't comment out unused #includes and functions, that just makes clutter. Delete them. I don't have your hardware, so substitute for or simulate the (unnecessary) uptime library functions.

This seems to be the essence of what you're trying to do:

#include <Arduino.h>
#include <string>
#include <vector>

void insertEntry(std::string s);
void printLog();

std::vector<std::string> vLogs;

void setup() {
  Serial.begin(115200);
  delay(1000);

  insertEntry("123");
  insertEntry("Testing");
  insertEntry("World");
  insertEntry("Hello");
  printLog();
}

void insertEntry(std::string s) {
  vLogs.insert(vLogs.begin(), s);
}

void printLog() {
  for (auto &e : vLogs) {
    Serial.println(e.c_str());
  }
}

void loop() {
}

It works as expected on an Adafruit ESP32 Feather:

Hello
World
Testing
123

If that's not the problem you're having, please explain the issue more clearly.

OK - in your example, you are declaring the elements in the vector, it all works fine.

My problem, I think, is in how I am passing the string to the function which puts the string into the vector, (void appendLog(std::string eventLog) {})

I've been racking my brains but struggling to get my head around string functions, but that must be where the problem lies.

If it helps, I identified today that my serial listener was actually passing an empty string... I fixed that, and now the vector elements are not identical, but they have the first part of the string overwritten by the latest element added:

For example if the serial function receives 3 lines:

This is the first string!
And the 2nd.
3rd.

Then my vector looks like this:

This is the first string!
And the 2nd.first string!
3rd. is the first string!

I'm off to read more on strings in C++....

OK - whilst I enjoyed learning about strings / char in c++, I was totally barking up the wrong tree.

The problem was not in my handling of strings, rather me not realising that my TFT display did not clear the pixels in the background of a new line of displayed text.

Problems solved by padding out my string with blank space before writing to the display.

Thanks for your assistance.

Ross

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.