splitting decimal number to 2 pieces

Hi!
I tried to figure this out last 2 weeks without manage to solve it(googleling, reading this forum for hours, testing different types of libraries etc). So I registered in here.
So, I try to make 3 digit 7-segment display(via three 74hc595 multiplexer) which displays decimal number for example 36.7(temperature which is always between 10.0 to 40.9 C) . To showing integer numbers is not a problem(working fine), but I can't manage to find out how to divide decimal number to two pieces (because i assume that to light decimal point on I have to have after decimal point numbers separated from number before decimal point).

Just because English isn't my native I will explain it other way too:

Problem: 37.7 (Temp which is always between 10.0 to 40.9 C )

need to get this format:

int a = 37
int b=7

to get it to the 7-segment display which will show 37.7.

-Toni
ps. Programming is new to me.

Demo code. You tell us

A. Why this works (work it out with paper and pen before answering.

B. How would you deal with 2 digits after the decimal point?

float temp = 37.9;
int a;
int b;

void setup() {
  // put your setup code here, to run once:
  
  a = temp; // gets the first part as going from (casting) 
  //float to int drops the bit after the decimal point
  
  Serial.begin(9600);
  Serial.print("before the point ");
  Serial.println(a);
  // get the second part
  b= temp*10-a*10;
  Serial.print("after the point ");
  Serial.print(b);
  
}

void loop() {
  // put your main code here, to run repeatedly: 
  
}

Mark

1 Like

If you want to split at the decimal then you can cast the float variable to an int. I think that always truncates the number (floor). If not the math to make that happen is easy. That will give you the whole number part. Subtract from the original float to find the decimal part.

But in your case it shouldn't be so hard. It looks like all of your numbers have exactly one decimal place. In that case, multiply the number by 10 to get an int and put that on your display as normal, and always light up the decimal point between the second and third digits. The decimal on most 7 segment displays I've seen is just one more lead on the package, and is usually after the number. So you would be adding one wire to the second digit in the display and leaving it on always. You don't even need to add anything to the program, just tie that lead to power or ground as the case may be.

int a = (int)temp;
int b = temp - a;

No division necessary.

you can also use dtostrf() to create a character string out of it, and simply look for the '.' so you can pick it apart and send it, since you need a character anyway.

Thanks to all of you!

Answer was really really simple. But sometimes you just can't see it :slight_smile:

I solved this out this way with your help:

 const int  latchPin = 42; 
 const int  clockPin     = 41; 
 const int  dataPin    = 44; 
 
float temp=0.0;
int a=0;
int b=0;
int c;
int d;
byte g_digits[10];
byte g_digitsd[10];
float temp2=1.1;
 
 void setup()
 {
   pinMode (latchPin, OUTPUT);
   pinMode (clockPin, OUTPUT);
   pinMode (dataPin, OUTPUT);
   
   Serial.begin (115200);
   
 g_digits [0] = 1 + 2 + 4 + 8 + 16 + 32 + 00;
g_digits [1] = 0 + 2 + 4 + 0 + 00 + 00 + 00;
g_digits [2] = 1 + 2 + 0 + 8 + 16 + 00 + 64;
g_digits [3] = 1 + 2 + 4 + 8 + 00 + 00 + 64;
g_digits [4] = 0 + 2 + 4 + 0 + 00 + 32 + 64;
g_digits [5] = 1 + 0 + 4 + 8 + 00 + 32 + 64;
g_digits [6] = 1 + 0 + 4 + 8 + 16 + 32 + 64;
g_digits [7] = 1 + 2 + 4 + 0 + 00 + 00 + 00;
g_digits [8] = 1 + 2 + 4 + 8 + 16 + 32 + 64;
g_digits [9] = 1 + 2 + 4 + 8 + 00 + 32 + 64;

g_digitsd [0] = 1 + 2 + 4 + 8 + 16 + 32 + 00 +128;
g_digitsd [1] = 0 + 2 + 4 + 0 + 00 + 00 + 00 +128;
g_digitsd [2] = 1 + 2 + 0 + 8 + 16 + 00 + 64 +128;
g_digitsd [3] = 1 + 2 + 4 + 8 + 00 + 00 + 64 +128;
g_digitsd [4] = 0 + 2 + 4 + 0 + 00 + 32 + 64 +128;
g_digitsd [5] = 1 + 0 + 4 + 8 + 00 + 32 + 64 +128;
g_digitsd [6] = 1 + 0 + 4 + 8 + 16 + 32 + 64 +128;
g_digitsd [7] = 1 + 2 + 4 + 0 + 00 + 00 + 00 +128;
g_digitsd [8] = 1 + 2 + 4 + 8 + 16 + 32 + 64 +128;
g_digitsd [9] = 1 + 2 + 4 + 8 + 00 + 32 + 64 +128;

 }
 
 void loop() {
   
    temp=analogRead(A1);
    
   
  temp2=(temp/1024)*50;
 a= (int)temp2;
 b= temp2*10 - a*10;
 c=a/10;
 d=a-c*10;

Serial.println(a);
Serial.println(c);
Serial.println(d);
Serial.println(b);
Serial.println(temp2);
Serial.println("_____");


   
  
    digitalWrite(latchPin, 0);
   
    shiftOut(dataPin, clockPin, MSBFIRST, g_digits[c]);
    shiftOut(dataPin, clockPin, MSBFIRST, g_digits[d]);
    shiftOut(dataPin, clockPin, MSBFIRST, g_digitsd[b]);
   
    digitalWrite(latchPin, 1);
    delay(300);
  
  }

I just replace thermometer with variable resistor to be able to change voltage quickly. I think that there is "cleaner way to do this but it seems works so it's ok to me.

-Toni

Aw man... good catch. My code example tried to save the remainder to an int. You would need a float for that to work (or, as you did, multiply the result by 10 for a single digit of precision.)

Sorry about that. :slight_smile: Glad you figured it out despite my goof-up.

You don't need floats at all.
If you declare temp2 as an int, you can use:

// the math here is that 500/1024 equals 125/256
temp2=(temp*125)/256; // temp2 is now in tenths of a degree

only that will overflow so instead use:

// the math here is:
// 500/1024 = 125/256 = 128/256 - 3/256 = 1/2 - 3/256
temp2=(temp/2)-((3*temp)/256); // temp2 is now in tenths of a degree

Since you have the temperature in tenths of a degree, all you need to do is insert a decimal point.

g_digitsd [4] = 0 + 2 + 4 + 0 + 00 + 32 + 64 +128;

Did you know about the binary constant notation?

g_digitsd [4] =  0b11100110;

Just note that the biggest bit comes first (128 +64+32+4+2) so the bits are reversed compared to your sum.