/*********************************************************************************
|
* Copyright: (C) 2023 LingYun IoT System Studio
|
* All rights reserved.
|
*
|
* Filename: led.c
|
* Description: This file is HC-SR501 infrared sensor code
|
*
|
*
|
* Pin connection:
|
* HC-SR501 Module Raspberry Pi Board
|
* VCC <-----> 5V
|
* I/O <-----> #Pin18(BCM GPIO24)
|
* GND <-----> GND
|
*
|
* System install:
|
* sudo apt install -y libgpiod-dev gpiod
|
*
|
*
|
********************************************************************************/
|
|
|
#include <stdio.h>
|
#include <unistd.h>
|
#include <errno.h>
|
#include <stdlib.h>
|
#include <string.h>
|
#include <signal.h>
|
#include <getopt.h>
|
#include <libgen.h>
|
|
#include <gpiod.h>
|
|
/* infrared code */
|
enum
|
{
|
IR1 = 0,
|
IR_CNT,
|
};
|
|
/* infrared hardware information */
|
typedef struct ir_info_s
|
{
|
const char *name; /* infrared name */
|
int gpio; /* infrared BCM pin number */
|
int active;/* infrared active GPIO level: 0->low 1->high */
|
struct gpiod_line *line; /* libgpiod line */
|
} ir_info_t;
|
|
static ir_info_t ir_info[IR_CNT] =
|
{
|
{"IR1", 23, 1, NULL },
|
};
|
|
/* infrared API context */
|
typedef struct ir_ctx_s
|
{
|
struct gpiod_chip *chip;
|
ir_info_t *ir;
|
int count;
|
} ir_ctx_t;
|
|
int init_infrared(ir_ctx_t *ctx);
|
int term_infrared(ir_ctx_t *ctx);
|
int detect_infrared(ir_ctx_t *ctx, int which);
|
static inline void msleep(unsigned long ms);
|
|
static inline void banner(const char *progname)
|
{
|
printf("%s program Version v1.0.0\n", progname);
|
printf("Copyright (C) 2023 LingYun IoT System Studio.\n");
|
}
|
|
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(" -v[version ] Display the program version\n");
|
|
printf("\n");
|
banner(progname);
|
return;
|
}
|
|
int g_stop = 0;
|
void sig_handler(int signum)
|
{
|
switch( signum )
|
{
|
case SIGINT:
|
case SIGTERM:
|
g_stop = 1;
|
|
default:
|
break;
|
}
|
|
return ;
|
}
|
|
int main(int argc, char **argv)
|
{
|
int i, rv;
|
char *progname=NULL;
|
|
ir_ctx_t ir_ctx =
|
{
|
.chip = NULL,
|
.ir = ir_info,
|
.count = IR_CNT,
|
};
|
|
struct option long_options[] = {
|
{"version", no_argument, NULL, 'v'},
|
{"help", no_argument, NULL, 'h'},
|
{NULL, 0, NULL, 0}
|
};
|
|
progname = basename(argv[0]);
|
|
/* Parser the command line parameters */
|
while ((rv = getopt_long(argc, argv, "vh", long_options, NULL)) != -1)
|
{
|
switch (rv)
|
{
|
case 'v': /* Get software version */
|
banner(progname);
|
return EXIT_SUCCESS;
|
|
case 'h': /* Get help information */
|
program_usage(progname);
|
return 0;
|
|
default:
|
break;
|
}
|
}
|
|
if( (rv=init_infrared(&ir_ctx)) < 0 )
|
{
|
printf("initial infrared gpio failure, rv=%d\n", rv);
|
return 1;
|
}
|
|
signal(SIGINT, sig_handler);
|
signal(SIGTERM, sig_handler);
|
|
while( !g_stop )
|
{
|
for( i=0; i<ir_ctx.count; i++ )
|
{
|
rv = detect_infrared(&ir_ctx, i);
|
printf("Infrared[%d] monitor: %s\n", i, rv ? "Someone is closing!":"No one nearby!");
|
}
|
sleep(1);
|
}
|
|
term_infrared(&ir_ctx);
|
return 0;
|
}
|
|
int term_infrared(ir_ctx_t *ctx)
|
{
|
int i;
|
ir_info_t *ir;
|
|
if( !ctx )
|
{
|
printf("Invalid input arguments\n");
|
return -1;
|
}
|
|
if( !ctx->chip )
|
return 0;
|
|
for(i=0; i<ctx->count; i++)
|
{
|
ir = &ctx->ir[i];
|
|
if( ir->line )
|
gpiod_line_release(ir->line);
|
}
|
|
gpiod_chip_close(ctx->chip);
|
return 0;
|
}
|
|
int init_infrared(ir_ctx_t *ctx)
|
{
|
int i, rv;
|
ir_info_t *ir;
|
|
if( !ctx )
|
{
|
printf("Invalid input arguments\n");
|
return -1;
|
}
|
|
ctx->chip = gpiod_chip_open_by_name("gpiochip0");
|
if( !ctx->chip )
|
{
|
printf("open gpiochip failure, maybe you need running as root\n");
|
return -2;
|
}
|
|
|
for(i=0; i<ctx->count; i++)
|
{
|
ir = &ctx->ir[i];
|
|
ir ->line = gpiod_chip_get_line(ctx->chip, ir->gpio);
|
if( !ir->line )
|
{
|
printf("open gpioline for %s[%d] failed\n", ir->name, ir->gpio);
|
rv = -3;
|
goto failed;
|
}
|
|
rv = gpiod_line_request_input(ir->line, ir->name);
|
if( rv )
|
{
|
printf("request gpio input for %s[%d] failed\n", ir->name, ir->gpio);
|
rv = -4;
|
goto failed;
|
}
|
}
|
|
return 0;
|
|
failed:
|
term_infrared(ctx);
|
return rv;
|
}
|
|
int detect_infrared(ir_ctx_t *ctx, int which)
|
{
|
int rv = 0;
|
ir_info_t *ir;
|
|
if( !ctx || which<0 || which>=ctx->count )
|
{
|
printf("Invalid input arguments\n");
|
return 0;
|
}
|
|
ir = &ctx->ir[which];
|
|
return gpiod_line_get_value(ir->line)==ir->active ? 1 : 0;
|
}
|
|
|
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 ;
|
}
|