Gixxer
January 7, 2016, 9:12pm
1
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.
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
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
Gixxer
January 7, 2016, 9:24pm
4
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
Gixxer
January 7, 2016, 9:25pm
5
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?
Gixxer
January 7, 2016, 9:38pm
7
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
SRegan
January 7, 2016, 9:40pm
8
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).
Gixxer
January 7, 2016, 9:45pm
9
thanks
using %d or %u give the same result. Value is marked as zero.
any idea?
Gixxer
January 7, 2016, 9:52pm
10
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
Gixxer
January 7, 2016, 10:03pm
11
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.
Gixxer
January 7, 2016, 10:11pm
13
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 !?!
SRegan
January 7, 2016, 10:49pm
14
See if adding some spaces around the formatting works, try this:
sprintf(buff, "c:END,seconds: %d ,power: %d ", seconds,(int)consumo);
system
January 7, 2016, 10:56pm
15
more tests....
%d is NOT the format specifier for unsigned longs.
Gixxer
January 7, 2016, 10:59pm
16
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.
KeithRB
January 7, 2016, 11:59pm
17
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.