RaspberrPi project source code
Guo Wenxue
2024-07-06 f67df94069569d193ee2cc8d70dd9747cc2574a4
commit | author | age
d6b4a7 1 /*********************************************************************************
G 2  *      Copyright:  (C) 2021 LingYun IoT System Studio
3  *                  All rights reserved.
4  *
5  *       Filename:  relay.c
6  *    Description:  This file is used to control Relay
7  *
8  *
9  * Pin connection:
10  *                 Relay Module           Raspberry Pi Board
11  *                  VCC       <----->      5V
12  *                   I        <----->      #Pin16(BCM GPIO23)
13  *                  GND       <----->      GND
14  *
15  * System install:
16  *                  sudo apt install -y libgpiod-dev gpiod
17  *
18  *
19  ********************************************************************************/
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <dirent.h>
26 #include <string.h>
27 #include <time.h>
28 #include <errno.h>
29 #include <signal.h>
30 #include <getopt.h>
31 #include <libgen.h>
32
33 #include <gpiod.h>
34
35 #define DELAY     500
36
37 #define ON        1
38 #define OFF       0
39
40 /* relay code */
41 enum
42 {
43     RELAY1 = 0,
44     RELAY_CNT,
45 };
46
47 /* Relay hardware information */
48 typedef struct relay_info_s
49 {
50     const char         *name;  /* Relay name  */
51     int                 gpio;  /* Relay BCM pin number */
52     int                 active;/* Relay active GPIO level: 0->low 1->high */
53     struct gpiod_line  *line;  /* libgpiod line */
54 } relay_info_t;
55
56 static relay_info_t    relay_info[RELAY_CNT] =
57 {
58     {"relay1",  23, 1, NULL },
59 };
60
61 /* Relay API context */
62 typedef struct relay_ctx_s
63 {
64     struct gpiod_chip   *chip;
65     relay_info_t        *relay;
66     int                  count;
67 } relay_ctx_t;
68
69 int init_relay(relay_ctx_t *ctx);
70 int term_relay(relay_ctx_t *ctx);
71 int turn_relay(relay_ctx_t *ctx, int which, int cmd);
72 static inline void msleep(unsigned long ms);
73
74 static inline void banner(const char *progname)
75 {
76     printf("%s program Version v1.0.0\n", progname);
77     printf("Copyright (C) 2023 LingYun IoT System Studio.\n");
78 }
79
80 static void program_usage(const char *progname)
81 {
82
83     printf("Usage: %s [OPTION]...\n", progname);
84     printf(" This is relay control program. \n");
85
86     printf(" -d[device  ]  Specify relay device, such as 0\n");
87     printf(" -s[status  ]  Specify relay status, 0 for open, 1 for close\n");
88     printf(" -h[help    ]  Display this help information\n");
89     printf(" -v[version ]  Display the program version\n");
90
91     printf("\n");
92     banner(progname);
93     return;
94 }
95
96 int main(int argc, char **argv)
97 {
98     int             rv;
99     char           *progname=NULL;
100     int             which = -1;
101     int             status = ON;
102
103     relay_ctx_t     relay_ctx =
104     {
105         .chip  = NULL,
106         .relay  = relay_info,
107         .count = RELAY_CNT,
108     };
109
110     struct option long_options[] = {
111         {"device", required_argument, NULL, 'd'},
112         {"status", required_argument, NULL, 's'},
113         {"version", no_argument, NULL, 'v'},
114         {"help", no_argument, NULL, 'h'},
115         {NULL, 0, NULL, 0}
116     };
117
118
119     progname = basename(argv[0]);
120
121     /* Parser the command line parameters */
122     while ((rv = getopt_long(argc, argv, "d:s:vh", long_options, NULL)) != -1)
123     {
124         switch (rv)
125         {
126             case 'd': /*  Set relay number, such as 0...max */
127                 which = atoi(optarg);
128                 break;
129
130             case 's': /*  Set relay status, 0 for open and 1 for close */
131                 status = atoi(optarg);
132                 break;
133
134             case 'v':  /* Get software version */
135                 banner(progname);
136                 return EXIT_SUCCESS;
137
138             case 'h':  /* Get help information */
139                 program_usage(progname);
140                 return 0;
141
142             default:
143                 break;
144         }
145     }
146
147     if( which<0 || which>=relay_ctx.count )
148     {
149         printf("ERROR: Invalid relay index [%d], max=%d\n", which, relay_ctx.count-1);
150         return 0;
151     }
152
153
154     if( (rv=init_relay(&relay_ctx)) < 0 )
155     {
156         printf("initial relay gpio failure, rv=%d\n", rv);
157         return 1;
158     }
159
160     turn_relay(&relay_ctx, which, status);
161
162     term_relay(&relay_ctx);
163     return 0;
164 }
165
166 int term_relay(relay_ctx_t *ctx)
167 {
168     int            i;
169     relay_info_t  *relay;
170
171     if( !ctx )
172     {
173         printf("Invalid input arguments\n");
174         return -1;
175     }
176
177     if( !ctx->chip )
178         return 0;
179
180     for(i=0; i<ctx->count; i++)
181     {
182         relay = &ctx->relay[i];
183
184         if( relay->line )
185             gpiod_line_release(relay->line);
186     }
187
188     gpiod_chip_close(ctx->chip);
189     return 0;
190 }
191
192
193 int init_relay(relay_ctx_t *ctx)
194 {
195     int            i, rv;
196     relay_info_t  *relay;
197
198     if( !ctx )
199     {
200         printf("Invalid input arguments\n");
201         return -1;
202     }
203
204     ctx->chip = gpiod_chip_open_by_name("gpiochip0");
205     if( !ctx->chip )
206     {
207         printf("open gpiochip failure, maybe you need running as root\n");
208         return -2;
209     }
210
211
212     for(i=0; i<ctx->count; i++)
213     {
214         relay = &ctx->relay[i];
215
216         relay->line = gpiod_chip_get_line(ctx->chip, relay->gpio);
217         if( !relay->line )
218         {
219             printf("open gpioline for %s[%d] failed\n", relay->name, relay->gpio);
220             rv = -3;
221             goto failed;
222         }
223
224         rv  = gpiod_line_request_output(relay->line, relay->name, !relay->active);
225         if( rv )
226         {
227             printf("request gpio output for %5s[%d] failed\n", relay->name, relay->gpio);
228             rv = -4;
229             goto failed;
230         }
231
232         //printf("request %s[%d] for gpio output okay\n", relay->name, relay->gpio);
233     }
234
235     return 0;
236
237 failed:
238     term_relay(ctx);
239     return rv;
240 }
241
242 int turn_relay(relay_ctx_t *ctx, int which, int cmd)
243 {
244     int            rv = 0;
245     relay_info_t  *relay;
246
247     if( !ctx || which<0 || which>=ctx->count )
248     {
249         printf("Invalid input arguments\n");
250         return -1;
251     }
252
253     relay = &ctx->relay[which];
254
255     if( OFF == cmd )
256     {
257         gpiod_line_set_value(relay->line, !relay->active);
258     }
259     else
260     {
261         gpiod_line_set_value(relay->line, relay->active);
262     }
263
264     return 0;
265 }
266
267 static inline void msleep(unsigned long ms)
268 {
269     struct timespec cSleep;
270     unsigned long ulTmp;
271
272     cSleep.tv_sec = ms / 1000;
273     if (cSleep.tv_sec == 0)
274     {
275         ulTmp = ms * 10000;
276         cSleep.tv_nsec = ulTmp * 100;
277     }
278     else
279     {
280         cSleep.tv_nsec = 0;
281     }
282
283     nanosleep(&cSleep, 0);
284
285     return ;
286 }