Используем встроенный микроконтроллер в Intel Edison

от автора

Думаю, что многие из вас уже знакомы с Intel Edison по предыдущим заметкам, и у некоторых после прочтения спецификации, вероятно, возникал вопрос — а что это за второй загадочный процессор MCU, работающий на частоте 100 МГц? Зачем он нужен? Как его использовать?
Между тем роль MCU в некоторых случаях исключительно важна. Те, кто пробовал применять Edison для работы с различными сенсорами, возможно, уже заметили — Intel Edison не обеспечивает real-time отклика на их показания при работе из Linux. И тут на помощь приходит MCU. Пришло время немного рассказать про этот встроенный микроконтроллер, его архитектуру, области применения и рассмотреть практический пример.

В программное обеспечение для Intel Edison начиная с версии 2.1 добавлена возможность использования встроенного микроконтроллера.

Рассмотрим систему на чипе, используемую в Intel Edison Compute Module:

Система на чипе, используемая в Intel Edison Compute Module включает в себя два процессора:

  1. Двухъядерный процессор Intel Atom, работающий на частоте 500 МГц. Обозначен как Host CPU.
  2. Микроконтроллер с архитектурой Minute IA, работающий на частоте 100 МГц. Обозначен как MCU.

Рассмотрим микроконтроллер детальнее. Вычислительное ядро Minute IA представляет собой энергоэффективную архитектуру, основанную на 486 с добавлением команд для совместимости с Pentium. Помимо вычислительного ядра, микроконтроллер содержит подсистему ввода-вывода (GPIO, I2C, High Speed UART, DMA) и SRAM. Микроконтроллер имеет доступ ко всем портам GPIO в Edison Compute Module. Суммарный объем SRAM для кода и данных 192 кб. На микроконтроллере запущена операционная система реального времени Viper OS от компании WindRiver.

Приложение для микроконтроллера работает поверх ядра Viper и управляет периферией, подключенной к MCU, независимо от процессора Intel Atom. Например, оно может управлять GPIO портами, взаимодействовать с сенсорами по протоколу I2C или UART, и обмениваться данными с процессором Intel Atom.

Зачем нужен микроконтроллер в Intel Edison?

Я бы выделил две области, где можно применить встроенный микроконтроллер:

  1. Работа с портами ввода/вывода и интерфейсами с real-time откликом.
  2. Энергоэффективность.

Процессор Intel Atom и стандартный дистрибутив Yocto Linux не позволяют «из коробки» реализовать приложения с real-time откликом. Приложение может быть вытеснено планировщиком задач, что приведет к недопустимой и непрогнозируемой задержке. На микроконтроллере запущено единственное приложение и real-time операционная система, поэтому обеспечить real-time отклик возможно. Это требуется для работы со многими датчиками, где протокол взаимодействия зависит от строгого соблюдения коротких временных интервалов. Для их подключения без встроенного микроконтроллера пришлось бы использовать отдельный микроконтроллер, на котором реализовать всю функциональность по работе с такими датчиками. В качестве примера решения для Intel Edison с внешним микроконтроллером можно привести плату расширения SparkFun Block for Intel Edison — Arduino.

Повысить энергоэффективность с помощью микроконтроллера можно в тех приложениях, где основной процессор может находиться в состоянии сна, а микроконтроллер ожидать определенного события (например, превышения пороговых значений с сенсора).
При необходимости микроконтроллер пробуждает основной процессор. Пример реализации приведен в статье Using the MCU SDK and API: Code examples.

В качестве примера работы с микроконтроллером Intel Edison рассмотрим подключение ультразвукового датчика расстояния HC-SR04. Измеренное расстояние будем выводить на символьный экран Grove LCD RGB Backlight.

Ультразвуковой датчик расстояния HC-SR04


Датчик имеет 4 вывода:

  • Vcc — 5V.
  • Trig — сигнал Trigger к датчику. Микроконтроллер подает 10 микросекундный импульс датчику. Датчик инициирует процесс замера.
  • Echo — сигнал Echo от датчика к микроконтроллеру. Длительность импульса пропорциональна измеренной дистанции.
  • Gnd — Земля.

Вот как выглядит процесс работы с датчиком на экране осциллографа:

  • 1 канал — Trig
  • 2 канал — Echo

Микроконтроллер подает импульс на Trig. После этого датчик отвечает импульсом на Echo.
Длительность импульса пропорциональна измеренному расстоянию.
Измеренное расстояние вычисляется по формуле (взята из спецификации на датчик):

дистанция(см) = длительность импульса Echo (микросекунды) / 58

По спецификации датчик может замерять расстояния от 2 до 400 см.
Измерить длительность импульса с прогнозируемой погрешностью без real-time будет проблематично.
Процесс замера может быть, например, вытеснен планировщиком и результат измерения будет неверным.

Подключаем HC-SR04 к микроконтроллеру Intel Edison

Используемые компоненты:

  • Edison Compute Module
  • Edison Arduino Board
  • Grove Basic Shield
  • Символьный экран Grove LCD RGB Backlight
  • Ультразвуковой датчик расстояния HC-SR04
  • Макетная плата

Первым делом подключаем Edison Compute Module к Edison Arduino board. Затем подключаем плату расширения Grove Basic Shield к Edison Arduino Board. Grove LCD RGB Backlight подключается к I2C разъему на Grove Basic Shield.

Ультразвуковой датчик расстояния HC-SR04 подключается к Grove Basic Shield следующим образом:

  • Vcc к +5V.
  • Trig к пину #3.
  • Echo к пину #4.
  • Gnd к Gnd.

Пины 3, 4 выбраны случайным образом, вместо них можно использовать другие.

Обновление прошивки Intel Edison

Поддержка микроконтроллера доступна в Intel Edison® Board Firmware Software Release начиная с версии 2.1. Если у вас прошивка старее, то её нужно обновить.

Узнать текущую версию прошивки можно командой:

# configure_edison --version 

Данный пример создавался на прошивке версии 146.

Процесс обновления прошивки подробно описан в статье Flashing Intel Edison. Лично я обычно пользуюсь способом, описанным в разделе Alternate Flashing Method.
Внимательно прочитайте инструкцию перед прошивкой.

Подключаем Intel Edison через Ethernet-over-USB

Для работы с Edison из среды MCU SDK нужно создать сетевое подключение.
Для этого нужно, например, подключить USB кабель к среднему micro-USB порту (переключатель должен быть установлен в сторону micro-USB портов).
В Linux сеть настраивается командой:

# ifconfig usb0 192.168.2.2 

IP-адрес Intel Edison: 192.168.2.15
Более подробно процесс подключения описывается в статье Connecting to your Intel® Edison board using Ethernet over USB.

MCU SDK

Для создания приложений, которые будут выполняться на встроенном микроконтроллере, выпущена кроссплатформенная среда разработки MCU SDK, основанная на Eclipse. Процесс установки подробно рассмотрен в статье Installing the MCU SDK.
MCU SDK позволяет создавать, компилировать, загружать на плату и отлаживать приложения для микроконтроллера.

Взаимодействие с MCU

Чтобы взаимодействовать с микроконтроллером из Linux доступны несколько интерфейсов:
/dev/ttymcu0 — Канал для обмена данными. Из Linux можно работать с помощью стандартных файловых операций. Из программы на микроконтроллере обмен производится с помощью функций host_send и host_receive.
/dev/ttymcu1 — Канал, по которому микроконтроллер отправляет отладочные сообщения функцией debug_print.
/sys/devices/platform/intel_mcu/log_level — Позволяет установить уровень отладочных сообщений (fatal, error, warning, info, debug).

Работа с портами Edison Arduino Board

Микроконтроллер встроен в Edison Compute Module и управляет портами ввода-вывода, размещенными на 70-выводном разъеме модуля.
Если необходимо использовать микроконтроллер c Edison Arduino Board, то нужно найти соответствие GPIO порта в Edison Compute Module номеру порта в Edison Arduino Board.
Затем нужно сконфигурировать мультиплексирование и установить направление в преобразователе логических уровней.
При работе с портами на Linux-уровне все эти действия выполняет библиотека MRAA. В случае с микроконтроллером об этом необходимо позаботиться самостоятельно с помощью скриптов (init_DIG.sh, init_i2c8.sh, init_mcu_PWM.sh, set_DIG.sh, read_DIG.sh, init_UART1.sh). Более подробная информация приведена в Intel® Edison Kit for Arduino* Hardware Guide (таблица 4).

Программа для Linux

Небольшой скрипт на Python, который будет получать данные от встроенного микроконтроллера и выводить их на символьный дисплей. Для работы с символьным дисплеем воспользуемся модулем Jhd1313m1 из библиотеки UPM.

Скрипт show_distance.py:

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) 

Программа для микроконтроллера

Программа на микроконтроллере должна при получении от хоста команды get_distance произвести измерение дистанции и отправить результат на хост (дистанция в сантиметрах, либо -1 в случае ошибки).
Настраиваем порты на Edison Arduino Board:

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

Напомню, что микроконтроллер работает с GPIO портами на Edison Compute Module, которые отличаются от нумерации на Edison Arduino Board. Таблица соответствия приведена, например, в конце статьи Blinking an LED using the MCU.

Программа для микроконтроллера в MCU SDK:

#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); 		} 	} } 

Добавляем скрипт в автозапуск

Создаем файл, который будет запускать наш скрипт:

Файл /home/root/startup.sh

#!/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 Linux использует systemd, то для добавления скрипта в автозапуск нужно создать файл так называемого «сервиса».

Создаем файл /lib/systemd/system/startup-script.service

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

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

[Install]
WantedBy=multi-user.target

Добавляем скрипт в автозапуск:

# systemctl enable startup-script 

После перезагрузки на символьном дисплее должна отобразиться измеренная дистанция:

Использованные ресурсы

ссылка на оригинал статьи http://habrahabr.ru/post/260471/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *