Quantcast
Channel: 英特尔开发人员专区文章
Viewing all articles
Browse latest Browse all 583

在英特尔® Edison 开发板上使用 MCU 和超声测距传感器

$
0
0

除 CPU 外,英特尔® Edison 开发板还包含一个内部微控制器单元 (MCU)。 在本文中,我将从两个方面解释使用内部 MCU 的优势

  • 实时
  • 能效

MCU 在多款应用中都至关重要。 例如,基于英特尔® Edison 开发板的 Linux* 在与传感器交互时无法提供实时响应。 MCU 支持自 2.1 版开始能够在英特尔® Edison® 开发板固件软件版本上使用。

我们来了解一下英特尔® Edison 计算模块中使用的系统芯片 (SoC):

英特尔® Edison 计算模块中的系统芯片包括两个 CPU:

  • 双核英特尔® 凌动™ 处理器(500 MHz) 标有主机 CPU
  • 采用 Minute 英特尔® 架构的 MCU (100 MHz)。 标有 MCU

Minute 英特尔架构内核是一款节能架构,基于英特尔® 486,并额外采用指令,能够与英特尔® 奔腾® 处理器兼容。 MCU 包含丰富的 I/O 子系统(GPIO、I2C、高速 UART、DMA)和 SRAM,并能够访问英特尔® Edison 计算模块上的所有 GPIO 针脚。 适用于代码和数据的总 SRAM 为 192 kb。 MCU 使用 WindRiver 的实时 Viper* 操作系统运行。

MCU 程序支持在 Viper 内核上使用,并可控制连接到 MCU 上的外围设备,而不受英特尔凌动处理器的影响。 例如,它能够控制 GPIO 针脚,与采用 I2C 和 UART 协议的传感器通信,并与英特尔凌动处理器通信。

为何在英特尔® Edison 上使用 MCU

使用 MCU 得益于两个原因:提供实时微秒级延迟和高能效。

英特尔凌动处理器和 Yocto Project* 标准 Linux* 分发版不支持即购即用的实时应用。

Linux 应用可能会被调度器先占用,从而造成不可接受且不可预测的延迟,因而不可能提供实时响应。

MCU 运行一个应用和实时操作系统,这使得其有可能提供实时响应。

对于许多通信协议需要严格遵守短时间来执行的传感器,均需要实时响应。

如要在没有内部 MCU 的情况下将这些传感器连接到英特尔® Edison 开发板,您将需要使用外部 MCU。 在这种情况下,所有的传感器通信都在外部 MCU 上进行。 例如,面向英特尔® Edison 开发板的 SparkFun Block* – Arduino 扩展板可提供外部 MCU 功能。 但是,使用外部 MCU 将会增加 BOM 成本并提高解决方案的复杂性。

MCU 可以提高某些应用的能效,在这些应用中, CPU 设置为睡眠状态且 MCU 正在等待外部事件(如当传感器的值上升到超过阈值时)。

当外部事件出现时,MCU 将会唤醒 CPU。 《使用 MCU SDK 和 API: 代码示例》一文中介绍了实施示例。

为了解释如何使用内部 MCU,我们将把超声波测距传感器 HC-SR04 连接到英特尔® Edison 开发板中。 我们将把测量到的距离输出到 Grove* LCD RGB 背光符号显示器中。

超声波测距传感器 HC-SR04

该传感器有四个针脚:

  • Vcc: 5V
  • Trig: 触发传感器信号。 MCU 向传感器发送 10 us 脉冲。 传感器启动一次测量。
  • 回波: 从传感器到 MCU 的回波信号。 脉冲宽度随测量距离成比例增减。
  • Gnd接地

图片展示了示波器屏幕上的协议:

  • 1 个通道: Trig
  • 2 个通道: 回波

MCU 向 Trig 针脚发送一个脉冲。 之后,传感器将相应回波针脚上的脉冲。

脉冲持续时间随测量距离成比例增减。

使用公式来计算距离(位于传感器数据表上):

距离 (cm) = 回波脉冲持续时间 (us) / 58

传感器可以测量从 2 厘米到 400 厘米的距离(如数据表所示)。

不借助微秒级实时延迟,以预估的精确度不可能测量这么短的脉冲的持续时间。 例如,调度器可能预先占用测量流程,测量结果可能无效。

将 HC-SR04 传感器连接到英特尔® Edison 开发板上的 MCU

组件:

  • 英特尔® Edison 计算模块
  • 面向 Arduino 的英特尔® Edison 开发板
  • Grove Basic Shield
  • Grove LCD RGB 背光灯
  • 超声波测距传感器 HC-SR04
  • 电路试验板

 

首先,安装适用于 Arduino 的英特尔® Edison 计算模块和英特尔® Edison 开发板。 接下来,将 Grove Base Shield 扩展板连接至适用于 Arduino 的英特尔® Edison 开发板。 将 Grove LCD RGB 背光灯连接至 Grove Basic Shield 上的任意 I2C 端口。

将超声波测距传感器 HC-SR04 连接至 Grove Basic Shield,如下:

  • Vcc至 +5V
  • Trig至针脚 3
  • Echo至针脚 4
  • Gnd至 Gnd

针脚 3 和 4 随机选择。 针对此目的,您可以使用任意 GPIO 针脚。

更新英特尔® Edison 开发板固件

MCU 支持自 2.1 版开始已经添加到英特尔® Edison 开发板固件软件版本中。 如果您有较旧的固件,则需要更新它。

如要获取当前的固件版本,请使用以下命令:

# configure_edison –version

该示例基于固件版本 146。

《刷新英特尔® Edison》一文中提供了固件更新说明。 我更喜欢使用该篇文章中介绍的备用刷新方法。

请在刷新前仔细阅读说明。

使用以太网通过 USB 连接英特尔® Edison 开发板

您必须对网络连接进行配置,使其能够与 MCU SDK 中的英特尔® Edison 开发板相连。

如要做到这一点,请将 USB 连接线与顶部的微型 USB 端口相连,并将微型开关设置到底部位置(朝向微型 USB 端口)。

如要在 Linux 上配置网络:

# ifconfig usb0 192.168.2.2

英特尔® Edison 开发板 IP 地址: 192.168.2.15

如欲了解更多信息,请参阅使用 USB 以太网连接到您的英特尔® Edison 开发板

MCU SDK

开发人员需要 MCU SDK 创建适用于内部 MCU 的应用。 MCU SDK 是一个基于 Eclipse* 的跨平台 IDE。 《安装 MCU SDK》一文中解释了安装流程。

MCU SDK 提供了创建、编译、上传至开发板的功能,并能够调试面向 MCU 的应用。

与 MCU 通信

有多个接口可与 Linux 层面的 MCU 进行通信:

/dev/ttymcu0— 通过该接口与 MCU 传输数据。 可以使用 Linux 的标准文件操作进行操作。 MCU 程序可以使用 host_sendhost_receive函数。

/dev/ttymcu1— 使用 debug_print 函数从 MCU 发送调试消息的 接口。

/sys/devices/platform/intel_mcu/log_level — 设置调试消息日志级别的接口(fatal、error、warning、info、debug)。

使用 MCU 上面向 Arduino 的英特尔® Edison 开发板针脚

MCU 集成在英特尔® Edison 计算模块中,可以控制 70 针脚 Hirose 模块连接器上的 GPIO。

如要将 MCU 与面向 Arduino 的英特尔® Edison 开发板结合使用,您需要查找英特尔® Edison 计算模块 GPIO 针脚和面向 Arduino 的英特尔® Edison 开发板针脚之间的映射。 配置多路复用器和电平位移器,将英特尔® Edison 计算模块的 GPIO 路由至面向 Arduino 的英特尔® Edison 开发板针脚。

当从 Linux 层面处理时,这些例程将在 MRAA 库中处理。 在使用 MCU 处理时,开发人员需要使用脚本来处理它们(init_DIG.sh、init_i2c8.sh、init_mcu_PWM.sh、set_DIG.sh、read_DIG.sh、init_UART1.sh) 更多信息,请参见面向 Arduino* 的英特尔® Edison 套件硬件指南中的表 4。

面向 Linux 的脚本

下方的 Python* 脚本 show_distance.py 可从内部 MCU 中获取数据,并在 Grove LCD 显示器上显示它们。 我们将使用 UPM 库中的 Jhd1313m1 模块,与 Grove LCD 显示器交互。

show_distance.py (注:所有文件/脚本在本文末尾均存为 .zip 文件)

import time
import pyupm_i2clcd

RET_ERROR = -1

if __name__ == '__main__':
    lcd = pyupm_i2clcd.Jhd1313m1(6, 0x3E, 0x62)
    with open('/dev/ttymcu0', 'w+t') as f:
        while True:
            f.write('get_distance\n') # Send command to MCU
            f.flush()
            line = f.readline() # Read response from MCU, -1 = ERROR
            value = int(line.strip('\n\r\t '))
            lcd.clear()
            if value == RET_ERROR:
                lcd.setColor(255, 0, 0) # RED
                lcd.write('ERROR')
            else:
                lcd.setColor(0, 255, 0) # GREEN
                lcd.write('%d cm' % (value,))
            time.sleep(1)

MCU 程序

MCU 程序等待主机 CPU 的 get_distance命令。 如果程序收到 get_distance命令,它将会测量距离并向主机 CPU 发送结果(距离以厘米计,如果出现错误则显示 -1)。

针对面向 Arduino 的英特尔® Edison 开发板设置针脚:

# ./init_DIG.sh -o 3 -d output
# ./init_DIG.sh -o 4 -d input

MCU 可与英特尔® Edison 计算模块上的 GPIO 针脚配合使用,该模块在面向 Arduino 的英特尔® Edison 开发板上标有不同的数字。 如欲了解更多信息,请参阅使用 MCU 让 LED 闪烁

mcu.c (注:所有文件/脚本在本文末尾均存为 .zip 文件)

#include "mcu_api.h"
#include "mcu_errno.h"

// Arduino Extension PIN = 3
#define TRIG 12
// Arduino Extension PIN = 4
#define ECHO 129

// From HC-SR04 datasheet
#define MIN_DISTANCE 2
#define MAX_DISTANCE 400

#define MAX_WAIT 10000
#define RET_ERROR -1

int get_distance() {
	// Send Trig signal to HC-SR04
	gpio_write(TRIG, 1);
	mcu_delay(10);
	gpio_write(TRIG, 0);

	// Read Echo signal from HC-SR04
	int i;

	i = 0;
	while ((gpio_read(ECHO) == 0) && (i < MAX_WAIT)) {
		mcu_delay(1);
		i++;
	}

	unsigned long t0 = time_us();
	if (gpio_read(ECHO) == 0 || i == MAX_WAIT) {
		return RET_ERROR;
	}

	i = 0;
	while ((gpio_read(ECHO) == 1) && (i < MAX_WAIT)) {
		mcu_delay(1);
		i++;
	}

	unsigned long t1 = time_us();
	if (gpio_read(ECHO) == 1 || i == MAX_WAIT) {
		return RET_ERROR;
	}

	unsigned long distance = (t1 - t0) / 58;
	if (MIN_DISTANCE < distance && distance < MAX_DISTANCE) {
		return distance;
	} else {
		return RET_ERROR;
	}
}

#define MAX_BUF 255
unsigned char buf[MAX_BUF];

void mcu_main() {
	// Setup Trig as OUTPUT
	gpio_setup(TRIG, 1);
	// Initially set Trig to LOW
	gpio_write(TRIG, 0);
	// Setup Echo as INPUT
	gpio_setup(ECHO, 0);

	while (1) {
		unsigned int len;
		len = host_receive(buf, MAX_BUF);

		if ((len >= 12) && (strncmp(buf, "get_distance", 12) == 0)) {
			unsigned int distance;
			distance = get_distance();
			len = mcu_snprintf(buf, MAX_BUF, "%d\n", distance);
			host_send(buf, len);
		}
	}
}

添加我们的脚本以自动启动

如要启动我们的脚本,请先创建一个 shell 脚本:

File /home/root/startup.sh:

startup.sh (注:所有文件/脚本在本文末尾均存为 .zip 文件)

#!/bin/bash

cd /home/root

# configure PIN3 as GPIO OUPUT (TRIG signal)
./init_DIG.sh -o 3 -d output

# configure PIN4 as GPIO INPUT (ECHO signal)
./init_DIG.sh -o 4 -d input

python show_distance.py

将脚本标记为可执行文件:

# chmod a+x /home/root/startup.sh
# chmod a+x /home/root/init_DIG.sh

Yocto Project Linux 使用 systemd,因此我们需要创建 “service” 文件,添加脚本以自动启动。

创建 file/lib/systemd/system/startup-script.service:

startup-script.service (注:所有文件/脚本在本文末尾均存为 .zip 文件)

[Unit]
Description=Startup User Script
After=syslog.target

[Service]
ExecStart=/home/root/startup.sh

[Install]
WantedBy=multi-user.target

添加服务以自动启动:

# systemctl enable startup-script

重启后,符号显示器将会显示所测量的距离:

源代码

 

使用的资源

声明

英特尔技术的特性和优势取决于系统配置,并需要借助硬件、软件或服务来实现。 实际性能会因您使用的具体系统配置的不同而有所差异。 请联系您的系统制造商或零售商,或访问 intel.com.了解更多信息。

本文档不代表英特尔公司或其它机构向任何人明确或隐含地授予任何知识产权。

英特尔明确拒绝所有明确或隐含的担保,包括但不限于对于适销性、特定用途适用性和不侵犯任何权利的隐含担保,以及任何对于履约习惯、交易习惯或贸易惯例的担保。

本文包含尚处于开发阶段的产品、服务和/或流程的信息。 此处提供的所有信息可随时更改,恕不另行通知。 联系您的英特尔代表,了解最新的预测、时间表、规格和路线图。

本文所述的产品和服务可能包含与宣称的规格不符的缺陷或失误。 英特尔提供最新的勘误表备索。

如欲获取本文提及的带订购编号的文档副本,可致电 1-800-548-4725,或访问 www.intel.com/design/literature.htm

Intel、英特尔、Intel 标识、Intel Atom、英特尔凌动、Pentium和奔腾是英特尔在美国和/或其他国家的商标。

*其他的名称和品牌可能是其他所有者的资产。

英特尔公司 © 2015 年版权所有。


Viewing all articles
Browse latest Browse all 583

Trending Articles