/********************************************************************************* * 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 #include #include #include #include #include #include #include #include #include #include #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; ichip_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; irequest ) { 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 ; }