Skip to content

Instantly share code, notes, and snippets.

@heiher
Created April 1, 2020 05:39
Show Gist options
  • Save heiher/495ce007ab59e3036dc1449849f1995a to your computer and use it in GitHub Desktop.
Save heiher/495ce007ab59e3036dc1449849f1995a to your computer and use it in GitHub Desktop.
外置硬盘盒电源开关伺服电机控制程序(NanoPi M4版)
/*
============================================================================
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