Trouble with avia_hx711_calibrate() function of "nobodyguy" HX711_zephyr_driver

I'm using the code based on this link (https://github.com/nobodyguy/HX711_zephyr_driver) But i've made some changes onto the hx711.c like change the target value (I've put my load sensors to a wood board of 2.1kg so my target for calibration would be 2100 grams) so i've made the necessary changes to the code like calibration_weight and target (both 2100 because of the wood board).

I'm using nRF connect version 2.3.0 with an nrf21540dk_nrf52840 board by the way.

I'm going to put my used code right below:

main.c:

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/util.h>
#include <zephyr/types.h>
#include <stddef.h>

LOG_MODULE_REGISTER(main, LOG_LEVEL_INF);

const struct device *hx711_dev;

void measure(void)
{
static struct sensor_value weight;
int ret;

ret = sensor_sample_fetch(hx711_dev);
if (ret != 0) {
LOG_ERR("Cannot take measurement: %d", ret);
} else {
ret = sensor_channel_get(hx711_dev, SENSOR_CHAN_PRIV_START, &weight);
if (ret != 0) {
LOG_ERR("Failed to read weight: %d", ret);
} else {
LOG_INF("Weight: %d grams", weight.val1, weight.val2);
}
}
}
void main(void)
{
int calibration_weight = 2100; // grams
hx711_dev = DEVICE_DT_GET_ANY(avia_hx711);

if (hx711_dev == NULL) {
LOG_ERR("Failed to get device binding");
return;
}

LOG_INF("Device is %p, name is %s", hx711_dev, hx711_dev->name);
LOG_INF("Calculating offset...");
avia_hx711_tare(hx711_dev, 10);

LOG_INF("Waiting for known weight of %d grams...", calibration_weight);

//avia_hx711_calibrate(hx711_dev, calibration_weight, 10);

while (true) {
k_msleep(1000);
measure();
}
}

hx711.c :

#define DT_DRV_COMPAT avia_hx711
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/irq.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/pm/device.h>

#include "hx711.h"

#define SAMPLE_FETCH_TIMEOUT_MS 600

LOG_MODULE_REGISTER(HX711, CONFIG_SENSOR_LOG_LEVEL);

static struct hx711_data hx711_data = {
.reading = 0,
.offset = CONFIG_HX711_OFFSET,
.slope =
{
.val1 = CONFIG_HX711_SLOPE_INTEGER,
.val2 = CONFIG_HX711_SLOPE_DECIMAL,
},
.gain = CONFIG_HX711_GAIN,
.rate = CONFIG_HX711_SAMPLING_RATE,
.power = HX711_POWER_ON,
};

static const struct hx711_config hx711_config = {
.dout_pin = DT_INST_GPIO_PIN(0, dout_gpios),
.dout_ctrl = DEVICE_DT_GET(DT_GPIO_CTLR(DT_DRV_INST(0), dout_gpios)),
.dout_flags = DT_INST_GPIO_FLAGS(0, dout_gpios),

.sck_pin = DT_INST_GPIO_PIN(0, sck_gpios),
.sck_ctrl = DEVICE_DT_GET(DT_GPIO_CTLR(DT_DRV_INST(0), sck_gpios)),
.sck_flags = DT_INST_GPIO_FLAGS(0, sck_gpios),
#if DT_INST_NODE_HAS_PROP(0, rate_gpios)
.rate_pin = DT_INST_GPIO_PIN(0, rate_gpios),
.rate_ctrl = DEVICE_DT_GET(DT_GPIO_CTLR(DT_DRV_INST(0), rate_gpios)),
.rate_flags = DT_INST_GPIO_FLAGS(0, rate_gpios),
#endif

};

static void hx711_gpio_callback(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
struct hx711_data *data = CONTAINER_OF(cb, struct hx711_data, dout_gpio_cb);
const struct hx711_config *cfg = data->dev->config;

gpio_pin_interrupt_configure(data->dout_gpio, cfg->dout_pin, GPIO_INT_DISABLE);

/* Signal thread that data is now ready */
k_sem_give(&data->dout_sem);
}

static int hx711_cycle(struct hx711_data data)
{
gpio_pin_set(data->sck_gpio, hx711_config.sck_pin, true);
k_busy_wait(1);

gpio_pin_set(data->sck_gpio, hx711_config.sck_pin, false);
k_busy_wait(1);

return gpio_pin_get(data->dout_gpio, hx711_config.dout_pin);
}

static int hx711_sample_fetch(const struct device *dev, enum sensor_channel chan)
{
int ret = 0;
uint32_t count = 0;
int i;

struct hx711_data *data = dev->data;
const struct hx711_config *cfg = dev->config;

if (data->power != HX711_POWER_ON) {
return -EACCES;
}
if (k_sem_take(&data->dout_sem, K_FOREVER)) { // K_MSEC(SAMPLE_FETCH_TIMEOUT_MS))) {
LOG_ERR("Weight data not ready within %d ms", SAMPLE_FETCH_TIMEOUT_MS);
ret = -EIO;
goto exit;
}

#ifdef CONFIG_HX711_DISABLE_INTERRUPTS_WHILE_POLLING
uint32_t key = irq_lock();
#endif
for (i = 0; i < 24; i++) {
count = count << 1;
if (hx711_cycle(data)) {
count++;
}
}

for (i = 0; i < data->gain; i++) {
hx711_cycle(data);
}
#ifdef CONFIG_HX711_DISABLE_INTERRUPTS_WHILE_POLLING
irq_unlock(key);
#endif

count ^= 0x800000;

data->reading = count;
exit:
ret = gpio_pin_interrupt_configure(data->dout_gpio, cfg->dout_pin,
GPIO_INT_EDGE_TO_INACTIVE);
if (ret != 0) {
LOG_ERR("Failed to set dout GPIO interrupt");
}

return ret;
}

static int hx711_attr_set_gain(const struct device *dev, const struct sensor_value *val)
{
struct hx711_data *data = dev->data;

switch (val->val1) {
case HX711_GAIN_128X:
data->gain = HX711_GAIN_128X;
break;
case HX711_GAIN_32X:
data->gain = HX711_GAIN_32X;
break;
case HX711_GAIN_64X:
data->gain = HX711_GAIN_64X;
break;
default:
return -ENOTSUP;
}
return hx711_sample_fetch(dev, HX711_SENSOR_CHAN_WEIGHT);
}

#if DT_INST_NODE_HAS_PROP(0, rate_gpios)

static int hx711_attr_set_rate(struct hx711_data *data, const struct sensor_value *val)
{
int ret;

switch (val->val1) {
case HX711_RATE_10HZ:
case HX711_RATE_80HZ:
if (data->rate_gpio == NULL) {
LOG_ERR("Failed to get pointer to RATE device");
return -EINVAL;
}
data->rate = val->val1;
ret = gpio_pin_set(data->rate_gpio, hx711_config.rate_pin, data->rate);
return ret;
default:
return -ENOTSUP;
}
}
#endif

static void hx711_attr_set_offset(struct hx711_data *data, const struct sensor_value *offset)
{
data->offset = offset->val1;
}

static void hx711_attr_set_slope(struct hx711_data *data, const struct sensor_value *slope)
{
data->slope.val1 = slope->val1;
data->slope.val2 = slope->val2;
}

static int hx711_attr_set(const struct device *dev, enum sensor_channel chan,
enum sensor_attribute attr, const struct sensor_value *val)
{
int ret = 0;
int hx711_attr = (int)attr;
struct hx711_data *data = dev->data;

switch (hx711_attr) {
#if DT_INST_NODE_HAS_PROP(0, rate_gpios)
case SENSOR_ATTR_SAMPLING_FREQUENCY:
ret = hx711_attr_set_rate(data, val);
if (ret == 0) {
LOG_DBG("Attribute RATE set to %d\n", data->rate);
}
return ret;
#endif
case SENSOR_ATTR_OFFSET:
hx711_attr_set_offset(data, val);
LOG_DBG("Attribute OFFSET set to %d\n", data->offset);
return ret;
case HX711_SENSOR_ATTR_SLOPE:
hx711_attr_set_slope(data, val);
LOG_DBG("Attribute SLOPE set to %d.%d\n", data->slope.val1, data->slope.val2);
return ret;
case HX711_SENSOR_ATTR_GAIN:
ret = hx711_attr_set_gain(dev, val);
if (ret == 0) {
LOG_DBG("Attribute GAIN set to %d\n", data->gain);
}
return ret;
default:
return -ENOTSUP;
}
}

static int hx711_channel_get(const struct device *dev, enum sensor_channel chan,
struct sensor_value *val)
{
enum hx711_channel hx711_chan = (enum hx711_channel)chan;
struct hx711_data *data = dev->data;

switch (hx711_chan) {
case HX711_SENSOR_CHAN_WEIGHT: {
val->val1 = sensor_value_to_double(&data->slope) * (data->reading - data->offset);
return 0;
}
default:
return -ENOTSUP;
}
}

static int hx711_init(const struct device *dev)
{
LOG_DBG("Initialising HX711\n");

int ret = 0;
struct hx711_data *data = dev->data;
const struct hx711_config *cfg = dev->config;

LOG_DBG("SCK GPIO port : %s\n", cfg->sck_ctrl->name);
LOG_DBG("SCK Pin : %d\n", cfg->sck_pin);
LOG_DBG("DOUT GPIO port : %s\n", cfg->dout_ctrl->name);
LOG_DBG("DOUT Pin : %d\n", cfg->dout_pin);
#if DT_INST_NODE_HAS_PROP(0, rate_gpios)
LOG_DBG("RATE GPIO port : %s\n", cfg->rate_ctrl->name);
LOG_DBG("RATE Pin : %d\n", cfg->rate_pin);
#endif

LOG_DBG("Gain : %d\n", data->gain);
LOG_DBG("Offset : %d\n", data->offset);
LOG_DBG("Slope : %d.%d\n", data->slope.val1, data->slope.val2);

data->sck_gpio = cfg->sck_ctrl;
LOG_DBG("SCK pin controller is %p, name is %s\n", data->sck_gpio, data->sck_gpio->name);

ret = gpio_pin_configure(data->sck_gpio, cfg->sck_pin,
GPIO_OUTPUT_INACTIVE | cfg->sck_flags);
if (ret != 0) {
return ret;
}

k_sem_init(&data->dout_sem, 0, K_SEM_MAX_LIMIT);

data->dout_gpio = cfg->sck_ctrl;
LOG_DBG("DOUT pin controller is %p, name is %s\n", data->dout_gpio, data->dout_gpio->name);
ret = gpio_pin_configure(data->dout_gpio, cfg->dout_pin, GPIO_INPUT | cfg->dout_flags);
if (ret != 0) {
return ret;
}
LOG_DBG("Set DOUT pin : %d\n", cfg->dout_pin);

gpio_init_callback(&data->dout_gpio_cb, hx711_gpio_callback, BIT(cfg->dout_pin));

if (gpio_add_callback(data->dout_gpio, &data->dout_gpio_cb) < 0) {
LOG_DBG("Failed to set GPIO callback");
return -EIO;
}

ret = gpio_pin_interrupt_configure(data->dout_gpio, cfg->dout_pin,
GPIO_INT_EDGE_TO_INACTIVE);
if (ret != 0) {
LOG_ERR("Failed to set dout GPIO interrupt");
return ret;
}

data->dev = dev;

return ret;
}

int avia_hx711_tare(const struct device *dev, uint8_t readings)
{
int32_t avg = 0;
struct hx711_data *data = dev->data;

if (readings == 0) {
readings = 1;
}

for (int i = 0; i < readings; i++) {
hx711_sample_fetch(dev, HX711_SENSOR_CHAN_WEIGHT);
avg += data->reading;
}
LOG_DBG("Average before division : %d", avg);
avg = avg / readings;
LOG_DBG("Average after division : %d", avg);
data->offset = avg;

for (int i = 10; i >= 0; i--) {
LOG_INF(" %d..", i);
k_msleep(1000);
}

for (int i = 0; i < readings; i++) {
hx711_sample_fetch(dev, HX711_SENSOR_CHAN_WEIGHT);
avg += data->reading;
}
LOG_DBG("Average before division : %d", avg);
avg = avg / readings;
LOG_DBG("Average after division : %d", avg);

double slope = (double)215000 / (double)(avg - data->offset);

data->slope.val1 = (int)slope;
data->slope.val2 = (slope - data->slope.val1) * 1e6;

LOG_DBG("Slope set to : %d.%06d", data->slope.val1, data->slope.val2);

return data->offset;
}

struct sensor_value avia_hx711_calibrate(const struct device *dev, uint32_t target, uint8_t readings)
{
int32_t avg = 0;
struct hx711_data *data = dev->data;

if (readings == 0) {
readings = 1;
}

for (int i = 0; i < readings; i++) {
hx711_sample_fetch(dev, HX711_SENSOR_CHAN_WEIGHT);
avg += data->reading;
}

LOG_DBG("Average before division : %d", avg);
avg = avg / readings;

LOG_DBG("Average after division : %d", avg);
double slope = (double)210000 / (double)(avg - data->offset);

data->slope.val1 = (int)slope;
data->slope.val2 = (slope - data->slope.val1) * 1e6;

LOG_DBG("Slope set to : %d.%06d", data->slope.val1, data->slope.val2);

return data->slope;
}

int avia_hx711_power(const struct device *dev, enum hx711_power pow)
{
int ret;
struct hx711_data *data = dev->data;

data->power = pow;
switch (pow) {
case HX711_POWER_ON:
ret = gpio_pin_set(data->sck_gpio, hx711_config.sck_pin, data->power);
hx711_sample_fetch(dev, HX711_SENSOR_CHAN_WEIGHT);
return ret;
case HX711_POWER_OFF:
ret = gpio_pin_set(data->sck_gpio, hx711_config.sck_pin, data->power);
return ret;
default:
return -ENOTSUP;
}
}

#ifdef CONFIG_PM_DEVICE
int hx711_pm_ctrl(const struct device *dev, enum pm_device_action action)
{
int ret = 0;

switch (action) {
case PM_DEVICE_ACTION_RESUME:
ret = avia_hx711_power(dev, HX711_POWER_ON);
break;
case PM_DEVICE_ACTION_TURN_OFF:
ret = avia_hx711_power(dev, HX711_POWER_OFF);
break;
default:
return -ENOTSUP;
}

return ret;
}
#endif /* CONFIG_PM_DEVICE */

static const struct sensor_driver_api hx711_api = {
.sample_fetch = hx711_sample_fetch,
.channel_get = hx711_channel_get,
.attr_set = hx711_attr_set,
};

PM_DEVICE_DT_DEFINE(DT_DRV_INST(0), hx711_pm_ctrl);
DEVICE_DT_INST_DEFINE(0, hx711_init, PM_DEVICE_DT_GET(DT_DRV_INST(0)), &hx711_data, &hx711_config,
POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &hx711_api);

The values i'm getting are pretty random, i don't understand why. And when the avia_hx711_calibrate() in uncommented this error appears:

os: ***** BUS FAULT *****
[00:00:13.475,433] os: Precise data bus error
[00:00:13.475,433] os: BFAR Address: 0xf0cead3
[00:00:13.475,463] os: r0/a1: 0x00000834 r1/a2: 0x0000003a r2/a3: 0x0000000a
[00:00:13.475,463] os: r3/a4: 0x20000258 r12/ip: 0x00000313 r14/lr: 0x00000deb
[00:00:13.475,494] os: xpsr: 0x21000000
[00:00:13.475,494] os: Faulting instruction address (r15/pc): 0x00004540
[00:00:13.475,555] os: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0
[00:00:13.475,585] os: Current thread: 0x200007b8 (unknown)
[00:00:13.590,545] fatal_error: Resetting system

I really hope you can help me.

Related