Электронный компонент:Набор Grove IoT Starter Kit с Beaglebone Green и поддержкой AWS

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.
Черновик


Набор Grove IoT Starter Kit с Beaglebone Green и поддержкой AWS[1]

Плата BeagleBone Green (BBG) – это совместная работа BeagleBoard.org и Seeed Studio. Она создана на основе BeagleBone Black, но имеет и нововведения – к примеру, два Grove-коннектора. Набор, о котором рассказывает эта статья, содержит плату BBG, десять Grove-модулей и пошаговые руководства, которые объясняют, как подключить эти компоненты друг к другу. Кроме того, все компоненты набора совместимы с облачными сервисами AWS (Amazon Web Services).

Купить набор можно по этой ссылке.

Функционал

  • Для сборки проектов не требуется ни пайки, ни макетной платы
  • Полная совместимость с сервисами и технологиями AWS
  • Пошаговые руководства

Что идет в комплекте

С чего начать

Настройка сервиса AWS IoT

В самом начале нужно войти в аккаунт AWS IoT и выполнить определенные настройки.

1. Создайте аккаунт в AWS

2. Войдите в консоль и откройте панель управления AWS IoT. Для этого кликните по кнопке Services в левом верхнем углу, а затем на AWS IoT



3. Нажмите на кнопку Get Started

4. Кликните на Create a Resource, а затем – на Create a thing




5. Введите название для «вещи» (т.е. «thing»). В моем случае это «temperature»

6. Кликните на Create, чтобы завершить создание «вещи», а затем на View thing, чтобы посмотреть информацию о созданной «вещи»

7. Кликните на Connect a device

8. Выберите пункт Node JS и кликните на Generate certificate and policy

9. Вы получите ссылки на три файла. Загрузите их, позже они нам понадобятся. Затем кликните на Confirm & start connecting

10. Теперь загрузите «AWS IoT Node.js SDK» и кликните на Return to Thing Detail

Настройка AWS IoT завершена. Переходим к следующему шагу.

Настройка Beaglebone Green

Подключите BBG к ПК через кабель MicroUSB и дайте BBG получить доступ к интернету. Если вы первый раз используете BBB/BBG, то ознакомительную статью можно прочесть тут.

Подключите Grove-модули к BBG как показано на картинке ниже:

Настройка ПО

Загрузка SDK и файлов ключей в Cloud9

Помните о трех файлах ключей и SDK, которые мы загрузили выше? Теперь они нам пригодятся.

Загрузите SDK и файлы ключей в папку «examples» Cloud9.


Установка SDK и ключей (сертификатов)

Теперь нам нужно распаковать SDK и переместить файлы ключей (сертификатов) в нужное место. Кликаем в Cloud9 на Window > New Terminal:

Переходим в папку «examples»:

# cd examples

Распаковываем архив с SDK:

# unzip aws-iot-device-sdk-js-latest.zip

Переходим в распакованную папку:

#cd aws-iot-device-sdk-js

Устанавливаем зависимые пакеты:

# npm install

Создаем новую папку под названием «awsCerts»:

# mkdir awsCerts && cd awsCerts

Перемещаем в эту папку три файла ключей (обратите внимание, что «31f2fd2680» нужно заменить на номер своего сертификата):

# mv ../../31f2fd2680-* .

Переименуйте файлы ключей:

# mv 31f2fd2680-certificate.pem.crt.txt  certificate.pem.crt
# mv 31f2fd2680-private.pem.key   private.pem.key

Загрузите файл из интернета:

# wget https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem

Переименуйте загруженный файл на «root-CA.crt»:

#mv VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem root-CA.crt

Запись прошивки на BBG

Войдите в папку «examples»:

# cd .. && cd examples/

Создайте новый файл под названием «grove_temperature_sensor.py»:

# vim grove_temperature_sensor.py

Скопируйте в этот файл следующий код:

#!/usr/bin/python
# -*- coding: utf-8 -*-
 
import time
import math
import Adafruit_BBIO.GPIO as GPIO
from Adafruit_I2C import Adafruit_I2C
BUZZER = "P9_22"            # GPIO P9_22
GPIO.setup(BUZZER, GPIO.OUT)
 
# Температурный порог для включения зуммера – 28 градусов:
THRESHOLD_TEMPERATURE = 28
ADDR_ADC121 = 0x50
 
REG_ADDR_RESULT = 0x00
REG_ADDR_ALERT = 0x01
REG_ADDR_CONFIG = 0x02
REG_ADDR_LIMITL = 0x03
REG_ADDR_LIMITH = 0x04
REG_ADDR_HYST = 0x05
REG_ADDR_CONVL = 0x06
REG_ADDR_CONVH = 0x07
 
i2c = Adafruit_I2C(ADDR_ADC121)           
 
class I2cAdc:
    def __init__(self):
        i2c.write8(REG_ADDR_CONFIG, 0x20)
 
    def read_adc(self):
        # считываем АЦП-данные (0-4095):
        "Read ADC data 0-4095." 
        data_list = i2c.readList(REG_ADDR_RESULT, 2)
        #print 'data list', data_list
        data = ((data_list[0] & 0x0f) << 8 | data_list[1]) & 0xfff
        return data
adc = I2cAdc()
 
#  Аргумент в функции read_temperature() определяет,
#  какую версию (температурного) Grove-модуля вы подключили.
#  По умолчанию стоит 'v1.2':
#       temp = read_temperature('v1.0')          # значение «B» = 3975
#       temp = read_temperature('v1.1')          # значение «B» = 4250
#       temp = read_temperature('v1.2')          # значение «B» = 4250
def read_temperature(model = 'v1.2'):
    #  «Считывание температуры (в Цельсиях) с температурного датчика»:
    "Read temperature values in Celsius from Grove Temperature Sensor"
    #  Разные версии датчика используют разные термисторы,
    #  и у каждого – собственное значение константы «B»:
    if model == 'v1.2':
        #  Неизвестно, какой термистор использует датчик v1.2.
        #  Пока Seeed Studio не уточнит этот вопрос, 
        #  предполагается, что это NCP18WF104F03RC:
        bValue = 4250
    elif model == 'v1.1':
        #  Датчик v1.1 использует термистор NCP18WF104F03RC:
        bValue = 4250
    else:
        #  Датчик v1.0 использует термистор TTC3A103*39H:
        bValue = 3975
 
    total_value = 0
    for index in range(20):
        sensor_value = adc.read_adc()
        total_value += sensor_value
        time.sleep(0.05)
    average_value = float(total_value / 20)
 
    # Трансформируем АЦП-данные в данные платформы Arduino:
    sensor_value_tmp = (float)(average_value / 4095 * 2.95 * 2 / 3.3 * 1023)
    resistance = (float)(1023 - sensor_value_tmp) * 10000 / sensor_value_tmp
    temperature = round((float)(1 / (math.log(resistance / 10000) / bValue + 1 / 298.15) - 273.15), 2)
    return temperature
 
# Функция: Если температурный датчик определит температуру,
# которая превышает заданный порог, это активирует зуммер,
# который будет издавать звук в течение 1 секунды.
#
# Устройства: 
# * Grove-модуль с АЦП (шина I2C)
# * Grove-модуль с температурным датчиком
# * Grove-модуль с зуммером
#
# Примечание: В качестве GPIO-контакта используйте P9_22(UART2_RXD)
#
# Подключите Grove-модуль с АЦП (I2C) к Grove-порту (I2C) BBG.
# Подключите Grove-модуль с температурным датчиком
# к Grove-модулю с АЦП (I2C).

if __name__ == '__main__':
 
    while True:
        try:
            # Считываем градусы Цельсия с температурного датчика:
            temperature = read_temperature('v1.2')
 
            # Когда температура достигает заданного значения,
            # активируем зуммер:
            if temperature > THRESHOLD_TEMPERATURE:
                # Отправляем HIGH, чтобы включить зуммер:
                GPIO.output(BUZZER, GPIO.HIGH)
            else:
                # Отправляем LOW, чтобы выключить зуммер:
                GPIO.output(BUZZER, GPIO.LOW)
 
            print "temperature = ", temperature
 
        except KeyboardInterrupt:
            GPIO.output(BUZZER, GPIO.LOW)
            break
 
        except IOError:
            print "Error"

Создайте новый файл под названием «python_sensor.py»:

#vim  python_sensor.py

Скопируйте в этот файл код ниже:

import socket
import grove_temperature_sensor
if __name__ == "__main__":
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect(('127.0.0.1', 7000))
 
    while True:
        temperature = grove_temperature_sensor.read_temperature('v1.2')
    print temperature
        client.sendall(str('%.2f'%temperature))
    data = client.recv(1024)
    print data
    client.close()
 
    print 'Received', repr(data)

Создайте новый файл под названием «rgbled.js»:

#vim rgbled.js

Скопируйте в него следующий код:

var exec = require('child_process').exec; 
var value = 0;
 
exports.initpins = function(){
    exec("echo 3 > /sys/class/gpio/export",function(error,stdout,stderr){
        if(error) 
                console.info('stderr : '+stderr);
    });
    exec("echo out > /sys/class/gpio/gpio3/direction",function(error,stdout,stderr){
                if(error) 
                        console.info('stderr : '+stderr);
        });
 
    exec("echo 2 > /sys/class/gpio/export",function(error,stdout,stderr){
                if(error) 
                        console.info('stderr : '+stderr);
        });
 
    exec("echo out > /sys/class/gpio/gpio2/direction",function(error,stdout,stderr){
                if(error) 
                        console.info('stderr : '+stderr);
        });
 
}
digitalwrite = function(pin,state){
    exec("echo "+state.toString()+" > /sys/class/gpio/gpio"+pin.toString()+"/value",
        function(error,stdout,stderr){
                    if(error) 
                            console.log('stderr : '+stderr);
        });
 
}
sleep = function(sleepTime) {
    for(var start = +new Date; +new Date - start <= sleepTime; ) { }
}
clk = function(){
        digitalwrite(2,0);
        sleep(2);
                digitalwrite(2,1);
        sleep(2);
}
sendByte = function(b){
    for(var i = 0 ; i < 8 ;i++){
        if((b & 0x80) != 0)
            digitalwrite(3,1);
        else
            digitalwrite(3,0);
        clk();
        b = b << 1; 
    }
}
setColor = function(red,green,blue){
    var prefix = 0xc0;
    if((blue & 0x80) == 0)
        prefix |= 0x20;
    if((blue & 0x40) == 0)
        prefix |= 0x10;
    if((green & 0x80) == 0)
        prefix |= 0x08;
    if((green & 0x40) == 0)
        prefix |= 0x04;
    if((red & 0x80) == 0)
        prefix |= 0x02;
    if((red & 0x40) == 0)
        prefix |= 0x01;
    sendByte(prefix);
    sendByte(blue);
    sendByte(green);
    sendByte(red);
}
exports.setColorRGB = function(led,red,green,blue){
    sendByte(0x00);
    sendByte(0x00);
    sendByte(0x00);
    sendByte(0x00);
    for(var i = 0; i < led; i++ ){
        setColor(red,green,blue);
    }
    sendByte(0x00);
    sendByte(0x00);
    sendByte(0x00);
    sendByte(0x00);
    console.log("set rgb");
}
test = function(){
    initpins();
    while(1){
    console.log("loop");
        setColorRGB(1, 255, 0, 0)
        setColorRGB(1, 0, 255, 0)
        setColorRGB(1, 0, 0, 255)
        setColorRGB(1, 0, 255, 255)
        setColorRGB(1, 255, 0, 255)
        setColorRGB(1, 255, 255, 0)
        setColorRGB(1, 255, 255, 255)
    }
}

Создайте новый файл под названием «shadow.js»:

#vim shadow.js

Вставьте туда следующий код:

var awsIot = require('..');
var net = require('net');
var rgbled = require('./rgbled.js');
var exec = require('child_process').exec;    
var myThingName = 'temperature';
var thingShadows = awsIot.thingShadow({
   keyPath: '/var/lib/cloud9/examples/aws-iot-device-sdk-js/awsCerts/private.pem.key',
  certPath: '/var/lib/cloud9/examples/aws-iot-device-sdk-js/awsCerts/certificate.pem.crt',
    caPath: '/var/lib/cloud9/examples/aws-iot-device-sdk-js/awsCerts/root-CA.crt',
  clientId: 'myAwsClientId',
    region: 'us-west-2'
});
var HOST = '127.0.0.1';
var PORT = 7000;
var temperature = 25;
var red = 0;
var green = 0;
var blue = 0;

//  создаем экземпляр класса для сервера
//  и привязываем к нему прослушивающую функцию:
net.createServer(function(socket) {
    console.log('CONNECTED: ' + socket.remoteAddress +':'+ socket.remotePort);
    //  добавляем экземпляру класса для гнезда
    //  обработчик событий «DATA»:
    socket.on('data', function(data) {
        console.log('DATA ' + socket.remoteAddress + ': ' + data);
        temperature = data.toString().substr(0,5);
        socket.write('This is your request: "' + data + '"');
                 //  "Это ваш запрос: " 
    });
    //  добавляем экземпляру класса для гнезда
    //  обработчик события «close»:
    socket.on('close', function(data) {
        console.log('Socket connection closed... ');
                //  "Соединение с гнездом закрыто... "
    });
}).listen(PORT, HOST);
//
//  Состояние тени вещи (т.е. состояние 
//  виртуальной репрезентации устройства).
//  «Тень» (shadow) в терминологии AWS –
//  это виртуальная репрезентация, а «вещь» (thing) – это устройство.
//
var rgbLedLampState = {"state":{"desired":{"red":187,"green":114,"blue":222,value:25}}};
 
//
// Токен клиента, возвращенный функцией thingShadows.update()
//
var clientTokenUpdate;
 
thingShadows.on('connect', function() {
//
// Подключившись к платформе AWS IoT, регистрируем интерес в тени вещи 
// под названием «RGBLedLamp». «Зарегистрировать интерес» - это значит
// подписать класс thingShadows на все доступные топики, а также 
// скомандовать ему запускать события для myThingName, 
// пока не будет вызвана функция unregister().
//
    thingShadows.register( myThingName );
//
// Спустя 2 секунды после регистрации обновляем тень вещи 'RGBLedLamp'
// новыми данными и сохраняем clientToken, чтобы его можно было 
// соотнести с событиями таймаута и статуса.
//
// Обратите внимание, что для последующих апдейтов задержка не нужна.
// Задержка нужна только для первого апдейта после регистрации
// интереса, которая использует параметры по умолчанию. 
// Более подробно об апдейте читайте в документации к API.
//
    exec('python python_sensor.py',function(error,stdout,stderr){
            if(stdout.length >1){
                console.log('you offer args:',stdout);
            }else {
                console.log('you don\'t offer args');
            }
            if(error) {
                console.info('stderr : '+stderr);
            }});
    rgbled.initpins();
    setTimeout( function() {
       clientTokenUpdate = thingShadows.update(myThingName, rgbLedLampState );
       }, 2000 );
    });
setInterval(function(){
        new_data = {"state":{"desired":{"red":187,"green":114,"blue":222,value:temperature.toString()}}};
        //new_data = {"state":{"desired":{"value":temperature.toString()}}};
        console.log(new_data);
       clientTokenUpdate = thingShadows.update(myThingName, new_data )
},2000);
thingShadows.on('status', 
    function(thingName, stat, clientToken, stateObject) {
       console.log('received '+stat+' on '+thingName+': '+
                   JSON.stringify(stateObject));
    });
 
thingShadows.on('delta', 
    function(thingName, stateObject) {
       console.log('received delta '+' on '+thingName+': '+
                   JSON.stringify(stateObject));
        //console.log(stateObject["state"]);
    if(stateObject["state"]["red"]      != red ||
       stateObject["state"]["green"]  != green||
      stateObject["state"]["blue"]    != blue)
            rgbled.setColorRGB(1,stateObject["state"]["red"],
                        stateObject["state"]["green"],
                        stateObject["state"]["blue"]);
 
    red = stateObject["state"]["red"];
    green = stateObject["state"]["green"];
    blue = stateObject["state"]["blue"];
    });
 
thingShadows.on('timeout',
    function(thingName, clientToken) {
       console.log('received timeout '+' on '+thingName+': '+
                   clientToken);
    });

Обратите внимание, что myThingName в 5-ой строчке нужно поменять на название своей вещи, которую вы создали ранее в аккаунте AWS.

Запуск кода

Перезагрузив BBG, запускаем код:

# cd examples/aws-iot-device-sdk-js/examples/
# node shadow.js

Просмотр результата

Открываем страницу AWS IoT и заходим в аккаунт. Кликаем на вещь, которую мы создали несколько минут назад. Вы должны увидеть, как на сайт загружаются данные о температуре:

Здесь также можно изменить цвет RGB-светодиода. Для этого измените значения в коде, который находится справа, в поле «Shadow state»:

Как видите, BBG получила новое значение для RGB-светодиода...

...а сам RGB-светодиод загорелся зеленым цветом:

Более подробно об AWS IoT читайте в ознакомительном руководстве AWS IoT.

Решение проблем

Проблема 1: Не могу открыть IP-адрес «192.168.7.2».

Чтобы исправить эту проблему, нужно установить последнюю версию прошивки. Для этого нужно сделать следующее:

Шаг 1. Загрузите образ с последней версией

Сделать это можно отсюда.

Шаг 2: Установите утилиту-архиватор

Загрузите и установите 7-zip.

Шаг 3: Разверните образ

При помощи 7-zip разверните файл «*.img» на рабочий стол или в другую папку.

Шаг 4: Установите утилиту для записи прошивки на SD-карту

Загрузите и установите Image Writer (Windows). Убедитесь, что загружаете двоичную версию.

Шаг 5: Подключите SD-карту к компьютеру

Для этого воспользуйтесь SD-адаптером или USB-адаптером. Потребуется карта MicroSD объемом не менее 8 Гб.

Шаг 6: Запишите образ на SD-карту

Запишите развернутый образ на SD-карту, подключенную к компьютеру.

Примечания:

  • Может появиться предупреждение о возможном повреждении устройства. Пока вы используете SD-карту для записи, его можно проигнорировать
  • Плату BeagleBone к компьютеру подключать не нужно

Шаг 7: Вытащите SD-карту

Отключите запрограммированную SD-карту от компьютера.

Шаг 8: Загрузите в плату прошивку с SD-карты

Вставьте SD-карту в (выключенную) плату, а затем подключите к ней питание – либо через USB-кабель, либо через 5-вольтовый адаптер. Если запись прошивки началась, у платы начнет мигать светодиод flash-памяти, и эта перезагрузка займет до 10 минут. Записав прошивку, флэшер Debian автоматически выключит плату. Теперь отключите питание от платы, выньте SD-карту и снова подключите к ней питание.

Техническая поддержка

Если у вас возникнут какие-то проблемы, обратитесь на форум.

Прошивка

Последняя версия – от 15.11.2015

  • Исправляет проблему с невозможностью открыть IP-адрес «192.168.7.2»
  • Добавлена поддержка Windows 10

Полезные ссылки

См.также

Внешние ссылки