Converting long long / uint64_t to string or char

Struggling to convert this and the only other question I can find was this fairly unhelpful one

I get the unix time (in s) but because I take many samples per second I convert this to ms then add millis() to it. This works fine as far as getting a unique timestamp goes, but it needs to be converted into a string for MQTT to handle.

I have tried some of the solutions in the linked thread such as this

void publishJson() {
  char buffer[15];
  measurement_time.toCharArray(buffer, 13);

  String jsonString = "{";
  jsonString += "\"measurement_time\":" + String(buffer) + ",";
  jsonString += "}";
  Serial.println(jsonString);
}

and get the complie error -
error: request for member 'toCharArray' in 'measurement_time', which is of non-class type 'uint64_t {aka long long unsigned int}' measurement_time.toCharArray(buffer, 13);

my original error is:

Compilation error: call of overloaded 'String(uint64_t)' is ambiguous

Try using sprintf to see if unsigned long long is supported.

void setup(){
  char  buffer[21]; //maximum value for uint64_t is 20 digits
  sprintf(buffer, "%llu", number);

You could just do it manually

uint64_t val = measurement_time;
char buffer[15];
uint8_t ndx = 15;
while (ndx) {
  ndx--;
  uint8_t v = val % 10;
  val = val  / 10; 
  buffer[ndx]  = v + '0';
}

Be careful to include the terminating null at the end of the buffer, variables declared inside a function will not be automatically initialized to all zeros.

Ah sorry, good point ! , so that would be

uint64_t val = measurement_time;
char buffer[15];
uint8_t ndx = 14;
buffer[ndx] = '\0';
while (ndx) {
  ndx--;
  uint8_t v = val % 10;
  val = val  / 10; 
  buffer[ndx]  = v + '0';
}

and afterwards

if (val) ERROR

Tried sprintf on a Mega and an UNO R4 WiFi, does not support unsigned long long on either.

Need to be careful of the buffer size, and allow for the number of digits being less than the full buffer. Safer to use a buffer that will fix the maximum size of a uint64_t.

  uint64_t val = measurement_time;
  char buffer[21];
  char* ndx = &buffer[sizeof(buffer) - 1];
  *ndx = '\0';
  do {
    *--ndx = val % 10 + '0';
    val = val  / 10;
  } while (val != 0);
  Serial.println(ndx);

This is a reduced form of the code used by Print for uint32_t

size_t Print::printNumber(unsigned long n, uint8_t base)
{
  char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
  char *str = &buf[sizeof(buf) - 1]; 

  *str = '\0';

  // prevent crash if called with base == 1
  if (base < 2) base = 10; 

  do {
    char c = n % base;
    n /= base;

    *--str = c < 10 ? c + '0' : c + 'A' - 10; 
  } while(n);

  return write(str);
}

Works on an ESP32:

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

  uint64_t x = 17179869184;
  Serial.printf("x = %llu\n", x);
}

void loop() {
}
x = 17179869184

@trap-fish, if the code in Post #8 doesn't work on your platform, then you can use one of the roll-your-own solutions presented above to get a character string decimal representation.

There's also a more efficient option if you're OK with time stamps presented as a character string HEX representation:

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

  uint64_t x = 4330422113570437784;
  uint32_t lower = x & 0xFFFFFFFF;
  uint32_t upper = (x >> 32) & 0xFFFFFFFF;
  Serial.printf("x = 0x%08X%08X\n", upper, lower);
}

void loop() {
}
x = 0x3C18BFF7FEDCBA98

However, I think I've seen some posts that say AVR-based platforms have a problem shifting 64-bit integers. If you run across that, then you could go with:

void setup() {
  Serial.begin(115200);
  delay(2000);
  uint32_t lower;
  uint32_t upper;

  uint64_t x = 4330422113570437784;
  uint8_t *ptr = reinterpret_cast<uint8_t *>(&x);
  memcpy(&upper, ptr + sizeof(uint32_t), sizeof(uint32_t));
  memcpy(&lower, ptr, sizeof(uint32_t));
  Serial.printf("x = 0x%08X%08X\n", upper, lower);
}

void loop() {
}
x = 0x3C18BFF7FEDCBA98

As I mentioned above, either of the HEX solutions are more efficient than trying to get a decimal representation.

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