From 86698613122403962f406552b41a42a4bdbd71ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=81yszczek?= Date: Tue, 27 Feb 2024 16:39:24 +0100 Subject: [PATCH] examples/hx711: add new program to test hx711 chip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Łyszczek --- examples/hx711/CMakeLists.txt | 31 +++ examples/hx711/Kconfig | 32 +++ examples/hx711/Make.defs | 23 +++ examples/hx711/Makefile | 34 ++++ examples/hx711/hx711_main.c | 361 ++++++++++++++++++++++++++++++++++ 5 files changed, 481 insertions(+) create mode 100644 examples/hx711/CMakeLists.txt create mode 100644 examples/hx711/Kconfig create mode 100644 examples/hx711/Make.defs create mode 100644 examples/hx711/Makefile create mode 100644 examples/hx711/hx711_main.c diff --git a/examples/hx711/CMakeLists.txt b/examples/hx711/CMakeLists.txt new file mode 100644 index 000000000..aabe90ef6 --- /dev/null +++ b/examples/hx711/CMakeLists.txt @@ -0,0 +1,31 @@ +# ############################################################################## +# apps/examples/hx711/CMakeLists.txt +# +# Licensed to the Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. The ASF licenses this +# file to you under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# +# ############################################################################## + +if(CONFIG_EXAMPLES_HX711) + nuttx_add_application( + NAME + ${CONFIG_EXAMPLES_HX711_PROGNAME} + SRCS + hx711_main.c + STACKSIZE + ${CONFIG_EXAMPLES_HX711_STACKSIZE} + PRIORITY + ${CONFIG_EXAMPLES_HX711_PRIORITY}) +endif() diff --git a/examples/hx711/Kconfig b/examples/hx711/Kconfig new file mode 100644 index 000000000..f68a26d12 --- /dev/null +++ b/examples/hx711/Kconfig @@ -0,0 +1,32 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config EXAMPLES_HX711 + tristate "HX711 driver example" + default n + select ADC_HX711 + ---help--- + Enable the HX711 example. This program is also useful during + development as it's possible to manipulate and dump hx711 + settings, as well as print conversions to terminal. + +if EXAMPLES_HX711 + +config EXAMPLES_HX711_PROGNAME + string "Program name" + default "hx711" + ---help--- + This is the name of the program that will be used when the NSH ELF + program is installed. + +config EXAMPLES_HX711_PRIORITY + int "hx711 task priority" + default 100 + +config EXAMPLES_HX711_STACKSIZE + int "hx711 stack size" + default DEFAULT_TASK_STACKSIZE + +endif diff --git a/examples/hx711/Make.defs b/examples/hx711/Make.defs new file mode 100644 index 000000000..7cffdda6f --- /dev/null +++ b/examples/hx711/Make.defs @@ -0,0 +1,23 @@ +############################################################################ +# apps/examples/hx711/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +ifneq ($(CONFIG_EXAMPLES_HX711),) +CONFIGURED_APPS += $(APPDIR)/examples/hx711 +endif diff --git a/examples/hx711/Makefile b/examples/hx711/Makefile new file mode 100644 index 000000000..4d2a84619 --- /dev/null +++ b/examples/hx711/Makefile @@ -0,0 +1,34 @@ +############################################################################ +# apps/examples/hx711/Makefile +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(APPDIR)/Make.defs + +# hx711 built-in application info + +PROGNAME = $(CONFIG_EXAMPLES_HX711_PROGNAME) +PRIORITY = $(CONFIG_EXAMPLES_HX711_PRIORITY) +STACKSIZE = $(CONFIG_EXAMPLES_HX711_STACKSIZE) +MODULE = $(CONFIG_EXAMPLES_HX711) + +# hx711 example + +MAINSRC = hx711_main.c + +include $(APPDIR)/Application.mk diff --git a/examples/hx711/hx711_main.c b/examples/hx711/hx711_main.c new file mode 100644 index 000000000..fc7117469 --- /dev/null +++ b/examples/hx711/hx711_main.c @@ -0,0 +1,361 @@ +/**************************************************************************** + * apps/examples/hx711/hx711_main.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct hx711_config +{ + char dev[32]; + char dump; + char channel; + unsigned char gain; + unsigned average; + unsigned loops; + float precision; + int val_per_unit; + int sign; +} g_hx711_config; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: hx711_print_help + * + * Description: + * Prints help onto stdout. + * + ****************************************************************************/ + +static void hx711_print_help(const char *progname) +{ + printf("usage: %s [-d ] [options]\n" + "\n" + "\t-h print this help message\n" + "\t-d path to hx711 device, default: /dev/hx711_0\n" + "\t-t tares the scale with specified precision, might" + "take few seconds to complete.\n" + "\t If you set value per unit, precision is in units, " + "otherwise it's raw values.\n" + "\t If units are used, float can be passed like 0.1\n" + "\t-v value read that coresponds to one unit. This value " + "has to be\n" + "\t calibrated first before it's known\n" + "\t-s reverse sign, if values decreses when mass increases, " + "pass this\n" + "\t-D dumps current device settings (like, average, channel, " + "gain etc.)\n" + "\t-a set how many samples should be averaged before " + "returning value,\n" + "\t values [1..%d] are valid\n" + "\t-c set channel to read (either 'a' or 'b' is valid)\n" + "\t-g set adc gain, for channel 'a' 64 and 128 are valid,\n" + "\t for channel 'b', only 64 is valid\n" + "\t-r read this number of samples before exiting, samples " + "will be printed\n" + "\t on stdout as string, one sample per line\n" + "\n" + "Check documentation for full description\n", + progname, HX711_MAX_AVG_SAMPLES); +} + +/**************************************************************************** + * Name: hx711_parse_args + * + * Description: + * Parses command line arguments + * + ****************************************************************************/ + +static int hx711_parse_args(int argc, FAR char *argv[]) +{ + int opt; + + memset(&g_hx711_config, 0x00, sizeof(g_hx711_config)); + + while ((opt = getopt(argc, argv, "hd:Dt:a:c:g:r:v:s")) != -1) + { + switch (opt) + { + case 'h': + hx711_print_help(argv[0]); + return 1; + + case 'd': + strcpy(g_hx711_config.dev, optarg); + break; + + case 't': + g_hx711_config.precision = atof(optarg); + break; + + case 'D': + g_hx711_config.dump = 1; + break; + + case 'a': + g_hx711_config.average = atoi(optarg); + break; + + case 'c': + g_hx711_config.channel = optarg[0]; + break; + + case 'g': + g_hx711_config.gain = atoi(optarg); + break; + + case 'r': + g_hx711_config.loops = atoi(optarg); + break; + + case 's': + g_hx711_config.sign = -1; + break; + + case 'v': + g_hx711_config.val_per_unit = atoi(optarg); + break; + + default: + fprintf(stderr, "Invalid option, run with -h for help\n"); + return 1; + } + } + + if (g_hx711_config.dev[0] == '\0') + { + strcpy(g_hx711_config.dev, "/dev/hx711_0"); + } + + return 0; +} + +/**************************************************************************** + * Name: hx711_set_options + * + * Description: + * Set hx711 options if they were specified on command line + * + * Input Parameters: + * fd - opened hx711 instance + * + ****************************************************************************/ + +int hx711_set_options(int fd) +{ + int ret; + + /* Set channel to read */ + + if (g_hx711_config.channel > 0) + { + if ((ret = ioctl(fd, HX711_SET_CHANNEL, g_hx711_config.channel))) + { + fprintf(stderr, "Failed to set channel to %c, error: %s\n", + g_hx711_config.channel, strerror(errno)); + return -1; + } + } + + /* Set channel ADC gain */ + + if (g_hx711_config.gain > 0) + { + if ((ret = ioctl(fd, HX711_SET_GAIN, g_hx711_config.gain))) + { + fprintf(stderr, "Failed to set gain to %d, error: %s\n", + g_hx711_config.gain, strerror(errno)); + return -1; + } + } + + /* Set how many samples to average before printing value */ + + if (g_hx711_config.average > 0) + { + if ((ret = ioctl(fd, HX711_SET_AVERAGE, g_hx711_config.average))) + { + fprintf(stderr, "Failed to set average to %d, error: %s\n", + g_hx711_config.average, strerror(errno)); + return -1; + } + } + + /* Set if sign should be reversed or not */ + + if (g_hx711_config.sign) + { + if ((ret = ioctl(fd, HX711_SET_SIGN, &g_hx711_config.sign))) + { + fprintf(stderr, "Failed to set sign to %d, error: %s\n", + g_hx711_config.sign, strerror(errno)); + return -1; + } + } + + /* Set what value coresponds to 1 unit */ + + if (g_hx711_config.val_per_unit > 0) + { + if ((ret = ioctl(fd, HX711_SET_VAL_PER_UNIT, + g_hx711_config.val_per_unit))) + { + fprintf(stderr, "Failed to set val per unit to %d, error: %s\n", + g_hx711_config.val_per_unit, strerror(errno)); + return -1; + } + } + + return 0; +} + +/**************************************************************************** + * Name: hx711_dump_options + * + * Description: + * Reads current hx711 settings from kernel driver and dumps them on stdout + * + ****************************************************************************/ + +static void hx711_dump_options(int fd) +{ + unsigned average; + unsigned char gain; + char channel; + unsigned val_per_unit; + + ioctl(fd, HX711_GET_GAIN, &gain); + ioctl(fd, HX711_GET_CHANNEL, &channel); + ioctl(fd, HX711_GET_AVERAGE, &average); + ioctl(fd, HX711_GET_VAL_PER_UNIT, &val_per_unit); + + printf("Current settings for: %s\n", g_hx711_config.dev); + printf("average.............: %u\n", average); + printf("channel.............: %c\n", channel); + printf("gain................: %d\n", gain); + printf("value per unit......: %u\n", val_per_unit); +} + +/**************************************************************************** + * Name: hx711_read_and_dump + * + * Description: + * Reads configured number of samples, and dumps them to terminal. + * + ****************************************************************************/ + +static int hx711_read_and_dump(int fd) +{ + int32_t sample; + + while (g_hx711_config.loops--) + { + if (read(fd, &sample, sizeof(sample)) != sizeof(sample)) + { + fprintf(stderr, "Error reading from %s, error %s\n", + g_hx711_config.dev, strerror(errno)); + return -1; + } + + printf("%"PRId32"\n", sample); + } + + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * hx711 + ****************************************************************************/ + +int main(int argc, FAR char *argv[]) +{ + int fd; + + if (hx711_parse_args(argc, argv)) + { + return 1; + } + + fd = open(g_hx711_config.dev, O_RDONLY); + if (fd < 0) + { + fprintf(stderr, "Failed to open %s, error: %s\n", g_hx711_config.dev, + strerror(errno)); + return 1; + } + + if (hx711_set_options(fd)) + { + close(fd); + return 1; + } + + if (g_hx711_config.precision) + { + ioctl(fd, HX711_GET_VAL_PER_UNIT, &g_hx711_config.val_per_unit); + + if (g_hx711_config.val_per_unit) + { + printf("Taring with %fg precision\n", g_hx711_config.precision); + } + + if (ioctl(fd, HX711_TARE, &g_hx711_config.precision)) + { + perror("Failed to tare the scale"); + close(fd); + return 1; + } + } + + if (g_hx711_config.dump) + { + hx711_dump_options(fd); + } + + if (g_hx711_config.loops) + { + hx711_read_and_dump(fd); + } + + close(fd); + return 0; +}