Binary value to decimal character conversion

I am using anLTC2400 ADC which output 24bit values. I need to display these values on a TFT display and to do so need to convert the value to decimal character. Theoretically this sounded quite easy to me as the maximum value will not be greater than 90,000. The method I chose was to subtract first 10,000 and count the number of times I could do that without the value going either negative or zero, then repeat the process using 1000, 100, 10 and finally one (actually the reamainder) each time counting how many times each value was subtracted. To do the above I need to use the IF statement to test the result of the subtraction and point to the next step i.e if negative add the value subtracted back, exit or continue subtracting.
I cannot get my mind around how to use the if statements and how the braces play a part. I have used If …then, if else…then, in other compilers (a long time ago). I have written (and rewritten many times) the attached code but cannot get it to work at all. Initially I followed the normal convention of placing my code in loop and printing out what was in each variable but I couldn’t step through it so I moved the code into setup so it would only run once - still to no avail

.

/*routine to convert binary value in value to decimal*/

    int tenthou = 10000;
    int tenthoucnt =0;
    int thou = 1000;
    int thoucnt = 0;
    int hun = 100;
    int huncnt = 0;
    int ten = 10;
    int tencnt = 0;
    int units =1;
    int unitcnt =0;
    
    
unsigned long valuess; //used as workspace to shift value
unsigned long value =99876;// this number used to test subroutin
void setup()
  {Serial.begin(9600);
/*get absolute value from value (32 bits) by shifting out top and bottom 4 bits */
//  valuess = value << 4; //not used during testing
 // value= valuess >>8;
 
test10000:
    {Serial.print ("  test10000  ");
    value=(value-10000);
    if (value = 0) 
    ++tenthoucnt;
    goto test1000;} 
     {if (value > 0) 
      ++tenthoucnt;
      goto test10000;}
   { if (value < 0) 
    value=value+10000;
    
  //   Serial.print(tenthoucnt);
  //   delay (5000);}

test1000:
Serial.print(tenthoucnt);
     delay (5000);}
   { Serial.print ("test1000");
    value = (value - 1000);
     if (value = 0) 
      ++thoucnt;
      goto test100; }
     {if(value > 0) 
      ++thoucnt;
      goto test1000;}
     {if(value < 0) 
      value=value+1000;
     Serial.print (thoucnt);
    delay (1000) ;}
 test100:  
   { Serial.print ("test100");
    value = (value - 100);
     if (value = 0) 
     ++huncnt;
     goto test10;}
    {if(value > 0) 
    ++huncnt;
    goto test100;}
     {if(value < 0) 
      value=value+100; 
     Serial.print (huncnt);
    delay (1000); }
test10:
  {  value = (value - 10);
     if (value = 0)
     ++tencnt;
     goto test1;}
  { if(value > 0) 
   ++tencnt;
   goto test10;}
   {  if(value < 0)
      value=value+10;            
     Serial.print(tencnt);
    delay (1000);}
test1:
    {value = (value - 1);
     if (value = 0) 
      ++unitcnt;
      goto exit;}
    {if(value > 0) 
    ++unitcnt;
    goto test1;}
     {if(value < 0)
     value=value+1;
exit:
     Serial.print (unitcnt);
      delay (5000);}     
  }
void loop()
{}

Any help would be much appreciated including where I can get more plain english guidance on braces and syntax. C++ is not an esay language to master. In the two weeks I have been using it I have found it very quirky especially the contradictions in the books I have referenced
Regards,

Don

Hi,
If you have the output of the LTC2400 ADC, how are you storing it?
In what variable?

It is stored as binary and can be displayed as DEC, BIN, HEX or OCT using print functions.

What is your TFT and what library are you using.
Have you looked at the examples that come with the library?

You should not need to write a conversion function.

Tom… :slight_smile:

this is C++ and 2018 mate… don’t use gotowhile or for loops are your friend. :slight_smile:

Printing an integral value to the lcd is just a matter of doing

lcd.print(v);

Not sure what I’m missing there… (do you have a library for your lcd?)

that being said there are “multiple ways to skin a cat”… check this out

long v = 98765l;
const long maxThousands = 100000l;


char decodedInAscii[10]; // 10 is plenty for what we have here, should be able to hold all the digits plus a trailing null char


void setup() {
  Serial.begin(115200);

  // the easiest way

  Serial.println("--------- DIRECT PRINTING ---------");
  Serial.print("Your value is: "); Serial.println(v);


  byte length;
  Serial.println("\n--------- FUNCTION ltoa() ---------");
  // using a standard C function
  ltoa(v, decodedInAscii, 10); // convert in ASCII in base 10
  Serial.print("Your value is: "); Serial.println(decodedInAscii);
  length = strlen(decodedInAscii);
  for (int i = 0; i < length; i++) {
    Serial.print("   caracter: ");
    Serial.println(decodedInAscii[i]);
  }

  memset(decodedInAscii, '\0', 10); // reset the cstring
  long vCopy = v;
  long d;
  byte index;
  for (d = maxThousands/10, index = 0; d >= 1; d /= 10, index++) {
    decodedInAscii[index] = '0' + (vCopy / d); // integral division gets rid of the decimal values, then shifting into ASCII table
    vCopy = vCopy % d; // modulo function
  }

  Serial.println("\n--------- DIVIDE AND MODULO ---------");

  Serial.print("Your value is: "); Serial.println(decodedInAscii);
  length = strlen(decodedInAscii);
  length = strlen(decodedInAscii);
  for (int i = 0; i < length; i++) {
    Serial.print("   caracter: ");
    Serial.println(decodedInAscii[i]);
  }
}

void loop() {}

running this code should get you this in the console:

[sub][color=purple]--------- DIRECT PRINTING ---------
Your value is: 98765

--------- FUNCTION ltoa() ---------
Your value is: 98765
   caracter: 9
   caracter: 8
   caracter: 7
   caracter: 6
   caracter: 5

--------- DIVIDE AND MODULO ---------
Your value is: 98765
   caracter: 9
   caracter: 8
   caracter: 7
   caracter: 6
   caracter: 5
[/color][/sub]

To J-M-L, Many, many thanks for that super routine it works a treat. I had tried to print the value straight but without success (reference Tom Georges comment). I will be using the TFT to monitor the Voltage and Current from a Bench Power Supply I have built. I am using David Prentices MCUFRIEND_kbv library which seems to be capable (with some tailoring of the .CPP) file to really do well on both the TFT's I have.

I guess the issue for me (well not really [u]guess[/u] - I know!) is being a real novice with C++. As I said in an earlier missive on this forum, I started in computing in 1964, when to diagnose faults we had to be able to write machine code, i moved on to micros, Z80, 8080, 8085, 6800, 68000, and now arduino and Pi from a "fun"/hobby point of view. Fortunately my daughter and her partner are very, very competent coders but have difficulty with me NOT thinking at "Abstaction" level, I have this failing of wanting to know what the bits are doing >:(

Enough excuses - once again many many thanks

Don Dempsey

I cannot get my mind around how to use the if statements and how the braces play a part.

In C, there are a bunch of "statement types", including the "if" statement and the looping statements ("while", "do", "for") that include a second "statement" as part of their syntax.

An "if" statement is defined as:

[b]   if [/b]([color=red]condition[/color]) [color=limegreen]statement[/color];

Braces can be used nearly anywhere to make a GROUP of statements behave like a single statement, as far as the compiler is concerned. So you could have an "if" statment like:

   [b]if[/b] ([color=red]a == 0[/color]) [color=limegreen]digitalWrite(13, 1);[/color]

Where "a=0" is the condition and "digitalWrite(13,1);" is the statement, but if you wanted to do MULTIPLE things when the condition was true, you would use braces:

    [b]if[/b] ([color=red]a == 0[/color]) [color=limegreen]{
        digitalWrite(13,1);
        a = 100;
     }[/color]

The multiple statements inside the braces act as a single statement for the purposes of the if... It's considered a good idea to always use braces with if and loop statements, because this permits you to add code to the "inside" bits without fooling yourself with the formatting. (remember that spaces and newlines have no meaning in most places, so a sequence like:

   [b]if[/b] ([color=red]a == 0[/color]) 
        [color=limegreen]digitalWrite(13, 1);[/color]
        a = 100;

is probably a mistake, because the "a=100" part is not actually part of the if statement, even though it looks like it should be.

Your decimal conversion idea is actually one of the standard ways to perform this function, especially on CPUs where division is "expensive." You may or may not see the alternating sign hack; as you've written your code, it's pretty much an unnecessary complication. It might end up being written something like this 3-digit example:

    hundredsDigit = '0';
    while (number >= 100) {
        number -= 100;
        hundredsDigit += 1;
    }
    tensDigit = '0';
    while (number >= 10) {
       number -= 10;
       tensDigit += 1;
    }
    onesDigit = number + '0';

Hi, Why did you write "Binary value to Decimal character conversion"? There is no binary involved.

Just extracting the individual digits out of a decimal number.

Tom... :)

Many thanks for taking time out to respond, J- M-L in his response gave me an excellent peice of code to use which worked extremely well (I now need to print it out and try to understand it!). Your explanation of IF will also get printed and added to my "Idiot Learning file". Interesting your comment about division. The very early computers I worked on used Software to carry out division to save on hardware costs and simplify the MILL design. They were called as "Extracodes", though the user didn't know it was software carrying out the division (and the multiplication) by shifting and adding/subtraction.

Once again many thanks I have learned a lot from this.

Don

Hi,

I am using David Prentices MCUFRIEND_kbv library

Does this statement work?

 myGLCD.setColor(0, 255, 0);
  myGLCD.setBackColor(0, 0, 255);
  myGLCD.print("Runtime: (msecs)", CENTER, 210);
  myGLCD.printNumI(millis(), CENTER, 225);

Where the decimal value of milllis() is printed on the display, without having to dissect the individual digits? What is the model of your TFT?

Tom... :)

Tom, The LTC2400 sends its output serially in binary - 4 Bits Control | 24 Bits data | 4 bits Control - that is a total of 32 bits. One needs to shift out the top and bottom 4 bits and only " process" the data bits (this is not entirely true as the bits moved out also indicate positive or negative data values and conversion state. )

This is my problem I tend to think at too low a level - computers are binary devices, I can work in binary. if one chooses to group those bits into Octal, Hex, characters for ease of understanding/communication that is something different.

Many thanks for taking time out to comment.

Don

Also note:

Single equals sign is for assignment.

  x = 2;  // sets x equal to 2

Double equals sign is for comparison.

  if (x == 5) {
    Serial.print("x equals five"); 
  }
  else {
    Serial.print("x does not equal five");
  }

@donbroadband

In these days of Arduino when many people are accustomed with the use of transmitted knowledge (doing things using built-in functions) for the quick solutions of their problems, you are running after the cultivation/preservation of the intelligent knowledge (doing things using fundamental approach) for solving problems.

In the transmitted knowledge, there is not much provision for asking ‘why’ as this kind of knowledge is transmitted by the knower only who knows the mechanics of the creation of the knowledge; whereas, intelligent knowledge comes into being thorough continuous interrogation – why? why? why?

Transmitted knowledge and intelligent knowledge are interrelated; one helps the other to flourish. For the modern knowledge to survive, both kinds of knowledge deserve equal cultivation.

Method-1: Counting
BINary = b23b22, …, b2b1b0

Maximum Decimal Value = 224 - 1 = 16777215
==> 1x10000000 = 10000000

  • 6x1000000 = 6000000
  • 7x100000 = 700000
  • 7x10000 = 70000
  • 7x1000 = 7000
  • 2x100 = 200
  • 1x10 = 10
  • 5x1 = 5

= 16777215

void setup() 
{
  Serial.begin(9600);
  unsigned long x = 0xFFFFFF; //16777215
  Serial.println(x, DEC);      //prints: 16777215
  byte myArray[] = {0, 0, 0, 0, 0, 0, 0, 0};
  unsigned long facArray[] = {10000000, 1000000, 100000, 10000, 1000, 100, 10, 1};
 
  for (int i=0; i<8; i++)  //getting the counts (1,6,7,7,7,2,1,5) for every position of the resultant decimal number
  {
    do
    {
      x = x - facArray[i];
      if (x >=0)
      {
        myArray[i] = myArray[i] +1;
      }
      if (x < facArray[i])
      {
        break;
      }
    }
    while(x>=0);
  }

  for(int i=0; i<8; i++)
  {
    Serial.print(myArray[i], DEC);  //prints: 16777215
  }
  Serial.println();
}

void loop()
{
  
}

Method-2 Horner Rule based on Newton’s Polynomial: A(x) = anxn+an-1xn-1+ … + a1x1 + a0x0

BIN = b23b22 … b1b0
BCD = b23x223 + b22x222 + … + b2x22 + b1x21 + b0x20
BCD = ((…(IPBCDx2 + b23)2 + b22)2 + … +b2)2 + b1)2 + b0

Where: IPBCD = Initail Partail BCD = 0

Computation Formula:
unsigned long IPBCD=0
for (int n=23; n>=0; n–)
{
IPBCD = IPBCD + bn
IPBCD = bcdAdjust(IPBCD); //IPBCD contains the final decimal value in BCD format
}

Method-3: Modulus and Division

void setup() 
{
  Serial.begin(9600);
  unsigned long x = 0xFFFFFF; //16777215
  Serial.println(x, DEC);      //prints: 16777215
  byte myArray[] = {0, 0, 0, 0, 0, 0, 0, 0};
  
  for (int i=0; i<8; i++)  //getting the indexes for every position of the resultatnt decimal number
  {
    myArray[i] = x%10;
    x = x/10;
  }

  for(int i=7; i>=0; i--)
  {
    Serial.print(myArray[i], DEC);  //prints: 16777215
  }
  Serial.println();
}

void loop()
{
  
}

Method-4: Arduino Style based on Transmitted Knowledge

unsigned long x = 0xFFFFFF;
Serial.println(x, DEC);     prints: 16777215

Hi GolamMostafa - a most interesting dissertation. Sadly I fall into a category of "unconcious incompetence" ie I don't know any better!!! I have spent the time since my original cry for help finding out why I couldn't do what I wanted to do using the method defined by both Tom and J-L-M. It was quite simple really during my prototyping/proofing session I had NOT allowed a large (LONG) enough variable to store my results. When I changed this things started to go better! I am now joining the "Serial out form of the LTC2400 application to my TFT output code, AND YET AGAIN HAVING errors due to my poor (bad) use of Braces. I will get there the issue for me is when

:) :) :) :)

Don