机器人开发套件闪烁 LED 教程

驱动英特尔® 实感™ 机器人开发套件 UP 开发板上的 GPIO 针脚闪烁 LED 电路。

您将学到的知识

本教程旨在通过针对“Hello World”的经典电子模拟,设置 UP 开发板以闪烁一个外部 LED,从而展示GPIO 针脚的基本用途。

机器人开发套件 UP 开发板简介

英特尔® 实感™ 机器人开发套件 (RDK) 由英特尔® 实感™ R200 景深摄像头 (R200) 和 Aaeon* UP 开发板组成。 UP 开发板是该系统的计算中心,能够通过 40 针输入/输出 header 与外部世界相连,如图 1 所示。 UP 开发板共有 28 个独立 GPIO 针脚,均在 I/O header 上提供。 Ubuntu 14.04 有一个专为 UP 开发板开发的内核平台驱动程序,可提供 0-27 号范围内的 Linux GPIO 针脚,从而模拟 Raspberry Pi。 

使用 Linux sysfs 可在较低的层面上访问适用于本教程的硬件 GPIO。  sysfs 支持用户在 Linux 中(或用户空间中的代码)在系统(内核)层与设备进行交互。

该教程使用 sysfs 接口,因此不要求使用特殊的库。

重点提示: 请注意,图 1 中的 Linux GPIO 编号不同于物理针脚编号和 UP 开发板引脚。 Linux GPIO 经过分配后,可匹配 Raspberry Pi BCM GPIO 编号方案。

如需对比 Raspberry Pi 布局,请访问: http://pinout.xyz

使用 UP 开发板点亮 LED

按照快速入门指南从新手到专家: 借助英特尔实感机器人开发套件实现正常运行配置 RDK 的 UP 开发板,即可准备好开发您的首个真实项目。 我们将使用 C 编程语言和 UP 开发板上的 GPIO 针脚点亮 LED。

今天你们将学习:

  • 组装基础电路并将其连接至 UP 开发板的 GPIO 针脚

你们需要

  • 1 个小 LED 灯(任意颜色)
  • 1 个 50 欧姆电阻器
  • 几根细线(实心)
  • 插孔组或鳄鱼夹,或两者,以进行连接

点亮 LED

编写代码之前先熟悉 UP 开发板的针脚编号,并创建一个简单的电路。 我们从使用 UP 开发板的 3.3 伏针脚和接地针脚点亮 LED 开始。 我们将使用以下电路原理图:


图 2

开始之前,拔掉 UP 开发板的插头, 以免‘接通电源’工作时发生短路,尤其因为这是我们的第一个项目。

  • 使用各种材料在插孔组上(或使用鳄鱼夹)创建电路。
  • 将 LED 较长的一端(正极)连接至针脚 1(+3.3 伏)。 该针脚能够提供稳定的 3.3 伏电源。 与 UP 开发板上的 GPIO 针脚不同,该针脚无法进行编程,也无法通过软件进行控制。
  • 将 LED 较短的一端连接至电阻器。 最后将电阻器的另一端连接至 UP 开发板的针脚 6(接地针脚)。

再次检查所有连接。 完成后的电路如下所示:


图 3

接通 UP 开发板的电源 — LED 应立即发亮。

通过代码控制 LED

测试完基础电路后,现在我们可以将正极引线从‘始终’ 3.3 伏针脚移至其中一个可编程 GPIO 针脚。 该电路如下所示:


图 4

  • 改变线路之前请再次关闭 UP 开发板。
  • 将正极引线从针脚 1 移至针脚 7。

完成后的电路如下所示:


图 5

使 LED 闪烁的源代码

以下代码示例可使电路闪烁。

#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define IN   0
#define OUT  1

#define LOW  0
#define HIGH 1

#define PIN  24 /* physical pin 18 */
#define POUT 4  /* physical pin 7  */

static int GPIOExport(int pin);
static int GPIOUnexport(int pin);
static int GPIODirection(int pin, int dir);
static int GPIORead(int pin);
static int GPIOWrite(int pin, int value);

int main(int argc, char *argv[])
{
	int repeat = 9;

	/*
	 * Enable GPIO pins
	 */
	if (-1 == GPIOExport(POUT) || -1 == GPIOExport(PIN))
		return(1);

	/*
	 * Set GPIO directions
	 */
	if (-1 == GPIODirection(POUT, OUT) || -1 == GPIODirection(PIN, IN))
		return(2);

	do {
		/*
		 * Write GPIO value
		 */
		if (-1 == GPIOWrite(POUT, repeat % 2))
			return(3);

		/*
		 * Read GPIO value
		 */
		printf("I'm reading %d in GPIO %d\n", GPIORead(PIN), PIN);

		usleep(500 * 1000);
	}
	while (repeat--);

	/*
	 * Disable GPIO pins
	 */
	if (-1 == GPIOUnexport(POUT) || -1 == GPIOUnexport(PIN))
		return(4);

	return(0);
}

Int GPIOExport(int pin)
{
#define BUFFER_MAX 3
	char buffer[BUFFER_MAX];
	ssize_t bytes_written;
	int fd;

	fd = open("/sys/class/gpio/export", O_WRONLY);
	if (-1 == fd) {
		fprintf(stderr, "Failed to open export for writing!\n");
		return(-1);
	}

	bytes_written = snprintf(buffer, BUFFER_MAX, "%d", pin);
	write(fd, buffer, bytes_written);
	close(fd);
	return(0);
}

Int GPIOUnexport(int pin)
{
	char buffer[BUFFER_MAX];
	ssize_t bytes_written;
	int fd;

	fd = open("/sys/class/gpio/unexport", O_WRONLY);
	if (-1 == fd) {
		fprintf(stderr, "Failed to open unexport for writing!\n");
		return(-1);
	}

	bytes_written = snprintf(buffer, BUFFER_MAX, "%d", pin);
	write(fd, buffer, bytes_written);
	close(fd);
	return(0);
}

Int GPIODirection(int pin, int dir)
{
	static const char s_directions_str[]  = "in\0out";

#define DIRECTION_MAX 35
	char path[DIRECTION_MAX];
	int fd;

	snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/direction", pin);
	fd = open(path, O_WRONLY);
	if (-1 == fd) {
		fprintf(stderr, "Failed to open gpio direction for writing!\n");
		return(-1);
	}

	if (-1 == write(fd, &s_directions_str[IN == dir ? 0 : 3], IN == dir ? 2 : 3)) {
		fprintf(stderr, "Failed to set direction!\n");
		return(-1);
	}

	close(fd);
	return(0);
}

Int GPIORead(int pin)
{
#define VALUE_MAX 30
	char path[VALUE_MAX];
	char value_str[3];
	int fd;

	snprintf(path, VALUE_MAX, "/sys/class/gpio/gpio%d/value", pin);
	fd = open(path, O_RDONLY);
	if (-1 == fd) {
		fprintf(stderr, "Failed to open gpio value for reading!\n");
		return(-1);
	}

	if (-1 == read(fd, value_str, 3)) {
		fprintf(stderr, "Failed to read value!\n");
		return(-1);
	}

	close(fd);

	return(atoi(value_str));
}

Int GPIOWrite(int pin, int value)
{
	static const char s_values_str[] = "01";

	char path[VALUE_MAX];
	int fd;

	snprintf(path, VALUE_MAX, "/sys/class/gpio/gpio%d/value", pin);
	fd = open(path, O_WRONLY);
	if (-1 == fd) {
		fprintf(stderr, "Failed to open gpio value for writing!\n");
		return(-1);
	}

	if (1 != write(fd, &s_values_str[LOW == value ? 0 : 1], 1)) {
		fprintf(stderr, "Failed to write value!\n");
		return(-1);
	}

	close(fd);
	return(0);
}

如果源代码在文件 blink.c 中,可以使用以下命令行命令对其进行编译:

gcc –Wall –o blink blink.c

结论

本 UP 开发板教程所展示的“Hello World”电路可将 UP 开发板变成 C 程序,从而运用 Linux sysfs 机制使 LED 闪烁 10 次。

本系列的下一篇教程将介绍如何将 R200 摄像头的深度数据与英特尔® 实感™ 交叉平台 API 相结合,并修改电路和 C 程序,以调节 LED 的亮度。

有关编译器优化的更完整信息,请参阅优化通知