Skip to content

Add hx711 ADC driver and saul#14039

Open
Citrullin wants to merge 2 commits intoRIOT-OS:masterfrom
Citrullin:hx711
Open

Add hx711 ADC driver and saul#14039
Citrullin wants to merge 2 commits intoRIOT-OS:masterfrom
Citrullin:hx711

Conversation

@Citrullin
Copy link
Contributor

@Citrullin Citrullin commented May 7, 2020

Contribution description

HX711 ADC driver for weigh scales. Including SAUL implementation.

Testing procedure

tests/driver_hx711

  1. Connect a HX711 board to a load cell on channel A.
  2. Connect DT (DOUT) and SCK to a GPIO pin of your board.
  3. Go into tests/drvier_hx711 and change the values of HX711_PARAM_SCK, HX711_PARAM_DOUT. If you use another board, change it as well.
  4. Execute the test

SAUL

  1. Connect the HX711 board to a weigh scale on channel A. Connect the hx711 breakout board to your microcontroller board.
  2. Go into examples/saul and add the following to the Makefile. Change the values accordingly.
USEMODULE += hx711
CFLAGS += "-DHX711_PARAM_SCK=GPIO_PIN(1, 13)"
CFLAGS += "-DHX711_PARAM_DOUT=GPIO_PIN(1, 14)"
  1. Flash the saul example and also use the target term.
  2. Use saul write [ID] 200 to tare the scale.
  3. Place a weight on your scale and execute saul read [TIMES] where [TIMES] is the number of reads. It should show the correct weight. If not, you have to adapt the divider. It is the value of HX711_PARAM_DIVIDER. If the weight result is too high, set a higher divider. If it is too low, you have to lower the divider. Until you have the correct value. You should use standardized weights in order to get precise results.

Issues/PRs references

Previous PR: #11416

@jue89
Copy link
Contributor

jue89 commented May 7, 2020

Hey @Citrullin!

Thanks for your contribution! One idea / question that came into my mind while reading over your code: Are there use cases that require one application to acquire different amounts of measurements for averaging?
If not, I would get rid of the times parameter and rely on on the configured dev.params.read_times. This would simplify the API.

It might be also good to split the driver into two separat commits: One for the driver itself and one for the saul wrapper.

@Citrullin
Copy link
Contributor Author

Hey @Citrullin!

Thanks for your contribution! One idea / question that came into my mind while reading over your code: Are there use cases that require one application to acquire different amounts of measurements for averaging?
If not, I would get rid of the times parameter and rely on on the configured dev.params.read_times. This would simplify the API.

It might be also good to split the driver into two separat commits: One for the driver itself and one for the saul wrapper.

It changes the accuracy of the results. With 200 it is accurate, but also really slow. I think the test takes 2 minutes or something like this.

@jue89
Copy link
Contributor

jue89 commented May 8, 2020

It changes the accuracy of the results. With 200 it is accurate, but also really slow. I think the test takes 2 minutes or something like this.

So it might be useful to average more measurements during tare process than the actual measurement?!

@Citrullin
Copy link
Contributor Author

It changes the accuracy of the results. With 200 it is accurate, but also really slow. I think the test takes 2 minutes or something like this.

So it might be useful to average more measurements during tare process than the actual measurement?!

Is an option, yes. Will change. One for normal ones and one for taring.

@miri64 miri64 added Area: drivers Area: Device drivers Area: SAUL Area: Sensor/Actuator Uber Layer Type: new feature The issue requests / The PR implemements a new feature for RIOT labels Jul 2, 2020
@miri64 miri64 requested a review from maribu July 2, 2020 15:42
Copy link
Member

@maribu maribu left a comment

Choose a reason for hiding this comment

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

Some comments inline

@@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base No newline at end of file
Copy link
Member

Choose a reason for hiding this comment

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

newline missing. (This is a configuration issue in your text editor. A correctly configured editor should never safe a text file without the newline. You might want to fix the configuration, so that you don't need to worry about this anymore.)

Comment on lines +81 to +83
value.u8.data[2] = gpio_util_shiftin(dout, sck);
value.u8.data[1] = gpio_util_shiftin(dout, sck);
value.u8.data[0] = gpio_util_shiftin(dout, sck);
Copy link
Member

Choose a reason for hiding this comment

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

How are timing constraints of the hardware are enforced? The datasheet says a clock speed of at most 20 MHz is supported.

If this driver happens to be used on a faster board (e.g. lets say an ESP32 or an STM32F4xx or STM32F7xx) and the application is compiled with LTO enabled, a gpio_set(), a gpio_read() and a gpio_clear() are performed in a single CPU cycle each. Let's assume 8 CPU cycles are required per bit with LTO=1 on an ESP32 clocked at 240 MHz: gpio_util_shiftin() would then run with a clock of 30 MHz.

I think we can be pretty sure that any currently supported board with the current GPIO implementation would not get anywhere near the 20 MHz without LTO being used. But once all issues with LTO are resolved, it might get enabled by default.

Making the GPIO API inline-able is also something that could result in drastic speed ups of the GPIOs; and this is something that is not so unlikely to happen.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's a really good point and would lead to an issue. They are not enforced. I need to think about this. Do you have an idea?

Copy link
Member

Choose a reason for hiding this comment

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

IMO, this issue could arise to all users of gpio_util_shiftin(), if LTO is enabled. So maybe the best is to extend it to also take a third argument specifying the maximum speed. This could be implemented using xtimer_periodic_wakeup()

If the GPIO ABC API proposed in #12015 would already be available, it would be even possible to provide a clock frequency argument (instead of a maximum clock frequency argument): With GPIO ABC it would be possible to match the clock frequency quite well. Maybe I should invest some time to polish that API and add "killer applications" on top of it to motivate the API.

So for now: The xtimer_periodic_wakeup() is the best option IMO. But I don't think that an API change will make it into the upcoming release, as this is not something usually merged during the feature freeze. But it is not too long until the next development cycle starts and PRs can of course be opened and reviewed at any point in time, only the merging is limited during feature freeze.

Comment on lines +85 to +88
for (unsigned i = 0; i < gain; i++) {
gpio_set(sck);
gpio_clear(sck);
}
Copy link
Member

Choose a reason for hiding this comment

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

Here again the clock frequency could easily exceed the allowed maximum depending on the performance of the GPIO implementation

Comment on lines +90 to +92
if (value.u8.data[2] & 0x80) {
value.u8.fill_byte = 0xFF;
}
Copy link
Member

Choose a reason for hiding this comment

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

sign extending 24 bits to 32 bits? If so, maybe add a comment


int32_t hx711_get_units(hx711_t *dev, int8_t times)
{
return (int32_t) (hx711_get_value(dev, times) / dev->params.divider);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
return (int32_t) (hx711_get_value(dev, times) / dev->params.divider);
return hx711_get_value(dev, times) / dev->params.divider;

#endif

#endif /* HX711_H */
/** @} */ No newline at end of file
Copy link
Member

Choose a reason for hiding this comment

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

missing newline

Comment on lines +97 to +107
int32_t hx711_read_average(hx711_t *dev, uint8_t times)
{
int32_t sum = 0;
uint8_t i = times;

while (i--) {
sum += hx711_read(dev);
}

return sum / times;
}
Copy link
Member

Choose a reason for hiding this comment

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

Is it needed to expose this function in the public API? If I don't miss anything, a user would call hx711_get_units() or hx711_tare() and never call this function directly, right? If so, please add static as qualifier

CFLAGS += "-DHX711_PARAM_SCK=GPIO_PIN(1, 13)"
CFLAGS += "-DHX711_PARAM_DOUT=GPIO_PIN(1, 14)"

include $(RIOTBASE)/Makefile.include No newline at end of file
Copy link
Member

Choose a reason for hiding this comment

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

missing newline

include ../Makefile.tests_common

BOARD ?= bluepill
FEATURES_REQUIRED += periph_gpio
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
FEATURES_REQUIRED += periph_gpio

The driver depends on periph_gpio already. So no need to specify this twice


expect(value_before > value_after);
expect(value_after <= 1);

Copy link
Member

Choose a reason for hiding this comment

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

Maybe drop to the shell afterwards so that the SAUL integration can be tested using the saul command?

@fjmolinas
Copy link
Contributor

ping @Citrullin :)

@tperchoc

This comment has been minimized.

@maribu
Copy link
Member

maribu commented Apr 1, 2021

@tperchoc: Care to adopt this PR? (E.g. by opening a new PR based on this and keeping the copyright. Of course, extend the copyright and author list as needed.)

@MrKevinWeiss MrKevinWeiss added this to the Release 2021.07 milestone Jun 22, 2021
@MrKevinWeiss MrKevinWeiss removed this from the Release 2021.07 milestone Jul 15, 2021
@stale
Copy link

stale bot commented Mar 2, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you want me to ignore this issue, please mark it with the "State: don't stale" label. Thank you for your contributions.

@stale stale bot added the State: stale State: The issue / PR has no activity for >185 days label Mar 2, 2022
@Citrullin
Copy link
Contributor Author

@tperchoc Should I just close this issue and you open another PR?

@stale stale bot removed the State: stale State: The issue / PR has no activity for >185 days label Apr 6, 2022
@jwktje
Copy link

jwktje commented Apr 15, 2022

@Citrullin I found this PR by looking for a way to use the HX711 in RIOT-OS. Do we need to wait for this PR to be merged or can I already use the HX711 somehow?

@tperchoc
Copy link

Hello, im alive just i didnt remember what i did here sry ;) just do has you want

@Citrullin
Copy link
Contributor Author

Citrullin commented Apr 18, 2022

@Citrullin I found this PR by looking for a way to use the HX711 in RIOT-OS. Do we need to wait for this PR to be merged or can I already use the HX711 somehow?

Would be great, if you just fork @tperchoc repo, pull the most recent main branch and create a new PR. I am happy to test it. :D

@stale
Copy link

stale bot commented Nov 2, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you want me to ignore this issue, please mark it with the "State: don't stale" label. Thank you for your contributions.

@stale stale bot added the State: stale State: The issue / PR has no activity for >185 days label Nov 2, 2022
@Citrullin
Copy link
Contributor Author

Good point. I am just talking to someone about it ^^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: drivers Area: Device drivers Area: SAUL Area: Sensor/Actuator Uber Layer State: stale State: The issue / PR has no activity for >185 days Type: new feature The issue requests / The PR implemements a new feature for RIOT

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants