Sprintf and arrays not working properly with this code SOLVED!

Hello! I'm using a standard photoresistor template in Arduino's Examples.

The output (when just printing each argument without sprintf) is:

30984,255,1023.00,5.00

Time (ms), LightLevel (255 is good), Bytes (1023 is good), Voltage (5 volts)

With sprintf, and despite changing buffer sizes, or moving pieces of code around, I get the output full of errors (also notice time becomes negative):

32573, 0, <----- it seems to insert a 0, and I not print the dtostrf variables
-32444, 0,
-31405, 0, ÄÑÎ, 1023.00 <----- or gibberish

Here is my code:

#include <SPI.h>
#include <SD.h>

//Definitions
uint32_t timeStamp = 0;
const int sensorPin = 0;
const int ledPin = 9; // DO NOT USE PIN 10

//SPRINTF STUFF
char buffer1[100];
char bytesStr[10];
char voltsStr[10];
int lightLevel, high = 0, low = 1023;
float voltBytes = 4.01176471; //lightlevel (0–255) * this = 0–1023 resolution
float milliVolt = 0.00488759; //5v÷1023 resolution
String header1 = ("Begin string Test");
String header2 = ("Time,LightLevel,Bytes,Voltage");
const int chipSelect = 4; //SD card write

//SD Card
File dataFile; //name of file object
void setup() {
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
pinMode(ledPin, OUTPUT);
pinMode(10, OUTPUT); //Required for SD card module, do not use

//SD CARD
Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// don't do anything more:
while (1);
}
Serial.println("card initialized.");

//Print initial startup – works!
dataFile = SD.open("newdoc.txt", FILE_WRITE);
if (dataFile) {
dataFile.println(""); //double spaces for now
dataFile.println("");
dataFile.println(header1); //headers
dataFile.println(header2);
dataFile.close();
// debug
Serial.println("");
Serial.println(header1);
}
//debug
delay(500);
}

void loop() {
timeStamp = millis(); // this declaration must be in void loop
//definitions within the loop
float Bytes = lightLevel*voltBytes;
float Voltage = lightLevel*voltBytes*milliVolt;
dtostrf(Bytes,1,2, bytesStr); //convert to text
dtostrf(Voltage, 1,2, voltsStr);
sprintf(buffer1,"%d,%d,%s,%s",timeStamp,lightLevel,bytesStr,voltsStr); //combine

//PHOTORESISTOR
lightLevel = analogRead(sensorPin);
autoTune(); // have the Arduino do the work for us!
analogWrite(ledPin, lightLevel); //nightlight: add 255 - before lightlevel

// SD CARD
dataFile = SD.open("newdoc.txt", FILE_WRITE);
if (dataFile) {
dataFile.println(buffer1); // send to card
Serial.println(buffer1); //send to screen
dataFile.close();

/*
// original code (works)
dataFile.print(timeStamp); // turn all reads into a string?
dataFile.print(",");
dataFile.print(lightLevel);
dataFile.print(",");
dataFile.print(Bytes);
dataFile.print(",");
dataFile.println(Voltage);
dataFile.close(); // close file
//debug
Serial.print("Time: ");
Serial.print(timeStamp);
Serial.print("\t Light Output: ");
Serial.print(lightLevel);
Serial.print("\t Bytes: ");
Serial.print(Bytes);
Serial.print("\t Voltage: ");
Serial.println(Voltage);
*/
}
else {
Serial.println("error opening newdoc.txt");
}
//END SD card write
delay(2000);
}
void manualTune()
{
lightLevel = map(lightLevel, 0, 1023, 0, 255);
lightLevel = constrain(lightLevel, 0, 255);
}
void autoTune()
{
if (lightLevel < low)
{
low = lightLevel;
}
if (lightLevel > high)
{
high = lightLevel;
}
lightLevel = map(lightLevel, low+30, high-30, 0, 255);
lightLevel = constrain(lightLevel, 0, 255);
//autotune END
}

try to cast variable types when you mix them

int lightLevel, high = 0, low = 1023;
float voltBytes = 4.01176471; //lightlevel (0–255) * this = 0–1023 resolution
float milliVolt = 0.00488759; //5v÷1023 resolution
...
float Bytes = (float)lightLevel*voltBytes;

You need %lu for the timestamp.

sprintf(buffer1,"%lu,%d,%s,%s",timeStamp,lightLevel,bytesStr,voltsStr);

strange..

sprintf(buffer1,"%s,%s,%d,%u",bytesStr,voltsStr,lightLevel,timeStamp); //combine

put strings first, then works??

have fun.. ~q

It is best to avoid casts where possible. In this case, arithmetic conversion applies so no further action is needed.

Thank you, I may try this. As it is, it works without this. Thank you though!

Thank you so much! I tried this and it seemed to solve some issues, but I still had weird time failures (the time would drop drastically for a few seconds, then "catch up")

I solved the problem by just removing time from the (string's) equation altogether and setting it up to print on its own. Seems to work now!

But for real, your suggestion was the closest to pure success I've had in weeks, and I'll keep it in mind!

This was an elegant idea and, along with the %ul change suggested above, we were at 90% working great! So thank you!!

I ended up moving time out and printing time on its own... but the rest of the string actually works now, when it never did before!

Super happy, everyone, thank you kindly

1 Like

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