New file |
| | |
| | | /********************************************************************************* |
| | | * Copyright: (C) 2024 LingYun IoT System Studio |
| | | * All rights reserved. |
| | | * |
| | | * Filename: infrared.h |
| | | * Description: This file is HC-SR501 infrared sensor code |
| | | * |
| | | * Pin connection: |
| | | * HC-SR501 Module IGKBoard-IMX6ULL |
| | | * VCC <-----> 5V |
| | | * I/O <-----> #Pin22(GPIO3_IO23) |
| | | * GND <-----> GND |
| | | * |
| | | ********************************************************************************/ |
| | | #include <stdio.h> |
| | | #include <stdlib.h> |
| | | #include <unistd.h> |
| | | #include <fcntl.h> |
| | | #include <dirent.h> |
| | | #include <string.h> |
| | | #include <time.h> |
| | | #include <errno.h> |
| | | #include <signal.h> |
| | | #include <getopt.h> |
| | | #include <libgen.h> |
| | | |
| | | #include "infrared.h" |
| | | |
| | | int g_stop = 0; |
| | | |
| | | static inline void msleep(unsigned long ms); |
| | | void sig_handler(int signum); |
| | | |
| | | static void program_usage(const char *progname) |
| | | { |
| | | printf("Usage: %s [OPTION]...\n", progname); |
| | | printf(" This is infrared detect program. \n"); |
| | | |
| | | printf(" -d[device ] Specify infrared device, such as 0\n"); |
| | | printf(" -h[help ] Display this help information\n"); |
| | | |
| | | printf("\n"); |
| | | printf("%s program Version v1.0.0\n", progname); |
| | | printf("Copyright (C) 2023 LingYun IoT System Studio.\n"); |
| | | |
| | | return; |
| | | } |
| | | |
| | | int main(int argc, char **argv) |
| | | { |
| | | char *progname=NULL; |
| | | int rv; |
| | | int which = -1; |
| | | |
| | | struct option long_options[] = { |
| | | {"device", required_argument, NULL, 'd'}, |
| | | {"help", no_argument, NULL, 'h'}, |
| | | {NULL, 0, NULL, 0} |
| | | }; |
| | | |
| | | progname = basename(argv[0]); |
| | | |
| | | /* Parser the command line parameters */ |
| | | while ((rv = getopt_long(argc, argv, "d:h", long_options, NULL)) != -1) |
| | | { |
| | | switch (rv) |
| | | { |
| | | case 'd': /* Set infrared number, such as 0...max */ |
| | | which = atoi(optarg); |
| | | break; |
| | | |
| | | |
| | | case 'h': /* Get help information */ |
| | | program_usage(progname); |
| | | return 0; |
| | | |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if( (rv=init_infrared()) < 0 ) |
| | | { |
| | | printf("initial infrared gpio failure, rv=%d\n", rv); |
| | | return 1; |
| | | } |
| | | |
| | | signal(SIGINT, sig_handler); |
| | | signal(SIGTERM, sig_handler); |
| | | |
| | | while( !g_stop ) |
| | | { |
| | | rv = detect_infrared(which); |
| | | printf("Infrared[%d] monitor: %s\n", which, rv ? "Someone is closing!":"No one nearby!"); |
| | | sleep(1); |
| | | } |
| | | |
| | | term_infrared(); |
| | | return 0; |
| | | } |
| | | |
| | | /*+-------------------------------------+ |
| | | *| Infrared API based on libgpiod v2.0 | |
| | | *+-------------------------------------+*/ |
| | | |
| | | static infrared_t ir_info[IR_CNT] = |
| | | { |
| | | {"IR1", 2, 23, IR_ACTIVE_HIGH, NULL}, /* #Pin22, GPIO3_IO23 on chip2 line 23, active high */ |
| | | }; |
| | | |
| | | /* infrareds context */ |
| | | static infrareds_t infrareds = |
| | | { |
| | | .infrareds = ir_info, |
| | | .count = IR_CNT, |
| | | }; |
| | | |
| | | int init_infrared(void) |
| | | { |
| | | infrared_t *infrared; |
| | | int i, rv = 0; |
| | | char chip_dev[32]; |
| | | struct gpiod_chip *chip; /* gpio chip */ |
| | | struct gpiod_line_settings *settings; /* gpio direction, bias, active_low, value */ |
| | | struct gpiod_line_config *line_cfg; /* gpio line */ |
| | | struct gpiod_request_config *req_cfg; /* gpio consumer, it can be NULL */ |
| | | |
| | | /* defined in libgpiod-2.0/lib/line-settings.c: |
| | | |
| | | struct gpiod_line_settings { |
| | | enum gpiod_line_direction direction; |
| | | enum gpiod_line_edge edge_detection; |
| | | enum gpiod_line_drive drive; |
| | | enum gpiod_line_bias bias; |
| | | bool active_low; |
| | | enum gpiod_line_clock event_clock; |
| | | long debounce_period_us; |
| | | enum gpiod_line_value output_value; |
| | | }; |
| | | */ |
| | | settings = gpiod_line_settings_new(); |
| | | if (!settings) |
| | | { |
| | | printf("unable to allocate line settings\n"); |
| | | rv = -2; |
| | | goto cleanup; |
| | | } |
| | | |
| | | /* defined in libgpiod-2.0/lib/line-config.c |
| | | |
| | | struct gpiod_line_config { |
| | | struct per_line_config line_configs[LINES_MAX]; |
| | | size_t num_configs; |
| | | enum gpiod_line_value output_values[LINES_MAX]; |
| | | size_t num_output_values; |
| | | struct settings_node *sref_list; |
| | | }; |
| | | */ |
| | | |
| | | line_cfg = gpiod_line_config_new(); |
| | | if (!line_cfg) |
| | | { |
| | | printf("unable to allocate the line config structure"); |
| | | rv = -2; |
| | | goto cleanup; |
| | | } |
| | | |
| | | |
| | | /* defined in libgpiod-2.0/lib/request-config.c: |
| | | |
| | | struct gpiod_request_config { |
| | | char consumer[GPIO_MAX_NAME_SIZE]; |
| | | size_t event_buffer_size; |
| | | }; |
| | | */ |
| | | req_cfg = gpiod_request_config_new(); |
| | | if (!req_cfg) |
| | | { |
| | | printf("unable to allocate the request config structure"); |
| | | rv = -2; |
| | | goto cleanup; |
| | | } |
| | | |
| | | for(i=0; i<infrareds.count; i++) |
| | | { |
| | | infrared = &infrareds.infrareds[i]; |
| | | |
| | | snprintf(chip_dev, sizeof(chip_dev), "/dev/gpiochip%d", infrared->chip_num); |
| | | chip = gpiod_chip_open(chip_dev); |
| | | if( !chip ) |
| | | { |
| | | printf("open gpiochip failure, maybe you need running as root\n"); |
| | | rv = -3; |
| | | goto cleanup; |
| | | } |
| | | |
| | | /* Set as input direction */ |
| | | gpiod_line_settings_reset(settings); |
| | | gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_INPUT); |
| | | |
| | | /* set gpio line */ |
| | | gpiod_line_config_reset(line_cfg); |
| | | gpiod_line_config_add_line_settings(line_cfg, &infrared->gpio_num, 1, settings); |
| | | |
| | | /* Can be NULL for default settings. */ |
| | | gpiod_request_config_set_consumer(req_cfg, infrared->name); |
| | | |
| | | /* Request a set of lines for exclusive usage. */ |
| | | infrared->request = gpiod_chip_request_lines(chip, req_cfg, line_cfg); |
| | | |
| | | gpiod_chip_close(chip); |
| | | //printf("request %5s infrared[%d] for gpio output okay\n", infrared->name, infrared->gpio); |
| | | } |
| | | |
| | | cleanup: |
| | | |
| | | if( rv< 0 ) |
| | | term_infrared(); |
| | | |
| | | if( line_cfg ) |
| | | gpiod_line_config_free(line_cfg); |
| | | |
| | | if( req_cfg ) |
| | | gpiod_request_config_free(req_cfg); |
| | | |
| | | if( settings ) |
| | | gpiod_line_settings_free(settings); |
| | | |
| | | return rv; |
| | | } |
| | | |
| | | int term_infrared(void) |
| | | { |
| | | infrared_t *infrared; |
| | | int i; |
| | | |
| | | printf("terminate infrared gpios\n"); |
| | | |
| | | for(i=0; i<infrareds.count; i++) |
| | | { |
| | | infrared = &infrareds.infrareds[i]; |
| | | |
| | | if( infrared->request ) |
| | | { |
| | | gpiod_line_request_release(infrared->request); |
| | | } |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int detect_infrared(int which) |
| | | { |
| | | int rv = 0; |
| | | infrared_t *infrared; |
| | | |
| | | if( which<0 || which>=infrareds.count ) |
| | | { |
| | | printf("Invalid input arguments\n"); |
| | | return 0; |
| | | } |
| | | |
| | | infrared = &infrareds.infrareds[which]; |
| | | |
| | | return gpiod_line_request_get_value(infrared->request, infrared->gpio_num)==infrared->active ? 1 : 0; |
| | | } |
| | | |
| | | /*+-------------------------------+ |
| | | *| Misc functions API | |
| | | *+-------------------------------+*/ |
| | | |
| | | static inline void msleep(unsigned long ms) |
| | | { |
| | | struct timespec cSleep; |
| | | unsigned long ulTmp; |
| | | |
| | | cSleep.tv_sec = ms / 1000; |
| | | if (cSleep.tv_sec == 0) |
| | | { |
| | | ulTmp = ms * 10000; |
| | | cSleep.tv_nsec = ulTmp * 100; |
| | | } |
| | | else |
| | | { |
| | | cSleep.tv_nsec = 0; |
| | | } |
| | | |
| | | nanosleep(&cSleep, 0); |
| | | |
| | | return ; |
| | | } |
| | | |
| | | void sig_handler(int signum) |
| | | { |
| | | switch( signum ) |
| | | { |
| | | case SIGINT: |
| | | case SIGTERM: |
| | | g_stop = 1; |
| | | |
| | | default: |
| | | break; |
| | | } |
| | | |
| | | return ; |
| | | } |
| | | |