force a value to 3 digits

I am writing some code for a data logger.
I am producing a readout from an analog pin and can display this on my LCD. However I always need a 3 byte value, in other words zero must be 000 not 0 and 25 025 etc. I must do this as I have to specify the number of bytes I need to write to my SD card module so cant have it changing.
Any suggestions greatly appreciated.

Bob

Here is my code, which will print the analog value on an LCD.

//* analog_input_test
//* reads analog input on pin 0
//* and sends value to lcd
//* ATD has 10 bit resolution, so max 5v = 1024
//* 3v will give about 630
//************************************************/
#include <LCD4Bit.h>
//create object to control an LCD.
//number of lines in display=1
LCD4Bit lcd = LCD4Bit(2);

int analogPin = 0; // Geophys Instument Input
int value1 = 0; // variable to store the value coming from the sensor
char value2[4] ;

void setup() {
lcd.init();

}

int ReadSens_and_Condition(){
int i;
int sval;

for (i = 0; i < 5; i++){
sval = sval + analogRead(0);
// sensor on analog pin 0
}

sval = sval / 5; // average
sval = sval -3;
//sval = sval / 4; // scale to 8 bits (0 - 255)
//sval = 255 - sval; // invert output
return sval;
}

void loop() {

//value1 = analogRead(analogPin); // reads the value 0-1023

value1 = ReadSens_and_Condition();

lcd.clear();

lcd.printIn(“Analog Input”);

//delay(100);
digitalWrite(13, LOW);

//print some dots individually
for (int i=0; i<3; i++){
lcd.print(’.’);
delay(100);
}

//print something on the display’s second line.
//uncomment this if your display HAS two lines!

lcd.cursorTo(2, 0); //line=2, x=0.
itoa (value1, value2, 10);
lcd.printIn("= ");
lcd.printIn(value2); // Value2 needs to always be 3 bytes help please!!
delay(1000);

//scroll entire display 20 chars to left, delaying 50ms each inc
lcd.leftScroll(20, 50);

}

Here is a routine that does this for serial. Replace the serial calls with LCD calls.

void padPrint( int value, int width)
{
// pads values with leading zeros to make the given width
char valueStr[6]; // large enough to hold an int
   itoa (value, valueStr, 10);
   int len = strlen(valueStr);
   if(len < width){
     len = width-len;
     while(len--)
      Serial.print('0');
   }
  Serial.println(valueStr);   
}

Usage: padPrint(val,3); // pad val to 3 places with leading zeros

This works for positive numbers, it’s a little more complicated if your values are negative.

Note also that you can use the sprintf library routine but this links in 1.5k of code

Based on mems function

// pads values with leading zeros to make the given width
void padPrint( Print &printer, int value, int width ){
  char valueStr[6]; // large enough to hold an int
  itoa (value, valueStr, 10);
  int len = strlen(valueStr);
  if(len < width){
    len = width-len;
    while(len--){
      printer.print('0');
    }
  }
  printer.print(valueStr);//removed the newline
}

void padPrintln( Print &printer, int value, int width ){
  padPrint( &printer, value, width );
  printer.println();
}

Usage:

#include <NewSoftSerial.h>
NewSoftSerial softSerial = NewSoftSerial(2,3);

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

  int x = 20;
  padPrintln(Serial, x, 3);//print 020\r\n to the Serial
  padPrint(softSerial, x, 3);/print 020 to the softSerial
}

Hi,
I have tried this and I get the following error when compiling the program.
It happens at the last print statement right at the end

In function ‘void padPrint(int, int)’:
error: invalid conversion from ‘char*’ to ‘int’

Here is my code I have not got as far as using pad print yet as it wont compile past the function.
Bob

//* analog_input_test
//* reads analog input on pin 0
//* and sends value to lcd
//* ATD has 10 bit resolution, so max 5v = 1024
//* 3v will give about 630
//************************************************/
#include <LCD4Bit.h>
//create object to control an LCD.
//number of lines in display=1
LCD4Bit lcd = LCD4Bit(2);

int analogPin = 0; // Geophys Instument Input
int value1 = 0; // variable to store the value coming from the sensor
char value2[4] ;

void setup() {
lcd.init();

}

int ReadSens_and_Condition(){
int i;
int sval;

for (i = 0; i < 5; i++){
sval = sval + analogRead(0);
// sensor on analog pin 0
}

sval = sval / 5; // average
sval = sval -3;
//sval = sval / 4; // scale to 8 bits (0 - 255)
//sval = 255 - sval; // invert output
return sval;
}
void padPrint( int value, int width)
{
// pads values with leading zeros to make the given width
char valueStr[6]; // large enough to hold an int
itoa (value, valueStr, 10);
int len = strlen(valueStr);
if(len < width){
len = width-len;
while(len–)
lcd.print(‘0’);
}
lcd.print(valueStr);
}

void loop() {

//value1 = analogRead(analogPin); // reads the value 0-1023

value1 = ReadSens_and_Condition();

lcd.clear();

lcd.printIn(“Analog Input”);

//delay(100);
digitalWrite(13, LOW);

//print some dots individually
for (int i=0; i<3; i++){
lcd.print(’.’);
delay(100);
}

//print something on the display’s second line.
//uncomment this if your display HAS two lines!

lcd.cursorTo(2, 0); //line=2, x=0.
itoa (value1, value2, 10);
lcd.printIn("= ");
lcd.printIn(value2); // Value2 needs to always be 3 bytes help please!!
delay(1000);

//scroll entire display 20 chars to left, delaying 50ms each inc
lcd.leftScroll(20, 50);

}

Hi, I have tried both these and get compile errors in the functions. Is there a way to do this to the raw data rather than when printing it?

Bob

Hi,

I had the same problem and I used the map function for it,

value1 = map(val1, 0, 255, 100, 356);

I don't know if it would help in your case, cause the number changes like 0 becomes 100 and 34 becomes 134 etc. But you always have three digits ;) In my case I then used map again to turn it back when I want to use the real number

va1 = map(value1, 100, 356, 0, 255);

Xavier

Hi, Thanks all. I am trying a different approach I am using the string library to count the number of bytes and return a value. Then I can work out how many bytes I will be sending to the SD card module and all will work!! Bob

You got the error because you were passing a string to padPrint, you need to pass the integer value. Here is a variant on your sketch that uses padPrint:

#include <LiquidCrystal.h>

//* analog_input_test
//* reads analog input on pin 0
//* and sends value to lcd
//* ATD has 10 bit resolution, so max 5v = 1024
//* 3v will give about 630
//************************************************/

LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);
int analogPin = 0;    // Geophys Instument Input
int value1 = 0;       // variable to store the value coming from the sensor
char value2[4] ; 

void setup() {
//lcd.init();

}

int ReadSens_and_Condition(){
 int i;
 int sval;

 for (i = 0; i < 5; i++){
   sval = sval + analogRead(0);
   // sensor on analog pin 0
 }

 sval = sval / 5;    // average
 sval = sval -3;
 //sval = sval / 4;    // scale to 8 bits (0 - 255)
 //sval = 255 - sval;  // invert output
 return sval;
}
void padPrint( int value, int width)
{
// pads values with leading zeros to make the given width
char valueStr[6]; // large enough to hold an int
  itoa (value, valueStr, 10);
  int len = strlen(valueStr);
  if(len < width){
    len = width-len;
    while(len--)
     lcd.print('0');
  }
 lcd.print(valueStr);  
}


void loop() {

  //value1 = analogRead(analogPin);   // reads the value 0-1023
  
  value1 = ReadSens_and_Condition();


 lcd.clear();
 
 lcd.print("Analog Input");
 
 //delay(100);
 digitalWrite(13, LOW);

//print some dots individually
 for (int i=0; i<3; i++){
   lcd.print('.');
   delay(100);
 }


//print something on the display's second line. 
 //uncomment this if your display HAS two lines!
 

// lcd.cursorTo(2, 0);  //line=2, x=0.
 lcd.setCursor(1,0);
 lcd.print("= ");
[glow] padPrint(value1, 3);[/glow]
 delay(1000);

 
 //scroll entire display 20 chars to left, delaying 50ms each inc
// lcd.leftScroll(20, 50);
   
}

I replaced the calls to lcd4bit to ones for LiquidCrystal to get this to compile on my system - change them back to LCD4bit if you prefer that library

Thanks will give it a go

Bob

Ugh… Why not the easy way?

 ...
 if (value2 < 100)
  lcd.print(' ');
 if (value2 < 10)
  lcd.print(' ');
 lcd.printIn(value2); // Value2 needs to always be 3 bytes help please!!

Thank for that, I have sorted it by doing exactly that for the whole string I send to be logged. I tell it to expect more data than I know I will be sending and then pad the end of the file with spaces the extra ones of which just get "lost"!! Cheerss

Bob

Ugh… Why not the easy way?
. . .

Pragmatic! I love it.

Here’s a padprint function from one of my sketches that could be easily adapted:

void padprint(int number, int chars) {
for (int i = pow(10, chars - 1); number <= i - 1; i /= 10) Serial.print(“0”);
Serial.print(number);
}