2

I have a question with Serial Print. I want the Sensor reading values to fall under 3 columns, and each column should have the readings from the same sensor.

Raw Value | Sensor 1 | Sensor 2 | Sensor 3

how can I modify this code do this?

Below I have posted my code and what I currently see using the Serial Monitor

 void loop(){
 RawValue0 = analogRead(analogIn0);
 Voltage0 = (RawValue0 / 1023.0) * 5000; // 5000 to get millivots.
 tempC0 = (Voltage0-500) * 0.1; // 500 is the offset
 tempF0 = (tempC0 * 1.8) + 32; // conver to F 
 Serial.print("Raw Value = " ); // shows pre-scaled value 
 Serial.print(RawValue0); 
 Serial.print("\t milli volts = "); // shows the voltage measured 
 Serial.print(Voltage0,0); //
 Serial.print("\t Sensor 1: Temperature in C = ");
 Serial.print(tempC0,1);
 Serial.print("\t Sensor 1: Temperature in F = ");
 Serial.println(tempF0,1);
 delay(500); 

enter image description here

asked Apr 14, 2019 at 19:18
4
  • you have no code for dealing with sensor 2 and sensor 3 ..... there is no way to modify non-existent code Commented Apr 14, 2019 at 19:53
  • 1
    is this schoolwork? Commented Apr 14, 2019 at 19:55
  • 1
    you already know how to print in column format .... it is entirely unclear what you are having a problem with Commented Apr 14, 2019 at 19:56
  • think very carefully about this .... do you really want Raw Value | Sensor 1 | Sensor 2 | Sensor 3? Commented Apr 14, 2019 at 20:17

2 Answers 2

2

Columns with lines?

The sprintf function can fill data with spaces to align them. However, the Arduino sprintf function does not support floating point variables. The dtostrf function has already a fixed output width by itself.
The sketch below is a combination of UTF-8 characters and the dtostrf and sprintf functions.

void setup() {
 Serial.begin(9600);
 Serial.println();
 Serial.println("┏━━━━━━┳━━━━━━━━┳━━━━━━━━┓");
 Serial.println("┃ raw ┃ °C ┃ °F ┃");
 Serial.println("┣━━━━━━╋━━━━━━━━╋━━━━━━━━┫");
}
void loop() {
 int raw = random(0, 1024);
 float c = random(-1000, 1000) / 10.0;
 float f = random(-500, 1500) / 10.0;
 char buffer_c[20];
 char buffer_f[20];
 dtostrf(c, 6, 1, buffer_c);
 dtostrf(f, 6, 1, buffer_f);
 char buffer[80];
 sprintf(buffer, "┃ %4d ┃ %s ┃ %s ┃", raw, buffer_c, buffer_f);
 Serial.println(buffer);
 delay(500);
}

The strlen() function can not be used before printing a floating point number to the serial port, since its length is determined while printing characters to the serial port. The final number of bytes that is written is the return value.
There is a way to use that return value, by using a dummy write to a dummy serial port. After that the number of spaces to align the floating point number can be calculated.

That reduces the code size from 6160 to 4708 for an Arduino Uno.

class DummyClass : public Stream
{
 int available() {return 0;}
 int read() {return 0;}
 int peek() {return 0;}
 void flush() {return;}
 size_t write(uint8_t) {return 1;}
 using Print::write;
};
DummyClass Dummy;
const int width_r = 4;
const int width_c = 6;
const int width_f = 6;
void setup() {
 Serial.begin(9600);
 Serial.println();
 Serial.println("┏━━━━━━┳━━━━━━━━┳━━━━━━━━┓");
 Serial.println("┃ raw ┃ °C ┃ °F ┃");
 Serial.println("┣━━━━━━╋━━━━━━━━╋━━━━━━━━┫");
}
void loop() {
 int raw = random(0, 1024);
 float c = random(-1000, 1000) / 10.0;
 float f = random(-500, 1500) / 10.0;
 int i;
 Serial.print("┃ ");
 Spaces(width_r - Dummy.print(raw));
 Serial.print(raw);
 Serial.print(" ┃ ");
 Spaces(width_c - Dummy.print(c,1));
 Serial.print(c,1);
 Serial.print(" ┃ ");
 Spaces(width_f - Dummy.print(f,1));
 Serial.print(f,1);
 Serial.print(" ┃");
 Serial.println();
 delay(500);
}
void Spaces(int n)
{
 for(int i=0; i<n; i++) {
 Serial.print(' ');
 }
}

I advise not to use this "Dummy" trick. It is mere a coding exercise. I can not find a problem with this trick, but I'm not 100% sure that it is okay.

answered Apr 14, 2019 at 22:28
2
  • use dtostrf for raw too and and save 1kB flash on sprintf Commented Apr 15, 2019 at 9:53
  • 1
    @Juraj I can do better than that. After reading your answer here: arduino.stackexchange.com/questions/62783/… I tried a dummy class. To my surprise it worked. Commented Apr 15, 2019 at 11:00
1

Here is a sketch that uses a different approach than Jot uses in his answer. There is no question that Jot's answer is excellent and takes very few lines of code to accomplish.

I thought it would look nice if the Raw Value, an integer, was centered under the "Raw Value" column when it was at it's maximum value of 1023. A value of 1 would be right-ish justified, but still aligned with the center in mind.

The floating point numbers, which could be positive or negative, should be right justified I thought, so I wrote a second function to deal with those numbers.

int RawValue0;
float Voltage0, tempC0, tempF0;
void setup(){
 Serial.begin(9600);
 Serial.println();
 Serial.println("Raw Value | Sensor 1 | Sensor 2 | Sensor 3");
 Serial.println("------------------------------------------");
 RawValue0 = 1023; //analogRead(analogIn0);
 Voltage0 = 11.0; //(RawValue0 / 1023.0) * 5000; // 5000 to get millivots.
 tempC0 = -100.0; //(Voltage0-500) * 0.1; // 500 is the offset
 tempF0 = 1212.0; //(tempC0 * 1.8) + 32; // conver to F
}
void loop(){
 // Increment the variables to simulate test data.
 RawValue0 += 51;
 if(RawValue0 > 1023){RawValue0 = 0;}
 Voltage0 += 99.99;
 if(Voltage0 > 9999.99){Voltage0 = 0.0;}
 tempC0 -= 99.99;
 if(tempC0 < -9999.99){tempC0 = 0.0;}
 // Print out the data in columns.
 printNumber(RawValue0);
 Serial.print(" | ");
 printNumber(Voltage0);
 Serial.print(" | ");
 printNumber(tempC0);
 Serial.print(" | ");
 printNumber(tempF0);
 Serial.println();
 delay(250);
}
long printNumber(int number){
 Serial.print(" ");
 int spaces = 0;
 if(number < 1000){spaces = 1;}
 if(number < 100){spaces = 2;}
 if(number < 10){spaces = 3;}
 for(int i = 0; i < spaces; i++){
 Serial.print(" ");
 }
 Serial.print(number);
}
float printNumber(float number){
 int spaces = 0;
 if(number > -1000.00){Serial.print(" ");}
 if(number < 1000){spaces = 1;}
 if(number < 100){spaces = 2;}
 if(number < 10){spaces = 3;}
 if(number < 0){spaces = 0;}
 if(number == -99.99){spaces = 1;}
 for(int i = 0; i < spaces; i++){
 Serial.print(" ");
 }
 Serial.print(number);
}

When I compile Jot's sketch, it's 6640 bytes. If you remove his "fancy" header, it drops to 6414 bytes. My sketch is 5124 bytes. There is a certain amount of "overhead" involved when using sprintf().

The question you have to ask yourself is, "Does saving 1000 bytes matter?".

answered Apr 14, 2019 at 23:12
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.