1

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

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

  • use dtostrf for raw too and and save 1kB flash on sprintf – Juraj Apr 15 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. – Jot Apr 15 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?".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.