【问题标题】:Display floating point numbers on an LCD在 LCD 上显示浮点数
【发布时间】:2017-04-04 09:12:43
【问题描述】:

如何获取变量伏特以在 LCD 上显示浮点数?

LCD 只显示带有很多小数位的浮点值,并以 E 结尾。我只需要 2 个小数位,那么如何显示呢?

int main (void){

    adcinit();

    lcd_init();//initializes LCD
    lcd_clear();//clear screen
    lcd_home();


    uint16_t value;
    float volts;
    while(1){
        ADCSRA |= (1<<ADSC);//start ADC conversion
        delay_ms(54);//delay 54 millisecond
        value = ADCW;//assign ADC conversion to value
        volts=(value*5)/1023;
        lcd_goto_xy(0,0);// coordinates of the cursor on LCD Display
        lcd_printf("ADC Value: %d ",value);//display on LCD
        lcd_goto_xy(0,1);// coordinates of the cursor on LCD Display
        lcd_printf("Volts: %f ",volts);//display on LCD
    }
}

【问题讨论】:

  • 它显示什么?
  • 这里有问题volts=(value*5)/1023。所有这些都是整数,因此计算的结果将是整数。这可能不是你想要的。尝试使用volts = (value * 5f) / 1023f
  • 或者考虑显示毫伏:unsigned volts=(value*5000L + 1024/2 /* add this value to round */)/1024; 并避免使用 FP 数学。
  • 上面的代码确实显示,伏特:液晶显示屏上的 1.00000E0。
  • chux,当您说 /* 将此值添加到舍入 */ 时,您的意思是例如 2 位小数:unsignedvolts(value*5000L+1024/2*100)/1024; ?

标签: c eclipse arduino proximitysensor


【解决方案1】:

我正在回答原帖最后一句中的问题 - 而不是标题。但这是您项目的正确答案。

您说“我只需要 2 个小数位” - 所以这应该告诉您不需要浮点数学。物理学家和工程师需要浮点数来表示非常非常小或非常非常大的数量,但您需要“定点” - 这意味着进行整数数学并正确选择单位。定点更快、更准确,并减少了编译二进制文件的大小,因为不需要浮点代码。

最简单的解决方案是使用整数并显示毫伏,就像您刚刚使用的 delay() 函数接受整数毫秒数的参数一样,而不是小数秒数。

#define VREF 5000
uint32_t mvolts;
.
.
mvolts=(value*VREF)>>10; // No floats here...
lcd_printf("milliVolts: %d",mvolts); // ...and no casts

如果您必须显示电压,那么这就是诀窍:

lcd_printf("Volts: %d.%02d ",mvolts/1000, (mvolts%1000)/10);

请注意,顺便说一句,mvolts 是一个 32 位整数,因为您现在将 10 位数字乘以 5000,而这不适合 16 位。这是必需的,因为您需要在进行缩放时保持值的准确性。我不认为这是题外话,因为我认为您确实想要显示 正确 值,否则显示这两个小数位是没有意义的。

除非你很小心,否则编译器会计算出 5000/1024 - 4.8828125 的值 - 然后进行整数运算,这会切断小数部分并最终将 ADC 结果乘以 4。为了保证正确的行为,乘以 5000,然后除以 - 2 个单独的操作。由于 1024 是 2**10,所以右移 10 位等同于除以 1024。

最后 - 不要假设从 ADC 读取 1023 实际上意味着 5.000 伏到 4 位有效数字;通过调整#define VREF 来校准经过测试的电压表以获得正确的结果。

【讨论】:

  • 刚刚编辑了我的答案,我突然想到你认为你需要浮点数的原因可能是为了代表比例因子。是这样吗?chux 和 msandiford 都在上面评论了相同的问题 - 我只是在更详细地解释发生了什么。
  • 如果您只需要几分之一伏特,则必须将 lcd_printf() 调用时的最后一个表达式除以 10 才能得到正确的结果,如 mvolts % 1000 / 10
  • Luis:很好,我倾向于以 mV 为单位。
【解决方案2】:

如果函数lcd_printf()与Arduino的函数sprintf()基于相同的库,则格式说明符'%f'即使用作'%.2f'也没有得到很好的管理。

第 1 步:在提出替代解决方案之前,有必要从从模数转换器读取的数值中得到一个经过良好计算的浮点值。

如果 ADC 是 10 位,则范围应为 1024(而不是 1023)。

value = ADCW;//assign ADC conversion to value
volts=((float)value*5.0f)/(1024.0f); 

Step2.1:显示 2 位小数固定浮点值的第一个快速解决方案是将其转换为 2 个整数。

lcd_printf("Volts: %d.%02d ",(int)volts, (int)(volts*100)%100));//display on LCD

而不是

lcd_printf("Volts: %.2f ",volts);//display on LCD

步骤 2.2:显示 2 位小数固定浮点值的更“官方”解决方案是使用 "Arduino sprintf float not formatting" 中建议的 dtostrf() 函数。

char str_volts[15]; // to store the float-to-string converted value
lcd_printf("Volts: %s ",dtostrf(volts, 4, 2, str_volts));//display on LCD
// 4 = minimum number of char ('X.XX'), 2 = number of decimals

而不是

lcd_printf("Volts: %.2f ",volts);//display on LCD

【讨论】:

    【解决方案3】:

    试试这个:

    编辑:我刚刚编辑了电压的显示,因为值是 int。但原则是一样的。

    int main (void){
    
        adcinit();
    
        lcd_init();//initializes LCD
        lcd_clear();//clear screen
        lcd_home();
    
    
        uint16_t value;
        float volts;
        while(1){
            ADCSRA |= (1<<ADSC);//start ADC conversion
            delay_ms(54);//delay 54 millisecond
            value = ADCW;//assign ADC conversion to value
            volts=(float)(value*5)/1023;
            lcd_goto_xy(0,0);// coordinates of the cursor on LCD Display
            lcd_printf("ADC Value: %d ",value);//display on LCD
            lcd_goto_xy(0,1);// coordinates of the cursor on LCD Display
            lcd_printf("Volts: %.2f ",volts);//display on LCD
        }
    }
    

    【讨论】:

    • 强制转换似乎是错误的,或者至少对于阅读此代码的人来说不清楚。典型值为伏特=(值*5.0)/1023; (这里不讨论1023)
    • 演员表适用于除法的左侧,因此即使对读者造成不必要的混淆,它似乎也是正确的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-15
    相关资源
    最近更新 更多