Використовуємо вбудований мікроконтролер в 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 до +5В.
  • 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 OUTPUT as
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

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


Використані ресурси

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.