Float Counter - Page 1
Forum section: electronics / general

author: george.manson.69
author_rank: Newbie
timestamp: July 25, 2020, 05:18:18 pm
content: Hello Everyone,I have some problems, I have been doing a code to show a float number in a 4 digits of 7 segments,for example,I have a number 0.123, so in the display must show each number in display [0.]but I put a printf function to show what happens to each number, and i got this.0,0,12,123of course in the display shows nothing correct.This is a part of the code to convert to float to array number for the 4 digits.(I use a PIC16F18877 in MPLAB X IDE with XC8)Code:#include "mcc_generated_files/mcc.h"/*0011 1111 -> 00000 0110 -> 10101 1011 -> 20100 1111 -> 30110 0110 -> 40110 1101 -> 50111 1101 -> 60000 0111 -> 70111 1111 -> 80110 1111 -> 9*/const uint8_t pattern[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};uint8_t mask = 0;uint8_t* buffer;uint8_t number;float cont;void shift_data(uint8_t data){RCLK_SetHigh();for(uint8_t i=0;i<8;i++){PORTDbits.RD1 = (data << i) & 0x80?1:0;SRCLK_SetHigh(); //ClockSRCLK_SetLow();}RCLK_SetLow();}void converter_uint_to_array(uint16_t dataToConvert,uint8_t* buff){uint8_t mm,cc,dd,uu;PIE0bits.TMR0IE = 0;mm = (uint8_t)(dataToConvert / 1000);cc = (uint8_t)(dataToConvert / 100);cc = cc - ((uint8_t)(cc/10))*10;dd = (uint8_t)(dataToConvert / 10);dd = dd - ((uint8_t)(dd/10))*10;uu = dataToConvert - ((uint8_t)(dataToConvert/10))*10;*buff++ = mm;*buff++ = cc;*buff++ = dd;*buff = uu;PIE0bits.TMR0IE = 1;}void converter_float_to_array(float dataToConvert,uint8_t* buff){uint16_t d1,d2,d3,d4,aux = 0;PIE0bits.TMR0IE = 0;if(dataToConvert>= 0.000 && dataToConvert < 10.00){d1 = (uint16_t)(dataToConvert);d2 = (uint16_t)((float)(dataToConvert - (float)d1));d3 = (uint16_t)dataToConvert*10;d3 = (uint16_t)(10*((float)(((float)dataToConvert*10) - (float)d3)));d4 = (uint16_t)dataToConvert*100;d4 = (uint16_t)(10*((float)(((float)dataToConvert*100) - (float)d4)));printf("4 %u,%u,%u,%u\r\n",d1,d2,d3,d4);}else if(dataToConvert>= 10.00 && dataToConvert < 100.0){d1 = (uint16_t)(dataToConvert / 10);d1 = d1 - ((uint16_t)(d1/10))*10;d2 = (uint16_t)(dataToConvert - ((uint16_t)(dataToConvert/10))*10);d3 = (uint16_t)dataToConvert;d3 = (uint16_t)((float)((float)dataToConvert - (float)d3) * 10);d4 = (uint16_t)dataToConvert*10;d4 = (uint16_t)((float)((float)(dataToConvert*10) - (float)d3) * 10);printf("2 %u,%u,%u,%u%\r\n",d1,d2,d3,d4);}*buff++ = (uint8_t)d1;*buff++ = (uint8_t)d2;*buff++ = (uint8_t)d3;*buff = (uint8_t)d4;PIE0bits.TMR0IE = 1;}/*Main application*/void main(void){// initialize the deviceSYSTEM_Initialize();// When using interrupts, you need to set the Global and Peripheral Interrupt Enable bits// Use the following macros to:// Enable the Global InterruptsINTERRUPT_GlobalInterruptEnable();// Enable the Peripheral InterruptsINTERRUPT_PeripheralInterruptEnable();// Disable the Global Interrupts//INTERRUPT_GlobalInterruptDisable();// Disable the Peripheral Interrupts//INTERRUPT_PeripheralInterruptDisable();LATD = 0x00;number = 0;number = 0;number = 0;number = 0;buffer = &number;buffer = &number;buffer = &number;buffer = &number;while (1){converter_float_to_array(0.123,&number);__delay_ms(500);// Add your application code}}I tried many times to resolve this issue if you have any idea that could help me, will be great!regards!

author: Nominal Animal
author_rank: Super Contributor
timestamp: July 25, 2020, 09:50:49 pm
content: Why are you usingfloaton an 8-bit microcontroller without hardware float support? Using e.g.int32_tto describe the values in thousandths (so 1 displays as 0.001 and -1 displays as -.001) would be just as precise, but much faster.Here's what I'd use:Code:#include <stdint.h>#define display_none 0x00#define display_dot 0x80#define display_neg 0x40#define display_over 0x5Cstatic const uint8_t display_digit = {0x3F, /* "0": 0011 1111 */0x06, /* "1": 0000 0110 */0x5B, /* "2": 0101 1011 */0x4F, /* "3": 0100 1111 */0x66, /* "4", 0110 0110 */0x6D, /* "5", 0110 1101 */0x7D, /* "6", 0111 1101 */0x07, /* "7", 0000 0111 */0x7F, /* "8", 0111 1111 */0x6F, /* "9", 0110 1111 */};/*  is rightmost,  leftmost */uint8_t display_pattern;void display_thousandths(int32_t value){uint_fast32_t u, v;int_fast8_t i, s, d;display_pattern = display_none;display_pattern = display_none;display_pattern = display_none;display_pattern = display_none;if (value >= 9999500) {/* Too large to display. */display_pattern = display_over;return;} elseif (value >= 1000000) {u = (value + 500) / 1000;s = 0;d = 0;} elseif (value >= 100000) {u = (value + 50) / 100;s = 0;d = 1;} elseif (value >= 10000) {u = (value + 5) / 10;s = 0;d = 2;} elseif (value > 0) {u = value;s = 0;d = 3;} elseif (value == 0) {display_pattern = display_digit;return;} elseif (value <= -999500) {/* Too large to display */display_pattern = display_neg;display_pattern = display_over;return;} elseif (value <= -100000) {u = (500 - value) / 1000;s = 1;d = 0;} elseif (value <= -10000) {u = (50 - value) / 100;s = 1;d = 1;} elseif (value <= -1000) {u = (5 - value) / 10;s = 1;d = 2;} else {u = (-value);s = 1;d = 3;}/* Optional: Remove trailing fractional zeros. */while (d > 1 && !(u % 10)) {u /= 10;d--;}/* Save the value. We'll need it later. */v = u;/* Convert to digit patterns. */i = 0;do {display_pattern[i++] = display_digit[u % 10];u /= 10;} while (u > 0);/* Zeros up to decimal point. */while (i < d) {display_pattern[i++] = display_digit;}/* Room for an unit zero? Need one? */if (d > 0 && s + i < 4) {if ((d == 1 && v < 10) ||(d == 2 && v < 100) ||(d == 3 && v < 1000)) {display_pattern[i++] = display_digit;}}/* Negative? */if (s && i < 4) {display_pattern = display_neg;}/* Decimal point? */if (d > 0) {display_pattern |= display_dot;}/** TODO: Update display based on display_pattern[].*/}and in your case, you can use the following to displayfloats via using the above:Code:void display_float(float value){if (value > 9999.999f)display_thousandths(9999999);elseif (value >= 0.0f)display_thousandths((int32_t)(1000.0f * value + 0.5f));elseif (value < -999.999f)display_thousandths(-999999);elsedisplay_thousandths((int32_t)(1000.0f * value - 0.5f));}Note that the0.5fabove are used for correct rounding.If you want to explore what that looks like, addCode:#include <stdlib.h>#include <stdio.h>static const unsigned char lcd_mask = {{ 0x21, 0x01, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00 },{ 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 },{ 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 },{ 0x70, 0x40, 0x40, 0x40, 0x46, 0x00, 0x00, 0x00 },{ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00 },{ 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00 },{ 0x18, 0x08, 0x08, 0x08, 0x0C, 0x00, 0x80, 0x00 },};int main(int argc, char *argv[]){float val;int arg, r, c, d;char dummy;for (arg = 1; arg < argc; arg++) {if (sscanf(argv, " %f %c", &val, &dummy) != 1) {fprintf(stderr, "%s: Invalid value.\n", argv);return EXIT_FAILURE;} else {printf("%s:\n", argv);display_float(val);for (r = 0; r < 7; r++) {for (d = 3; d >= 0; d--) {for (c = 0; c < 8; c++) {if (display_pattern & lcd_mask) {fputc('X', stdout);} else {fputc(' ', stdout);}}}fputc('\n', stdout);}fflush(stdout);}}return EXIT_SUCCESS;}so you can compile it on any C compiler, to be run on your development system. Supply one or more numbers as a command-line parameter, and it'll display a crude ASCII version of the expected seven-segment display. For example, for-99.25it will printCode:-99.25:XXXXX XXXXX XXXXXX X X X XX X X X XXXXXX XXXXX XXXXX XXXXXX X XX X XXXXXX XXXXX X XXXXXand for 92.127Code:XXXXX XXXXX X XXXXXX X X X XX X X X XXXXXX XXXXX X XXXXXX X X XX X X XXXXXX XXXXX X X XXXXXThe displayable range is -999 to 9999. The code is smart enough to format -0.001 as -.001, but will use a leading zero if one fits.

author: george.manson.69
author_rank: Newbie
timestamp: July 26, 2020, 03:41:24 am
content: Quote from: Nominal Animal on July 25, 2020, 09:50:49 pmExcellent, I'm going to use it and will tell you the results!,Thanks!