From 5e7050e3c9ec8c1e35a80f9cdd1ab0c918f3e060 Mon Sep 17 00:00:00 2001 From: guowenxue <guowenxue@gmail.com> Date: Wed, 21 Aug 2024 16:32:06 +0800 Subject: [PATCH] Add relay source code --- hal/api/led.h | 6 hal/api/relay.c | 313 ++++++++++++++++++++++++++++++++++++++++++++ hal/api/relay.h | 70 ++++++++++ hal/api/led.c | 11 + 4 files changed, 393 insertions(+), 7 deletions(-) diff --git a/hal/api/leds.c b/hal/api/led.c similarity index 95% rename from hal/api/leds.c rename to hal/api/led.c index 5905885..16fe2f4 100644 --- a/hal/api/leds.c +++ b/hal/api/led.c @@ -24,7 +24,10 @@ #include <time.h> #include <errno.h> #include <signal.h> -#include "leds.h" +#include <getopt.h> +#include <libgen.h> + +#include "led.h" int g_stop = 0; @@ -71,9 +74,9 @@ static led_t leds_info[LEDCNT] = { - {"red", 0, 23, ACTIVE_HIGH, 0, NULL}, /* GPIO1_IO23 on chip0 line 23, active high */ - {"green", 4, 1, ACTIVE_HIGH, 0, NULL}, /* GPIO5_IO01 on chip4 line 1, active high */ - {"blue", 4, 8, ACTIVE_HIGH, 0, NULL}, /* GPIO5_IO08 on chip4 line 8, active high */ + {"red", 0, 23, ACTIVE_HIGH, 0, NULL}, /* #31, GPIO1_IO23 on chip0 line 23, active high */ + {"green", 4, 1, ACTIVE_HIGH, 0, NULL}, /* #33, GPIO5_IO01 on chip4 line 1, active high */ + {"blue", 4, 8, ACTIVE_HIGH, 0, NULL}, /* #35, GPIO5_IO08 on chip4 line 8, active high */ }; /* Leds context */ diff --git a/hal/api/leds.h b/hal/api/led.h similarity index 96% rename from hal/api/leds.h rename to hal/api/led.h index f8f827c..b486bcf 100644 --- a/hal/api/leds.h +++ b/hal/api/led.h @@ -2,7 +2,7 @@ * Copyright: (C) 2024 LingYun IoT System Studio * All rights reserved. * - * Filename: led.c + * Filename: led.h * Description: This file is used to control RGB 3-colors LED * * @@ -15,8 +15,8 @@ * ********************************************************************************/ -#ifndef _LEDS_H_ -#define _LEDS_H_ +#ifndef _LED_H_ +#define _LED_H_ #include "gpiod.h" diff --git a/hal/api/relay.c b/hal/api/relay.c new file mode 100644 index 0000000..93e45ff --- /dev/null +++ b/hal/api/relay.c @@ -0,0 +1,313 @@ +/********************************************************************************* + * Copyright: (C) 2024 LingYun IoT System Studio + * All rights reserved. + * + * Filename: relay.h + * Description: This file is used to control relay + * + * + * Pin connection: + * Relay Module IGKBoard-IMX6ULL + * VCC <-----> 5V + * I <-----> #Pin31 + * 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 "relay.h" + +static inline void msleep(unsigned long ms); + +static void program_usage(const char *progname) +{ + printf("Usage: %s [OPTION]...\n", progname); + printf(" This is relay control program. \n"); + + printf(" -r[relay ] 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("\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; + int status = ON; + + struct option long_options[] = { + {"relay", required_argument, NULL, 'r'}, + {"status", required_argument, NULL, 's'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + progname = basename(argv[0]); + + /* Parser the command line parameters */ + while ((rv = getopt_long(argc, argv, "r:s:h", long_options, NULL)) != -1) + { + switch (rv) + { + case 'r': /* 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 'h': /* Get help information */ + program_usage(progname); + return 0; + + default: + break; + } + } + + if( (rv=init_relay()) < 0 ) + { + printf("initial relays gpio failure, rv=%d\n", rv); + return 1; + } + + turn_relay(which, status); + + return 0; +} + + +/*+----------------------------------+ + *| Relay API based on libgpiod v2.0 | + *+----------------------------------+*/ + +static relay_t relays_info[RELAY_CNT] = +{ + {"relay1", 0, 22, ACTIVE_HIGH, 0, NULL}, /* #31, GPIO1_IO22 on chip0 line 22, active high */ +}; + +/* relays context */ +static relays_t relays = +{ + .relays = relays_info, + .count = RELAY_CNT, +}; + +int init_relay(void) +{ + relay_t *relay; + 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<relays.count; i++) + { + relay = &relays.relays[i]; + + snprintf(chip_dev, sizeof(chip_dev), "/dev/gpiochip%d", relay->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 output direction, active low and default level as inactive */ + gpiod_line_settings_reset(settings); + gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_OUTPUT); + gpiod_line_settings_set_active_low(settings, relay->active); + gpiod_line_settings_set_output_value(settings, GPIOD_LINE_VALUE_INACTIVE); + + /* set gpio line */ + gpiod_line_config_reset(line_cfg); + gpiod_line_config_add_line_settings(line_cfg, &relay->gpio_num, 1, settings); + + /* Can be NULL for default settings. */ + gpiod_request_config_set_consumer(req_cfg, relay->name); + + /* Request a set of lines for exclusive usage. */ + relay->request = gpiod_chip_request_lines(chip, req_cfg, line_cfg); + + gpiod_chip_close(chip); + //printf("request %5s relay[%d] for gpio output okay\n", relay->name, relay->gpio); + } + +cleanup: + + if( rv< 0 ) + term_relay(); + + 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_relay(void) +{ + int i; + relay_t *relay; + + printf("terminate relay gpios\n"); + + for(i=0; i<relays.count; i++) + { + relay = &relays.relays[i]; + + if( relay->request ) + { + turn_relay(i, OFF); + gpiod_line_request_release(relay->request); + } + } + + return 0; +} + +int turn_relay(int which, int cmd) +{ + relay_t *relay; + int rv = 0; + int value = 0; + + if( which<0 || which>=relays.count ) + { + printf("Invalid input arguments\n"); + return -1; + } + + relay = &relays.relays[which]; + + value = OFF==cmd ? GPIOD_LINE_VALUE_INACTIVE : GPIOD_LINE_VALUE_ACTIVE; + gpiod_line_request_set_value(relay->request, relay->gpio_num, value); + + relay->status = OFF==cmd ? OFF : ON; + + return 0; +} + +int toggle_relay(int which) +{ + relay_t *relay; + + if( which<0 || which>=relays.count ) + { + printf("Invalid input arguments\n"); + return -1; + } + + relay = &relays.relays[which]; + + return turn_relay(which, !relay->status); +} + +/*+-------------------------------+ + *| 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 ; +} + diff --git a/hal/api/relay.h b/hal/api/relay.h new file mode 100644 index 0000000..bbdd1bd --- /dev/null +++ b/hal/api/relay.h @@ -0,0 +1,70 @@ +/********************************************************************************* + * Copyright: (C) 2024 LingYun IoT System Studio + * All rights reserved. + * + * Filename: relay.h + * Description: This file is used to control relay + * + * + * Pin connection: + * Relay Module IGKBoard-IMX6ULL + * VCC <-----> 5V + * I <-----> #Pin31 + * GND <-----> GND + * + ********************************************************************************/ + +#ifndef _RELAY_H_ +#define _RELAY_H_ + +#include "gpiod.h" + +#define DELAY 300 + +#define ON 1 +#define OFF 0 + +/* relay number */ +enum +{ + RELAY1 = 0, + RELAY_CNT, +}; + +enum +{ + ACTIVE_HIGH, /* High level will turn relay on */ + ACTIVE_LOW, /* Low level will turn relay on */ +}; + +/* relay hardware information */ +typedef struct relay_s +{ + const char *name; /* relay name */ + int chip_num; /* relay connect chip */ + int gpio_num; /* relay connect line */ + int active; /* relay active level */ + int status; /* relay current status */ + struct gpiod_line_request *request; /* libgpiod gpio request handler */ +} relay_t; + +/* relay structure */ +typedef struct relays_s +{ + relay_t *relays;/* relay pointer to relays_info */ + int count; /* relay count */ +} relays_t; + +/* initial relays */ +int init_relay(void); + +/* terminate relays */ +int term_relay(void); + +/* turn $which relay ON/OFF */ +int turn_relay(int which, int cmd); + +/* toggle $which relay status */ +int toggle_relay(int which); + +#endif /* ----- #ifndef _relayS_H_ ----- */ -- Gitblit v1.9.1