Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drivers/lpsxxx: avoid float arithmetics #19609

Merged
merged 1 commit into from
May 19, 2023
Merged

Conversation

maribu
Copy link
Member

@maribu maribu commented May 17, 2023

Contribution description

Perform computation directly in centi-degree-celsius to avoid floating point arithmetics. In addition, use scientific rounding in the division.

Testing procedure

Beware: Code is untested. This should change results (much).

Issues/PRs references

Fixes #17486

@maribu maribu added Impact: minor The PR is small in size and might only require a quick look of a knowledgeable reviewer Type: cleanup The issue proposes a clean-up / The PR cleans-up parts of the codebase / documentation Area: drivers Area: Device drivers CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels May 17, 2023
@maribu maribu requested a review from aabadie May 17, 2023 21:24
@riot-ci
Copy link

riot-ci commented May 17, 2023

Murdock results

✔️ PASSED

dcb49cb drivers/lpsxxx: avoid float arithmetics

Success Failures Total Runtime
6945 0 6945 10m:35s

Artifacts

Copy link
Contributor

@aabadie aabadie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something is wrong with this PR. I just tested it on iotlab and the temperature returned by the test application is wrong:

$ make -C tests/drivers/lpsxxx/ flash term BOARD=iotlab-m3 IOTLAB_NODE=auto
make: Entering directory '/work/riot/RIOT/tests/drivers/lpsxxx'
Building application "tests_lpsxxx" for "iotlab-m3" with MCU "stm32".

"make" -C /work/riot/RIOT/pkg/cmsis/ 
"make" -C /work/riot/RIOT/boards/common/init
"make" -C /work/riot/RIOT/boards/iotlab-m3
"make" -C /work/riot/RIOT/boards/common/iotlab
"make" -C /work/riot/RIOT/core
"make" -C /work/riot/RIOT/core/lib
"make" -C /work/riot/RIOT/cpu/stm32
"make" -C /work/riot/RIOT/cpu/cortexm_common
"make" -C /work/riot/RIOT/cpu/cortexm_common/periph
"make" -C /work/riot/RIOT/cpu/stm32/periph
"make" -C /work/riot/RIOT/cpu/stm32/stmclk
"make" -C /work/riot/RIOT/cpu/stm32/vectors
"make" -C /work/riot/RIOT/drivers
"make" -C /work/riot/RIOT/drivers/lpsxxx
"make" -C /work/riot/RIOT/drivers/periph_common
"make" -C /work/riot/RIOT/sys
"make" -C /work/riot/RIOT/sys/auto_init
"make" -C /work/riot/RIOT/sys/div
"make" -C /work/riot/RIOT/sys/frac
"make" -C /work/riot/RIOT/sys/libc
"make" -C /work/riot/RIOT/sys/malloc_thread_safe
"make" -C /work/riot/RIOT/sys/newlib_syscalls_default
"make" -C /work/riot/RIOT/sys/pm_layered
"make" -C /work/riot/RIOT/sys/preprocessor
"make" -C /work/riot/RIOT/sys/stdio_uart
"make" -C /work/riot/RIOT/sys/ztimer
   text	   data	    bss	    dec	    hex	filename
  12596	    156	   2324	  15076	   3ae4	/work/riot/RIOT/tests/drivers/lpsxxx/bin/iotlab-m3/tests_lpsxxx.elf
iotlab-node --jmespath='keys(@)[0]' --format='lambda ret: exit(int(ret))'  --list saclay,m3,10 --flash /work/riot/RIOT/tests/drivers/lpsxxx/bin/iotlab-m3/tests_lpsxxx.bin
ssh -t abadie@saclay.iot-lab.info 'socat - tcp:m3-10.saclay.iot-lab.info:20000' 
Pressure value: 1006hPa - Temperature: -263.-67°C
Pressure value: 1006hPa - Temperature: -263.-70°C
Pressure value: 1006hPa - Temperature: -263.-66°C
Pressure value: 1006hPa - Temperature: -263.-64°C
Pressure value: 1006hPa - Temperature: -263.-63°C
Pressure value: 1006hPa - Temperature: -263.-59°C
Pressure value: 1006hPa - Temperature: -263.-61°C
Pressure value: 1006hPa - Temperature: -263.-57°C
Pressure value: 1006hPa - Temperature: -263.-56°C

it works as expected on master:

$ make -C tests/drivers/lpsxxx/ flash term BOARD=iotlab-m3 IOTLAB_NODE=auto
make: Entering directory '/work/riot/RIOT/tests/drivers/lpsxxx'
Building application "tests_lpsxxx" for "iotlab-m3" with MCU "stm32".

"make" -C /work/riot/RIOT/pkg/cmsis/ 
"make" -C /work/riot/RIOT/boards/common/init
"make" -C /work/riot/RIOT/boards/iotlab-m3
"make" -C /work/riot/RIOT/boards/common/iotlab
"make" -C /work/riot/RIOT/core
"make" -C /work/riot/RIOT/core/lib
"make" -C /work/riot/RIOT/cpu/stm32
"make" -C /work/riot/RIOT/cpu/cortexm_common
"make" -C /work/riot/RIOT/cpu/cortexm_common/periph
"make" -C /work/riot/RIOT/cpu/stm32/periph
"make" -C /work/riot/RIOT/cpu/stm32/stmclk
"make" -C /work/riot/RIOT/cpu/stm32/vectors
"make" -C /work/riot/RIOT/drivers
"make" -C /work/riot/RIOT/drivers/lpsxxx
"make" -C /work/riot/RIOT/drivers/periph_common
"make" -C /work/riot/RIOT/sys
"make" -C /work/riot/RIOT/sys/auto_init
"make" -C /work/riot/RIOT/sys/div
"make" -C /work/riot/RIOT/sys/frac
"make" -C /work/riot/RIOT/sys/libc
"make" -C /work/riot/RIOT/sys/malloc_thread_safe
"make" -C /work/riot/RIOT/sys/newlib_syscalls_default
"make" -C /work/riot/RIOT/sys/pm_layered
"make" -C /work/riot/RIOT/sys/preprocessor
"make" -C /work/riot/RIOT/sys/stdio_uart
"make" -C /work/riot/RIOT/sys/ztimer
   text	   data	    bss	    dec	    hex	filename
  13860	    156	   2324	  16340	   3fd4	/work/riot/RIOT/tests/drivers/lpsxxx/bin/iotlab-m3/tests_lpsxxx.elf
iotlab-node --jmespath='keys(@)[0]' --format='lambda ret: exit(int(ret))'  --list saclay,m3,10 --flash /work/riot/RIOT/tests/drivers/lpsxxx/bin/iotlab-m3/tests_lpsxxx.bin
ssh -t abadie@saclay.iot-lab.info 'socat - tcp:m3-10.saclay.iot-lab.info:20000' 
Pressure value: 1006hPa - Temperature: 44.46°C
Pressure value: 1006hPa - Temperature: 44.47°C
Pressure value: 1006hPa - Temperature: 44.45°C
Pressure value: 1006hPa - Temperature: 44.46°C
Pressure value: 1006hPa - Temperature: 44.46°C
Pressure value: 1006hPa - Temperature: 44.49°C

Still on iotlab, the nrf52dk boards deployed in Saclay have a ST shield with an lps22hb. The temperature value read is also wrong:

$ make -C tests/drivers/lpsxxx/ flash term BOARD=nrf52dk DRIVER=lps22hb IOTLAB_NODE=auto
make: Entering directory '/work/riot/RIOT/tests/drivers/lpsxxx'
Building application "tests_lpsxxx" for "nrf52dk" with MCU "nrf52".

"make" -C /work/riot/RIOT/pkg/cmsis/ 
"make" -C /work/riot/RIOT/boards/common/init
"make" -C /work/riot/RIOT/boards/nrf52dk
"make" -C /work/riot/RIOT/boards/common/nrf52xxxdk
"make" -C /work/riot/RIOT/core
"make" -C /work/riot/RIOT/core/lib
"make" -C /work/riot/RIOT/cpu/nrf52
"make" -C /work/riot/RIOT/cpu/cortexm_common
"make" -C /work/riot/RIOT/cpu/cortexm_common/periph
"make" -C /work/riot/RIOT/cpu/nrf52/periph
"make" -C /work/riot/RIOT/cpu/nrf52/vectors
"make" -C /work/riot/RIOT/cpu/nrf5x_common
"make" -C /work/riot/RIOT/cpu/nrf5x_common/periph
"make" -C /work/riot/RIOT/drivers
"make" -C /work/riot/RIOT/drivers/lpsxxx
"make" -C /work/riot/RIOT/drivers/periph_common
"make" -C /work/riot/RIOT/sys
"make" -C /work/riot/RIOT/sys/auto_init
"make" -C /work/riot/RIOT/sys/div
"make" -C /work/riot/RIOT/sys/frac
"make" -C /work/riot/RIOT/sys/libc
"make" -C /work/riot/RIOT/sys/malloc_thread_safe
"make" -C /work/riot/RIOT/sys/newlib_syscalls_default
"make" -C /work/riot/RIOT/sys/preprocessor
"make" -C /work/riot/RIOT/sys/stdio_uart
"make" -C /work/riot/RIOT/sys/ztimer
   text	   data	    bss	    dec	    hex	filename
  12156	    148	   2636	  14940	   3a5c	/work/riot/RIOT/tests/drivers/lpsxxx/bin/nrf52dk/tests_lpsxxx.elf
iotlab-node --jmespath='keys(@)[0]' --format='lambda ret: exit(int(ret))'  --list saclay,nrf52dk,10 --flash /work/riot/RIOT/tests/drivers/lpsxxx/bin/nrf52dk/tests_lpsxxx.bin
ssh -t abadie@saclay.iot-lab.info 'socat - tcp:nrf52dk-10.saclay.iot-lab.info:20000' 
Pressure value: 1005hPa - Temperature:  1.48°C
Pressure value: 1005hPa - Temperature:  1.50°C
Pressure value: 1005hPa - Temperature:  1.51°C
Pressure value: 1005hPa - Temperature:  1.51°C

Whereas it's correct on master:

$ make -C tests/drivers/lpsxxx/ flash term BOARD=nrf52dk DRIVER=lps22hb IOTLAB_NODE=auto
make: Entering directory '/work/riot/RIOT/tests/drivers/lpsxxx'
Building application "tests_lpsxxx" for "nrf52dk" with MCU "nrf52".

"make" -C /work/riot/RIOT/pkg/cmsis/ 
"make" -C /work/riot/RIOT/boards/common/init
"make" -C /work/riot/RIOT/boards/nrf52dk
"make" -C /work/riot/RIOT/boards/common/nrf52xxxdk
"make" -C /work/riot/RIOT/core
"make" -C /work/riot/RIOT/core/lib
"make" -C /work/riot/RIOT/cpu/nrf52
"make" -C /work/riot/RIOT/cpu/cortexm_common
"make" -C /work/riot/RIOT/cpu/cortexm_common/periph
"make" -C /work/riot/RIOT/cpu/nrf52/periph
"make" -C /work/riot/RIOT/cpu/nrf52/vectors
"make" -C /work/riot/RIOT/cpu/nrf5x_common
"make" -C /work/riot/RIOT/cpu/nrf5x_common/periph
"make" -C /work/riot/RIOT/drivers
"make" -C /work/riot/RIOT/drivers/lpsxxx
"make" -C /work/riot/RIOT/drivers/periph_common
"make" -C /work/riot/RIOT/sys
"make" -C /work/riot/RIOT/sys/auto_init
"make" -C /work/riot/RIOT/sys/div
"make" -C /work/riot/RIOT/sys/frac
"make" -C /work/riot/RIOT/sys/libc
"make" -C /work/riot/RIOT/sys/malloc_thread_safe
"make" -C /work/riot/RIOT/sys/newlib_syscalls_default
"make" -C /work/riot/RIOT/sys/preprocessor
"make" -C /work/riot/RIOT/sys/stdio_uart
"make" -C /work/riot/RIOT/sys/ztimer
   text	   data	    bss	    dec	    hex	filename
  12152	    148	   2636	  14936	   3a58	/work/riot/RIOT/tests/drivers/lpsxxx/bin/nrf52dk/tests_lpsxxx.elf
iotlab-node --jmespath='keys(@)[0]' --format='lambda ret: exit(int(ret))'  --list saclay,nrf52dk,10 --flash /work/riot/RIOT/tests/drivers/lpsxxx/bin/nrf52dk/tests_lpsxxx.bin
ssh -t abadie@saclay.iot-lab.info 'socat - tcp:nrf52dk-10.saclay.iot-lab.info:20000' 
Pressure value: 1005hPa - Temperature: 27.62°C
Pressure value: 1005hPa - Temperature: 27.66°C
Pressure value: 1005hPa - Temperature: 27.67°C
Pressure value: 1005hPa - Temperature: 27.69°C

The 20° difference with the M3 comes from the fact that the M3s are in a closed box with an embedded Linux close/connected to it and it can be pretty hot inside. The nrf52dk are outside of the box :)

/* compute actual temperature value in °C */
res += ((float)val) / TEMP_DIVIDER;
/* convert val to c°C */
val *= 100;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could it be that since val is int16 there's an overflow when multiplying by 100 ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could it be that since val is int16 there's an overflow when multiplying by 100 ?

Yes that's it. With the following diff, I get correct temperature values:

diff --git a/drivers/lpsxxx/lpsxxx.c b/drivers/lpsxxx/lpsxxx.c
index e0047c6cae..7019a94b42 100644
--- a/drivers/lpsxxx/lpsxxx.c
+++ b/drivers/lpsxxx/lpsxxx.c
@@ -131,7 +131,7 @@ int lpsxxx_init(lpsxxx_t *dev, const lpsxxx_params_t * params)
 int lpsxxx_read_temp(const lpsxxx_t *dev, int16_t *temp)
 {
     uint8_t tmp;
-    int16_t val = 0;
+    int32_t val = 0;
     uint16_t res = TEMP_BASE;      /* reference value -> see datasheet */
 
     i2c_acquire(DEV_I2C);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for testing, I applied the bugfix :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure which target you are going for but assuming uint32_t val;
turning all of it into one multiplication might be faster.

(val *((100L<<16)/480))>>16)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PRs are always welcome :)

@aabadie
Copy link
Contributor

aabadie commented May 19, 2023

bors merge

@bors
Copy link
Contributor

bors bot commented May 19, 2023

Build succeeded!

The publicly hosted instance of bors-ng is deprecated and will go away soon.

If you want to self-host your own instance, instructions are here.
For more help, visit the forum.

If you want to switch to GitHub's built-in merge queue, visit their help page.

@bors bors bot merged commit 2327d74 into RIOT-OS:master May 19, 2023
@maribu maribu deleted the drivers/lpsxxx branch May 19, 2023 14:35
@maribu
Copy link
Member Author

maribu commented May 19, 2023

thx :)

@benpicco benpicco added this to the Release 2023.07 milestone Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: drivers Area: Device drivers CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Impact: minor The PR is small in size and might only require a quick look of a knowledgeable reviewer Type: cleanup The issue proposes a clean-up / The PR cleans-up parts of the codebase / documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

lpsxxx: float arithmetics
5 participants