Created
April 1, 2020 05:39
-
-
Save heiher/495ce007ab59e3036dc1449849f1995a to your computer and use it in GitHub Desktop.
外置硬盘盒电源开关伺服电机控制程序(NanoPi M4版)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
============================================================================ | |
Name : sg90.c | |
Author : Heiher <r@hev.cc> | |
Copyright : Copyright (c) 2020 everyone. | |
Description : SG90 Motor Controller | |
============================================================================ | |
*/ | |
#include <poll.h> | |
#include <errno.h> | |
#include <fcntl.h> | |
#include <stdio.h> | |
#include <sched.h> | |
#include <unistd.h> | |
#include <stdlib.h> | |
#include <sys/stat.h> | |
#include <sys/types.h> | |
#include <sys/mount.h> | |
static const char *led_prefix = "/sys/class/leds"; | |
static const char *gpio_prefix = "/sys/class/gpio"; | |
static int | |
set_scheduler_rt (void) | |
{ | |
struct sched_param sp = { .sched_priority = 1 }; | |
return sched_setscheduler (0, SCHED_RR, &sp); | |
} | |
static int | |
gpio_set_export (int gpio, int unexport) | |
{ | |
char path[256]; | |
char pin[16]; | |
int ret = -1; | |
int len; | |
int fd; | |
if (unexport) { | |
snprintf (path, sizeof (path), "%s/unexport", gpio_prefix); | |
} else { | |
snprintf (path, sizeof (path), "%s/export", gpio_prefix); | |
} | |
fd = open (path, O_WRONLY); | |
if (fd < 0) { | |
goto exit; | |
} | |
len = snprintf (pin, sizeof (pin), "%d", gpio); | |
ret = write (fd, pin, len); | |
if (ret <= 0) { | |
goto exit_close; | |
} | |
usleep (10 * 1000); | |
exit_close: | |
close (fd); | |
exit: | |
return ret; | |
} | |
static int | |
gpio_set_direction (int gpio, int direction) | |
{ | |
char path[256]; | |
int ret = -1; | |
int fd; | |
snprintf (path, sizeof (path), "%s/gpio%d/direction", gpio_prefix, gpio); | |
fd = open (path, O_WRONLY); | |
if (fd < 0) { | |
goto exit; | |
} | |
if (direction) { | |
ret = write (fd, "out", 3); | |
} else { | |
ret = write (fd, "in", 2); | |
} | |
close (fd); | |
exit: | |
return ret; | |
} | |
static int | |
gpio_set_edge (int gpio, int edge) | |
{ | |
char path[256]; | |
int ret = -1; | |
int fd; | |
snprintf (path, sizeof (path), "%s/gpio%d/edge", gpio_prefix, gpio); | |
fd = open (path, O_WRONLY); | |
if (fd < 0) { | |
goto exit; | |
} | |
switch (edge) { | |
case 1: | |
ret = write (fd, "rising", 6); | |
break; | |
case 2: | |
ret = write (fd, "falling", 7); | |
break; | |
case 3: | |
ret = write (fd, "both", 4); | |
break; | |
default: | |
ret = write (fd, "none", 4); | |
} | |
close (fd); | |
exit: | |
return ret; | |
} | |
static int | |
gpio_read (int fd) | |
{ | |
char buf[16]; | |
if (pread (fd, buf, 16, 0) <= 0) { | |
return -1; | |
} | |
if (buf[0] == '1') { | |
return 1; | |
} | |
return 0; | |
} | |
static int | |
gpio_write (int fd, int value) | |
{ | |
if (value) { | |
return write (fd, "1", 1); | |
} | |
return write (fd, "0", 1); | |
} | |
static int | |
gpio_poll (int fd, int timeout) | |
{ | |
struct pollfd pfd = { .fd = fd, .events = POLLPRI | POLLERR }; | |
return poll (&pfd, 1, timeout); | |
} | |
static int | |
gpio_open (int gpio, int direction) | |
{ | |
char path[256]; | |
int fd; | |
gpio_set_export (gpio, 1); | |
if (gpio_set_export (gpio, 0) < 0) { | |
fprintf (stderr, "ERR: Export gpio%d failed!\n", gpio); | |
return -1; | |
} | |
if (gpio_set_direction (gpio, direction) < 0) { | |
fprintf (stderr, "ERR: Set direction of gpio%d failed!\n", gpio); | |
return -1; | |
} | |
snprintf (path, sizeof (path), "%s/gpio%d/value", gpio_prefix, gpio); | |
fd = open (path, O_RDWR); | |
if (fd < 0) { | |
fprintf (stderr, "ERR: Open value of gpio%d failed!\n", gpio); | |
return -1; | |
} | |
return fd; | |
} | |
static void | |
gpio_close (int gpio, int fd) | |
{ | |
close (fd); | |
gpio_set_export (gpio, 1); | |
} | |
static void | |
click_button (int fd) | |
{ | |
const double duty_up = 2.0; | |
const double duty_down = 4.0; | |
int i; | |
for (i = 0; i < 10; i++) { | |
gpio_write (fd, 1); | |
usleep (duty_down * 200); | |
gpio_write (fd, 0); | |
usleep ((100.0 - duty_down) * 200); | |
} | |
for (i = 0; i < 10; i++) { | |
gpio_write (fd, 1); | |
usleep (duty_up * 200); | |
gpio_write (fd, 0); | |
usleep ((100.0 - duty_up) * 200); | |
} | |
} | |
int | |
main (int argc, char *argv[]) | |
{ | |
int fd; | |
if (set_scheduler_rt () < 0) { | |
fprintf (stderr, "WARN: Set realtime scheduler failed!\n"); | |
} | |
fd = gpio_open (145, 1); | |
if (fd < 0) { | |
goto exit; | |
} | |
click_button (fd); | |
gpio_close (145, fd); | |
return 0; | |
exit: | |
return -1; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment