/********************************************************************************* * Copyright: (C) 2021 LingYun IoT System Studio * All rights reserved. * * Filename: relay.c * Description: This file is used to control Relay * * * Pin connection: * Relay Module Raspberry Pi Board * VCC <-----> 5V * I <-----> #Pin16(BCM GPIO23) * GND <-----> GND * * System install: * sudo apt install -y libgpiod-dev gpiod * * ********************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #define DELAY 500 #define ON 1 #define OFF 0 /* relay code */ enum { RELAY1 = 0, RELAY_CNT, }; /* Relay hardware information */ typedef struct relay_info_s { const char *name; /* Relay name */ int gpio; /* Relay BCM pin number */ int active;/* Relay active GPIO level: 0->low 1->high */ struct gpiod_line *line; /* libgpiod line */ } relay_info_t; static relay_info_t relay_info[RELAY_CNT] = { {"relay1", 23, 1, NULL }, }; /* Relay API context */ typedef struct relay_ctx_s { struct gpiod_chip *chip; relay_info_t *relay; int count; } relay_ctx_t; int init_relay(relay_ctx_t *ctx); int term_relay(relay_ctx_t *ctx); int turn_relay(relay_ctx_t *ctx, int which, int cmd); 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 relay control program. \n"); printf(" -d[device ] Specify relay device, such as 0\n"); printf(" -s[status ] Specify relay status, 0 for open, 1 for close\n"); printf(" -h[help ] Display this help information\n"); printf(" -v[version ] Display the program version\n"); printf("\n"); banner(progname); return; } int main(int argc, char **argv) { int rv; char *progname=NULL; int which = -1; int status = ON; relay_ctx_t relay_ctx = { .chip = NULL, .relay = relay_info, .count = RELAY_CNT, }; struct option long_options[] = { {"device", required_argument, NULL, 'd'}, {"status", required_argument, NULL, 's'}, {"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, "d:s:vh", long_options, NULL)) != -1) { switch (rv) { case 'd': /* Set relay number, such as 0...max */ which = atoi(optarg); break; case 's': /* Set relay status, 0 for open and 1 for close */ status = atoi(optarg); break; case 'v': /* Get software version */ banner(progname); return EXIT_SUCCESS; case 'h': /* Get help information */ program_usage(progname); return 0; default: break; } } if( which<0 || which>=relay_ctx.count ) { printf("ERROR: Invalid relay index [%d], max=%d\n", which, relay_ctx.count-1); return 0; } if( (rv=init_relay(&relay_ctx)) < 0 ) { printf("initial relay gpio failure, rv=%d\n", rv); return 1; } turn_relay(&relay_ctx, which, status); term_relay(&relay_ctx); return 0; } int term_relay(relay_ctx_t *ctx) { int i; relay_info_t *relay; if( !ctx ) { printf("Invalid input arguments\n"); return -1; } if( !ctx->chip ) return 0; for(i=0; icount; i++) { relay = &ctx->relay[i]; if( relay->line ) gpiod_line_release(relay->line); } gpiod_chip_close(ctx->chip); return 0; } int init_relay(relay_ctx_t *ctx) { int i, rv; relay_info_t *relay; 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; icount; i++) { relay = &ctx->relay[i]; relay->line = gpiod_chip_get_line(ctx->chip, relay->gpio); if( !relay->line ) { printf("open gpioline for %s[%d] failed\n", relay->name, relay->gpio); rv = -3; goto failed; } rv = gpiod_line_request_output(relay->line, relay->name, !relay->active); if( rv ) { printf("request gpio output for %5s[%d] failed\n", relay->name, relay->gpio); rv = -4; goto failed; } //printf("request %s[%d] for gpio output okay\n", relay->name, relay->gpio); } return 0; failed: term_relay(ctx); return rv; } int turn_relay(relay_ctx_t *ctx, int which, int cmd) { int rv = 0; relay_info_t *relay; if( !ctx || which<0 || which>=ctx->count ) { printf("Invalid input arguments\n"); return -1; } relay = &ctx->relay[which]; if( OFF == cmd ) { gpiod_line_set_value(relay->line, !relay->active); } else { gpiod_line_set_value(relay->line, relay->active); } return 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 ; }