/**************************************************************************** * 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; }