8669861312
Signed-off-by: Michał Łyszczek <michal.lyszczek@bofc.pl>
362 lines
9.8 KiB
C
362 lines
9.8 KiB
C
/****************************************************************************
|
|
* 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 <nuttx/config.h>
|
|
#include <nuttx/analog/hx711.h>
|
|
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <sys/ioctl.h>
|
|
|
|
/****************************************************************************
|
|
* 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 <device>] [options]\n"
|
|
"\n"
|
|
"\t-h print this help message\n"
|
|
"\t-d<path> path to hx711 device, default: /dev/hx711_0\n"
|
|
"\t-t<prec> 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<val> 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<avg> set how many samples should be averaged before "
|
|
"returning value,\n"
|
|
"\t values [1..%d] are valid\n"
|
|
"\t-c<chan> set channel to read (either 'a' or 'b' is valid)\n"
|
|
"\t-g<gain> set adc gain, for channel 'a' 64 and 128 are valid,\n"
|
|
"\t for channel 'b', only 64 is valid\n"
|
|
"\t-r<num> 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;
|
|
}
|