sprintf missing one parameter [SOLVED]

Hello,
I am having trouble with sprintf. In order to get a second parameter, I must add a middle value (kk) which will return zero, and then the thirds value will have the correct value.

  double SumPower = 0;            // Energy Meter - Accumulator
  static double energyStartPower = 0;
.
more code
.
double consumo = (SumPower - energyStartPower);
.
.more code...
.
char buff[60];
sprintf(buff, "c:END,seconds:%d,kk:%u,power:%u", seconds,(int)consumo,(int)consumo);      // d=define   ld=long   u=int

the variable "consumo" is a double. However, I have tried with long, int, unsigned long. Same thing happens always.

see the serial output picture.
2016-01-07 22_35_13-COM26.jpg
as you can see, even sending the exact same variable, the output of the buffer is different.

if I remove the "kk" parameter, then the "power" parameter will show zero.

any idea why this is happening?
thanks a lot

edit: see solution at the end of the thread

2016-01-07 22_35_13-COM26.jpg

The sprintf format string in your code expects three parameters (one signed int, two unsigned ints), so you need to supply three.

What is the actual value of "consumo"?

sprintf does not handle floats or doubles.

Pete

I have updated my first post.
I am actually sending it three parameters. Just to test, I used the same variable twice.

The thing is, that unless I add the middle parameter, then the third one does not appear.
So this would only show the following

char buff[60];
sprintf(buff, "c:END,seconds:%d,power:%u", seconds,(int)consumo);

output

c:END,seconds:26,power:0

el_supremo:
sprintf does not handle floats or doubles.

Pete

thanks, I know, that is why I am casting to (int)
which is working as long as I add the third parameter. wierd

Is it too much trouble to tell us what the value of consumo is?

jremington:
Is it too much trouble to tell us what the value of consumo is?

sorry, not at all. It is just that it will increment as power us drawn by a CT sensor.
To test I have written a shorter code...

  static long prev = millis();
  if (millis() - prev > 20000){
              prev = millis();
              char buff[60];
              int consumo = 4000.89 + SumPower - 3900.2;
              Serial.print("\n\n\n");
              Serial.println(consumo);
              sprintf(buff, "c:END,seconds:%d,power:%d", millis()/1000,(int)consumo);
              byte buffLen=strlen(buff);
            Serial.println(buff);
            Serial.print("\n\n\n");
  }

Sumpower is reported as

SumPower: 48.2875wh

this outputs:

151
c:END,seconds:25,power:0

Try using this:

sprintf(buff, "c:END,seconds:%d,power:%d", seconds,(int)consumo);

You are casting "consumo" to an int but formatting your string for an unsigned int (%u). This might be causing your issue (it would be odd, but it could be the issue).

thanks
using %d or %u give the same result. Value is marked as zero.
any idea?

  static long prev = millis();
  if (millis() - prev > 20000){
    prev = millis();
    char buff[60];
    double kk = 4000.89 + 50 - 3800.2;
    int consumo = (int) kk;
    Serial.print("\n\n\n");
    Serial.print("Consumption: "); Serial.println(consumo);
    sprintf(buff, "c:END,seconds:%d,power:%u", millis()/1000,(int)consumo);
    byte buffLen=strlen(buff);  Serial.print(F("buffLen: ")); Serial.println(buffLen);
    Serial.print(F("Buffer: ")); Serial.println(buff);
    Serial.print("\n\n\n");
}

output:

Consumption: 250
buffLen: 24
Buffer: c:END,seconds:25,power:0

This is another example. same issue

If I add another parameter

sprintf(buff, "c:END,seconds:%d,power:%d.%d", currentTime,(int)consumo,(int)consumo);

then the new parameter will work but not the other one

Consumption: 250
buffLen: 28
Buffer: c:END,seconds:25,power:0.250

While sprintf() is a powerful function, I'm not a big fan because you almost always only use a small fraction of that power, resulting in a bloated code size. I, too, did not get the right answer, even though the code size was 3752 bytes. I then tried a version that doesn't use sprintf():

void setup() {
  Serial.begin(9600);

  
  static long prev = 5000L;        // Make up some test values
  char buff[60];
  char temp[10];
  int consumo = 151;                // Same here

  strcpy(buff, "c:END,seconds:");
  strcat(buff, ltoa(prev / 1000, temp, 10));
  strcat(buff, ", power: ");
  strcat(buff, itoa(consumo, temp, 10));
  
  Serial.println(buff);
}

void loop() {


}

which compiles to 2174 bytes and has the advantage that it gives a correct answer.

thanks econjack!
I am still wondering what is going on.
more tests....

unsigned long currentTime = millis()/1000;
    char buff[60];
    sprintf(buff, "c:END,seconds__%d__%d__%d__%d", currentTime,currentTime,currentTime,currentTime);
Serial.print(F("Buffer: ")); Serial.println(buff);

outputs:

currentTime: 45
Consumption: 250
buffLen: 27
Buffer: c:END,seconds__45__0__45__0

What is happening with the even number parameters !?!

See if adding some spaces around the formatting works, try this:

sprintf(buff, "c:END,seconds: %d ,power: %d ", seconds,(int)consumo);

more tests....

%d is NOT the format specifier for unsigned longs.

ok I just found out the problem:

I need to use %ld

So by selecting the wrong identifier in the previous parameter (first one), makes the following parameter (second one) not print correctly!

edit: Thanks Paul, I just read your message after finding this out.

Yes, because the arguments tell the compiler how many bytes to put on the stack, and the specifier tells sprintf() how many bytes to pull off the stack. They do not communicate with each other.

Clang will inform you of this mismatch.