Інгредієнти IoT делікатесів швидкого приготування: Intel Edison + Intel XDK + JavaScript + Grove Kit

Наскільки швидко можна створити пристрій для Інтернету речей (IoT), яке управляється через браузер, отримує і передає інформацію, враховуючи, що ви ніколи не працювали з мікроконтролерами, а тільки займалися високорівневим програмування на JavaScript?



Наприклад, такий пристрій як на фото. У нього є РК-екран і стрілочний покажчик на сервоприводі. Поруч лежить телефон із запущеним браузером, який підключений до вебсерверу на пристрої. При натисканні стрілки в браузері, покажчик повертається вправо, вліво або встановлюється в нейтральне положення. Після установки значення, воно передається назад в браузер і показується як значення Value. Додатково у браузері можна задати текстовий рядок, що після натискання кнопки «Set text» виводиться на РК-екрані. Всі взаємодія відбувається по Wi-Fi. Як ви думаєте, скільки часу піде на розробку?

Якщо поміркувати, доведеться багато чого зробити. Написати код на C/С++, який виконується на пристрої і взаємодіє з датчиками, підняти вебсервер, реалізувати бекенда, фронтэнд, і все це поєднати. Насправді, все набагато простіше. І, насмілюся стверджувати, що на все вистачить години. Чому? Та тому, що є готові рішення, які можна об'єднати і, таким чином, швидко зробити продукт. Ми візьмемо плату Intel Edison, середовище розробки Intel XDK IoT Edition, набір датчиків Grove Kit і всього одна мова програмування — JavaScript. Так, жодного З/З++. Все просто, відразу з коробки.

Я розповім про все по порядку, починаючи з самих азів, щоб навіть непідготовлений розробник не загубився. Ну, а на завершення ми розглянемо спочатку описаний приклад.

Grove Starter Kit Plus — Intel IoT Edition Gen2


Набір Grove Starter Kit — це чудова штука. Знаю, що деякі програмісти бояться працювати з радіоелектронікою. Всякі там дроти, з'єднання, паяння, радіодеталі… Але цей набір дозволяє спростити роботу. Всі датчики підключаються універсально з допомогою стандартних роз'ємів, які, при всьому бажанні, не можна з'єднати неправильно. Всі роз'єми на платі розширення підписані. Досить під'єднати потрібні дроти до датчиків і можна зосередитися на програмній частині пристрою.

В комплект входять:

  • Плата розширення, з роз'ємами для стандартного підключення всіх датчиків.
  • Світлодіод.
  • Зумер.
  • Реле.
  • Кнопка звичайна.
  • сенсорна Кнопка.
  • Датчик повороту.
  • Термометр.
  • Мікрофон.
  • Датчик освітлення.
  • Сервопривід.
  • РК-екран.
  • Дроти з роз'ємами.
  • USB роз'єми.
  • Роз'єм для батарейки типу " Крона.
Звичайно, можна купити датчики і самостійно підключити їх. Так, це буде дешевше, але тут всі стандартні роз'єми, всі дроти вже є в наявності. Навіть мені, кого не налякати пайкою, набагато приємніше просто втикати розйомчики і думати не про те, де який проводок, а про саму програму. Тим більше, у мене була ситуація на хакатоне, коли я поспіхом підключаючи датчики перед демонстрацією, переплутав дроти, подавши харчування на вихід сенсора. На щастя, нічого не згоріло.

Середовище розробки Intel XDK IoT Edition


Середовище розробки Intel XDK дозволяє створювати програми на JavaScript на Node.js і запускати їх на платі Intel Edison і Intel Galileo. Це дає можливість тим розробникам, які раніше писали на JavaScript в основному для інтернету, спробувати себе в чомусь новому. Перевага в тому, що якщо раніше, щоб писати для мікроконтролера, треба було знати C/C++, то тепер все стає набагато простіше. Ви просто пишете свою програму на вашому будь-якому JavaScript, і все працює.

Можливо, що додаток, написаний на JavaScript, буде поступатися в швидкості такого ж, але на C++. Але справа в тому, що код писати легше, так, і потужне залізо зараз. Перевага Intel XDK ще і в тому, що завантаження і запуск програми на плату з усіма пов'язаними бібліотеками і файлами робиться натисканням пари кнопок.

Знову наведу приклад з хакатона. Одна з команд розповідала, що вони довго мучилися з реалізацією свого проекту. Намагалися змусити його працювати і на Python і на З++. Але тільки перейшовши на JavaScript у них все відразу вийшло.

Труднощі, які були при розробці
Іноді XDK не міг підключитися до Edison. При цьому плата працювала з серійного порту (емуляція через USB). Перевірка показала, що не працював WiFi на платі. Виявилося, що в моїй версії прошивки плати був баг. Коли працюєш з роз'ємом D7, то починає погано працювати Wi-Fi. Після цього дуже проблематично змусити плату працювати нормально. Т. к. при перезапуску плати, програма стартує автоматично. Я вирішив тільки підключенням до USB з емуляцією серійного порту. Підключившись, виправив програму, щоб вона не зверталася до D7 і перезапустив плату.

Ось опис проблемиhttps://github.com/intel-iot-devkit/mraa/краплі/master/docs/edison.md — Arduino pin 7 can sometimes negatively impact the WiFi capability, if using WiFi avoid using this pin.
Проблема усунена в останньому релізі:
http://download.intel.com/support/edison/sb/edison_rn_332032009.pdf
Resolved issues:
EDISON-2356 Setting Arduino 7 pin to output causes Wi-Fi connection to become flaky.
Підключення плати
Припускаю, що ви вже підключили плату Intel Edison до комп'ютера через USB або WiFi. Якщо ні, то є кілька способів. Можна включити емуляцію серійного порту USB, це крайній роз'єм microUSB. Можна включити емуляцію мережевого інтерфейсу USB, це середній роз'єм microUSB. Можна використовувати WiFi. Харчування можна підключити через USB або за допомогою блоку живлення.

Бібліотека MRAA
Для спрощення роботи з датчиками з JavaScript є спеціальні бібліотеки. Одна з них це MRAA. Вона забезпечує досить низький рівень роботи з платою.

http://iotdk.intel.com/docs/master/mraa/index.html — документація по MRAA

Її основне завдання – налаштувати пін на введення або виведення, видати нуль або одиницю, вважати значення цифрового або аналогово сигналу з контакту. Може налаштувати пін на роботу в ШІМ (PWM) режимі і задати його параметри. Цього достатньо, щоб помигати світлодіодом, вважати стан кнопки, отримати значення температури з датчика, включити сервопривід.
Ось, наприклад, програма включення вбудованого на платі світлодіода:

var mraa = require('mraa'); 
var myOnboardLed = new mraa.Gpio(13); // працюємо з 13-им піном
myOnboardLed.dir(mraa.DIR_OUT); // налаштовуємо його на висновок
myOnboardLed.write(1); // встановлюємо високий рівень сигналу на піне

Але от якщо треба керувати чимось більш складним, наприклад, РК-екраном, то цього недостатньо.

Бібліотека UPM
Така бібліотека це UPM. Вона надає більш високий рівень роботи.

http://iotdk.intel.com/docs/master/upm/node/ — документація по UPM для Node.JS

В бібліотеці реалізовані алгоритми для управління складними пристроями, наприклад, екранами, сервомоторами і т. д. Інакше, це довелося б робити самостійно. Ми будемо її використовувати для керування РК-екраном по послідовній шині I2C.

Приклад програми виводить на РК-екранчик текст:

var jsUpmI2cLcd = require ('jsupm_i2clcd');
var lcd = new jsUpmI2cLcd.Jhd1313m1(0, 0x3E, 0x62);
lcd.setCursor(1,5);
lcd.write('Hello Edison!');

Робота Node.JS
Коли ви створюєте додаток в Intel XDK на комп'ютері, ви завантажуєте його на плату (кнопка Upload). Він буде поміщений в теку, але не буде запущений. Проект знаходиться на платі у теці /home/root/.node_app_slot на цю папку налаштована посилання з кореня /node_app_slot

Відправлене на плату додаток можна запустити двома способами. Або безпосередньо з середовища розробки кнопкою Run. Або вручну в консолі на платі, для цього треба перейти в папку /node_app_slot і виконати команду

node main.js

Якщо ж ви перезавантажте плату Edison, додаток стартує автоматично. Щоб це не відбувалося, можна прибрати з автозапуску старт демона, або видалити або перейменувати файл main.js, що простіше.

Зараз ми розглянемо всі датчики, які йдуть в комплекті Grove Starter Kit Plus (Intel IoT Edition) групами за типом підключення.

Світлодіод, зумер, реле


Всі ці пристрої підключаються до цифрового виходу. Можна використовувати D2-D8. При подачі одиниці вони включаються, при нулі вимикаються.

Світлодіод
В комплекті є три світлодіода — червоний, синій і зелений. Вибирайте будь-який. Світлодіод пристрій полярне, значить важливо підключити його правильно. Треба вставляти світлодіод так, щоб довга ніжка (анод) була в роз'ємі зі значком «+». Але якщо ви підключите неправильно, він усього лише не буде світити.



Підключимо його до D2 і помигаем.



Вихідний код main.js
/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */

// Підключити бібліотеку mraa
var mraa = require('mraa'); 

// Ініціалізуємо D2 висновок як цифровий вихід
var myOnboardLed = new mraa.Gpio(2); 

// Налаштуємо на висновок
myOnboardLed.dir(mraa.DIR_OUT); 
var ledState = true; //Поточний стан світлодіода

// Будемо викликати функцію через кожні 100 мс
setInterval(periodicActivity,100);

function periodicActivity()
{
myOnboardLed.write(ledState?1:0); // встановимо сигнал станом
ledState = !ledState; // змінимо стан на протилежне
}

Зумер
Зумер або пищалка. При подачі напруги починає пищати на одній частоті. Підключається до цифрового виходу. Можна використовувати код, як для світлодіода.

Реле
Реле являє собою вимикач, який управляється сигналом. При подачі одиниці вимикач замикає контакти, при подачі нуля, розмикає. Його можна використовувати для управління пристроями, які розраховані на напругу більше ніж 5В і струм, більший ніж 0.5 А і тому підключені до зовнішнього джерела живлення. Наприклад, можна включити настільну лампу. Реле, яке йде в комплекті Grove має параметри 10A х 250V. Це 2,5 кВт. Але це гранична потужність. Думаю, чайник не варто включати таким способом. І якщо будете комутувати прилад з напругою живлення 220 В, будьте обережні, по-перше сама напруга небезпечно для здоров'я, а по-друге, якщо воно потрапить на плату, тоді вона швидше за все згорить.

ШІМ і регулювання яскравості світлодіода
А що робити, якщо ми хочемо видавати аналоговий сигнал проміжного рівня, а не тільки нуль і один? Або як включити світлодіод на половинну яскравість, якщо у нього тільки два стани? Цього можна досягти за допомогою ШІМ – широтно-імпульсної модуляції (PWM – Pulse-width modulation). При її використовуванні сигнал періодично змінюється з 1 до 0.

Це відбувається кожен кадр. Коли час обох рівнів однакове, то в середньому ми отримуємо значення 0,5. Припустимо, одиниця була 25% часу, тоді і сигнал виходить таким же, 0.25 від максимального. Якщо ми так управляємо світлодіодом і кадр вибраний досить малим, то через інертність нашого зору ми будемо бачити це середнє значення яскравості.

Частина цифрових роз'ємів на платі може працювати в режимі PWM, на шилде це D3, D5, D6. (На самій платі Edison вони помічені позначкою «~»).

Для включення PWM треба задати кілька параметрів. Перше, це період повторення сигналу, тобто величина кадру. Другий параметр-це час, протягом якого буде одиниця. Його можна задавати або як коефіцієнт 0-1, або як значення часу до мкс.

Ось приклад, в якому буде блимати світлодіод, плавно змінюючи свою яскравість.

Вихідний код main.js
/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */

var mraa = require("mraa");
var pwm3 = new mraa.Pwm(5);

var frameSize = 2000;
pwm3.enable(true);
pwm3.period_us(frameSize);

var value = 0;
var step = 0.04;

setInterval(proc, 20);

function proc()
{
value += step;
if( value < 0 )
{
value = 0;
step = -step;
}
else if( value > 1 )
{
value = 1;
step = -step;
}

pwm3.write(value);
}

Кнопка звичайна і сенсорна


Кнопки підключаються до цифрових входах D2-D8. Видають одиницю, якщо на них натиснули. Відмінність один від одного в тому, що сенсорна кнопка являє собою ємнісний датчик і тому спрацьовує від легкого дотику і працює навіть через шар паперу.

Створимо програму, яка буде виводити на екран стан кнопки.
Підключаємо кнопку до D8:



Вихідний код main.js
/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */

var mraa = require('mraa');

// будемо використовувати висновок D8
var myButton = new mraa.Gpio(8);

// налаштовуємо на введення
myButton.dir(mraa.DIR_IN); 

// викликаємо опитування кнопки
getButton(); 

// кожні 20 мс опитуємо кнопку
function getButton()
{
var b = myButton.read();
console.log('button='+b); 
setTimeout(getButton,20); 
}

Якщо після запуску ви будете натискати кнопку, то побачите щось подібне.



Датчик повороту, термометр, мікрофон, датчик освітлення


Всі ці датчики видають аналоговий сигнал різного рівня в залежності від зовнішнього впливу на них. Підключаються до аналогових входів A0-A3. Значення сигналу 0-1023.

Датчик повороту
Повертає кут, на який він повернений. Значення в діапазоні 0-1023.
Підключимо його в A0.



Вихідний код main.js
/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */

var mraa = require('mraa'); //require mraa

// Підключаємо до A0
var myRotary = new mraa.Aio(0); 

getRotary();

function getRotary()
{
var b = myRotary.read();
console.log('rotary='+b); 
setTimeout(getRotary,20); 
}

При запуску програми і обертанні ручки ви побачите приблизно такий висновок.



Датчик температури
Як можна здогадатися, він повертає значення температури. Але недостатньо просто вважати значення, так як це буде відносне опір терморезистора. Для перекладу в градуси краще використовувати бібліотеку UPM. Отже, підключимо датчик до A0.

Вихідний код main.js
/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */

var mraa = require('mraa');
var groveSensor = require('jsupm_grove');

// Підключаємо до A0
var temp = new groveSensor.GroveTemp(0);

setInterval(getTemp,100);

function getTemp()
{ 
var celsius = temp.value();
console.log('temp='+celsius);
}

Бібліотечна функція повертає ціле значення. Якщо потрібно більш точне значення, можна скористатися наступним кодом, який використовує безпосередньо значення датчика.

Вихідний код main.js
/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */

var mraa = require('mraa'); //require mraa

var temp = new mraa.Aio(0); 

setInterval(getTemp,100);

function getTemp()
{ 
var sens = temp.read();
var celsius = convertTemp(sens);
console.log('temp='+celsius);
}

function convertTemp(sensorValue)
{
var resistance=(1023-sensorValue)*10000/sensorValue; //отримаємо опір
var temperature=1/(Math.log(resistance/10000)/3975+1/298.15)-273.15;//convert by datasheet ; 
return temperature;
}

Мікрофон
Мікрофон видає рівень звукового сигналу. Підключимо до A1. Значення, як зазвичай для аналогового входу, лежать в діапазоні від 0 до 1023.

Вихідний код main.js
/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */

var mraa = require('mraa');
var myMic = new mraa.Aio(1); 

getLevel(); 

function getLevel()
{
var lev = myMic.read();
console.log('level='+lev); 
setTimeout(getLevel,20); 
}

Сервопривід


Більш цікава штука — сервопривід, це мотор, який повертається на заданий кут (0-180 градусів) і намагається зберегти це положення.

Для завдання кута, треба подавати імпульс, певної тривалості (шпаруватості). Такі імпульси повинні приходити постійно, зазвичай 50 разів в секунду (20 мс). Але період приходу не так важливий, важлива тривалість. Вона може бути від 500 мкс до 2000 мкс. При мінімальному значенні імпульсу встановлюється в кут 0 градусів, при максимальному в 180 градусів.

Для різних сервоприводів граничні значення тривалості імпульсу можуть відрізнятися. Їх можна підібрати експериментально. Але треба бути акуратним. Якщо значення тривалості лежить поза допустимого діапазону, тоді сервомотор починає стукати і сильно нагрівається. При правильній роботі він повинен повернутися на заданий кут, зупиниться і замовкнути, залишаючись холодним.

Будемо використовувати цифровий вихід, який вміє виводити ШІМ (PWM) сигнал. Це висновки D3, D5, D6.

Треба врахувати, що з-за того, що PWM може приймати на вхід тільки 256 значень і не можна використовувати всі значення для заповнення, а тільки невелику частину, то виходить, що фіксованих кутів у сервоприводу не так і багато, у мене вийшло близько 20.

РК-екран


Екран пристрій більш складне, ніж світлодіод, тому і підключається до спеціальної послідовній шині I2C.

На екран можна виводити текст в 2 рядки по 16 символів в кожній. Є RGB підсвічування. В документації сказано, що підтримує Англійська та Японська мови і є можливість додавати деяку кількість своїх символів.

Так як пристрою до шини I2C підключаються паралельно, то всі роз'єми на платі рівнозначні, і екран можна вставити в будь-який з них.



Ми використовуємо бібліотеку UPM.

http://iotdk.intel.com/docs/master/upm/node/classes/jhd1313m1.html — робота з цим екраном.

var jsUpmI2cLcd = require ('jsupm_i2clcd');
var lcd = new jsUpmI2cLcd.Jhd1313m1(0, 0x3E, 0x62);
lcd.setColor(100, 127, 53);
lcd.setCursor(1,1);
lcd.write('Hello Edison!');


Зберемо всі разом
Ось ми і розглянули всі пристрої, які є в наборі Grove Starter Kit Plus. Спробуємо зібрати щось цікавіше, що одночасно використовують кілька модулів.

У нас буде датчик повороту (A0), при обертанні якого сервопривід (D3) буде повертатися на відповідний кут. Знайдена тривалість імпульсу ШІМ для повороту на цей кут буде відображатися на екрані (I2C).



Вихідний код main.js
/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */

var mraa = require('mraa');

var jsUpmI2cLcd = require ('jsupm_i2clcd');
var lcd = new jsUpmI2cLcd.Jhd1313m1(0, 0x3E, 0x62);
lcd.setColor(100, 127, 53);

var myRotary = new mraa.Aio(0); 

var pwm3 = new mraa.Pwm(3);
pwm3.enable(true);
var frameSize = 20000; 
pwm3.period_us(frameSize);

setInterval(proc, 100);

function proc()
{
// визначимо відносне положення повороту
var maxRotary = 1023;
var valueRate = value / maxRotary ;

// знайдемо тривалість імпульсу 
var minServoTime = 420;
var maxServoTime = 2000;
var servoVal = Math.floor(minServoTime + (maxServoTime - minServoTime)*valueRate);

// встановимо тривалість у мікросекундах
pwm3.pulsewidth_us(servoVal);

// покажемо тривалість на екранчику
lcd.setCursor(0,0);
lcd.write('Time=' + servoVal + ' us ');
}

Створення веб-сервера
Раз ми розглядаємо розробку для IoT (Internet of Things – Інтернет речей) нам треба зробити можливість роботи з пристроєм через інтернет. Наступний приклад створює вебсервер, який показує поточну температуру на температурному датчику. Сервер прослуховує 1337 порт і відповідає на запит до кореня сайту. Датчик температури підключаємо до A0. Якщо ваша плата має адресу 192.168.0.105, тоді в браузері вказуємо 192.168.0.105:1337.

Вихідний код main.js
var mraa = require('mraa');
var groveSensor = require('jsupm_grove');

var temp = new groveSensor.GroveTemp(0);

var lastSetVal = 0;

var app = require('express')();
var http = require('http').Server(app);
var url = require("url");

var numCalls = 0;

app.get(", function (req, res)
{
'use strict';
res.writeHead(200, {"Content-Type": "text/html"});
res.write('Intel Edison temperature Sensor' + temp.value() + '<sup></sup>C');
res.end();
});

http.listen(1337, function () {
'use strict';
console.log('listening on *:1337');
});

Приклад роботи:



Десерт — управління через браузер


Отже, обіцяне в самому початку. Створимо пристрій, керований через браузер, зі стрілкою на сервоприводі і екранчиком. І при кожній команді повороту від клієнта, воно буде у форматі JSON повертати реально встановлене значення, так як в крайніх положеннях повороту не відбувається. І як маленький бонус, на підключений РК-екран можна відсилати текст.

Програма складається з двох частин. Одна з них знаходиться на пристрої Edison. Це вебсервер, файл main.js. Він відповідає на запити клієнта, обслуговує сервопривід і екран. Використовує бібліотеку express і http.

Друга частина знаходиться на клієнта у браузері. Вона отримує команди від користувача і пересилає їх на сервер. Отримує дані від веб-сервера у форматі JSON і відображає їх. Використовує бібліотеку jQuery.

Це додаток буде трохи складніше. У проекті створимо папку public, у неї помістимо статичний контент. У нашому випадку це три зображення для кнопок — rotate_ccw.png, rotate_cw.png, rotate_center.png, html-файл index.html, який відображається в браузері клієнта і бібліотека jquery-1.11.3.min.js (Її треба буде завантажити з офіційного сайту jquery.com/download



На клієнті скрипт відстежує натискання на зображення стрілок і при виникненні такої події відправляє запит на сервер за відповідною адресою /right, /left, /center і очікує отримання JSON даних з інформацією про положення стрілки. При натисканні на кнопку «Set text», текст з поля вводу відправляється на сервер.

Вміст файлу index.html
<html><body>

<title>Rotation</title>

<script src="jquery-1.11.3.min.js"></script>

<script>

function showVal(val)
{
$("#val").text('Value='+val);
}

function left()
{
$.getJSON( "/left", function( data ) {
showVal(data['value']);
} ) ;
} 

function right()
{
$.getJSON( "/right", function( data ) {
showVal(data['value']);
} );
} 

function center()
{
$.getJSON( "/center", function( data ) {
showVal(data['value']);
} );
} 

function setText()
{
$.get("/text/"+$("#text").val());
} 

</script>

<a onclick="left();">
<img src="rotate_ccw.png"/>
</a>

<a onclick="center();">
<img src="rotate_center.png"/>
</a>

<a onclick="right();">
<img src="rotate_cw.png"/>
</a> 
<br/>
<h1 id="val">Value=0</h1>

<input id="text" type="text" name="data" value=""> 
<input type="submit" value="Set text" onclick="setText();" />

</body></html>

На платі екран підключений до I2C. Сервопривід підключається до D3. Сервер прослуховує 1337 порт. Додаток очікує звернення до /right. При такому запиті, якщо можливо, виконується поворот вправо і надсилається відповідь у форматі JSON з інформацією про положення стрілки. Аналогічно оброблюється звернення до /left /center. При запиті виду /text/abcdef рядок abcdef буде виведена на ЖК-екран. Робота з сервоприводом і екраном була розглянута раніше.

Вміст main.js
var mraa = require('mraa');

/ / ----- PWM-----
var value = 0.5;
var step = 0.05;
var frameSize = 20000; 

var pwm3 = new mraa.Pwm(3);
pwm3.enable(true);
pwm3.period_us(frameSize);
setTime(value);

//---------- LCD----------
var jsUpmI2cLcd = require ('jsupm_i2clcd');
var lcd = new jsUpmI2cLcd.Jhd1313m1(0, 0x3E, 0x62);

var express = require('express');
var http = require('http');
var app = express();

// папка зі статичним контентом
app.use(express.static(__dirname + '/public'));

// поворот вліво
app.get('/left', function (req, res)
{
value = fitValue(value-step);
setServoValue(res,value);
});

// поворот вправо
app.get('/right', function (req, res)
{
value = fitValue(value+step);
setServoValue(res,value);
});

// установка центру
app.get('/center', function (req, res)
{
value = 0.5; 
setServoValue(res,value);
});

// відображення тексту на LCD
app.get('/text/:text', function (req, res)
{
var text = req.params.text;

var t = text.toString().substring(0, 16);
var vs = t + ' '.substring(0,16-t.length);

lcd.setCursor(0,0);
lcd.write(vs);
console.log('value='+vs+'=');
res.writeHead(200, {"Content-Type": "text/html"});
res.end();
});

// створення сервера
http.createServer(app).listen(1337);

// поворот і повернення положення в JSON 
function setServoValue(res,v)
{
res.writeHead(200, {"Content-Type": "text/json"});

var text = '{"value":"'+value.toFixed(2)+'"}';
res.write(text); 
console.log(text); 

setTime(value); 
res.end(); 
}

// установка значення для сервоприводу
function setTime(valueRate)
{
var minServoTime = 420;
var maxServoTime = 2000; 
var servoVal = Math.floor(minServoTime + (maxServoTime - minServoTime)*(1-valueRate));
pwm3.pulsewidth_us(servoVal);
}

// коригування значення
function fitValue(v)
{
if( v > 1 ) { v = 1; }
if( v < 0 ) { v = 0; }
return v;
}

Вміст package.json
{
"name": "PWM",
"description": "",
"version": "0.0.0",
"main": "main.js",
"engines": {
"node": ">=0.10.0"
},
"dependencies": {
"express" : "latest",
"http" : "latest"

}
}

Зображення rotate_ccw.png


Зображення rotate_cw.png


Зображення rotate_center.png


Ось власне і все. Запускаємо і перевіряємо.

Демони Node.JS
Пара слів про те, як працюють демони на платі Intel Edison.
В системі запущений демон xdk-daemon. Якщо його зупинити командою:

systemctl stop xdk-daemon

тоді працює Node.JS-додаток зупиниться. Запустити повторно можна командою:

systemctl start xdk-daemon

або перезапустити:

systemctl restart xdk-daemon

Програму можна редагувати безпосередньо на платі (vi), тільки не забувайте після зміни її перезапускати. Або так:

systemctl restart xdk-daemon

Або, якщо програма була запущена в консолі через команду:

cd /node_app_slot
node main.js

то зупинити її можна через <Ctrl>+<C>

Корисніше
» Відтворення звуку на Intel Edison через Bluetooth з використанням Advanced Audio Distribution Profile (A2DP)
» Установка OpenCV 3.0.0-rc1 (з використанням IPP і TBB) на Intel Edison Yocto. USB-камера OpenCV
» Використання плати Intel Edison для зміни кольору кулі Orbotix Sphero при появі нових твітів
» Підключаємося до Intel Edison через Android з Bluetooth LE (BLE)

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

0 коментарів

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