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