«То, что вы узнаете сегодня, может изменить будущее»

В настоящее время все больше и больше устройств могут управляться голосом с помощью таких сервисов, как Google Home и Amazon Alexa. Я решил набрать обороты, пройдя курс Alexa в codecademy и добавив голосовое управление в свой Infiniti G35 2006 года, казалось, это хороший способ проверить то, что я узнал. В этом руководстве мы припаяем пульт к вашему автомобилю, чтобы возможности управления ограничились возможностями пульта (на данный момент). Для выполнения этого проекта вам потребуется некоторый опыт работы с паяльником, Raspberry Pi (RPi), Amazon Alexa, AWS Lambda, Javascript / NodeJS / NodePackageManager и базовое понимание электрических цепей или готовность учиться на ходу. . Я сам все еще новичок и уверен, что есть лучший / более понятный способ сделать это, поэтому любые отзывы приветствуются.

Вот что вы можете ожидать, когда сделаете это

А теперь приступим :)

Хорошо, обо всем по порядку, вот что вам понадобится:

Пусть вас не перегрузит количество необходимых материалов. Звучит много, но некоторые предметы можно приобрести вместе в виде пакета, и они будут доставлены в избытке, поэтому они пригодятся для будущих проектов.

Часть 0: программирование дополнительного автомобильного пульта ДУ

Прежде чем мы зайдем слишком далеко, убедитесь, что вы можете запрограммировать запасной пульт дистанционного управления на свой автомобиль. Если ваш автомобиль является самопрограммируемым (как и мой), вы можете перейти по этой ссылке или для так называемого программирования ключей по этой ссылке. Если ваш автомобиль НЕ является самопрограммируемым, вы можете найти слесаря или обратиться к вашему дилеру.

Часть 1: настройка Alexa на Raspberry PI

Подключите динамик к Raspberry PI и убедитесь, что он работает (например, воспроизведите случайное видео на YouTube). После этого следуйте этому или этому руководству, чтобы установить клиент Alexa на свой Pi. Скорее всего, по пути вы столкнетесь с известной проблемой неверного запроса, и вот вы можете ее исправить. Если вы все сделали правильно, вы должны услышать приветствие от Алексы. На этом похлопайте себя по плечу и переходите ко 2 части :)

Часть 2: настройка микрофона

Если вы выбрали PS Eye, вам сначала нужно установить пакет motion, набрав

sudo apt-get install motion

в терминале, как описано в этой отличной статье.

Когда закончите, введите

arecord -l

Вы должны увидеть свое устройство в списке CAPTURE Hardware Devices.

Это означает, что USB-микрофон / камера подключены к «карте 1», «устройству 0». Теперь продолжайте и попробуйте что-нибудь записать, набрав

arecord --device=hw:1,0 --format S16_LE --rate 44100 -c1 test.wav

а затем воспроизведите его, набрав

aplay --device=plughw:1,0 test.wav

Если вы смогли услышать свою запись, немного поиграйте с Alexa и переходите к части 3, в противном случае проверьте это и / или это для устранения неполадок.

Часть 3. Собираем схему

На данный момент у вас уже должен быть работающий сервис Alexa на вашем Raspberry Pi и вы готовы поговорить о некоторых схемах. Это, наверное, самая сложная и трудоемкая часть, поэтому терпение - ключ к успеху :)

Заявление об ограничении ответственности: я ни в коем случае не являюсь экспертом в области построения схем. Большую часть материала, необходимого для этого проекта, я изучил в процессе, так что если вы похожи на меня, мы находимся в одной лодке :) Должен признать, что в процессе обучения я сжег 2 светодиода и 1 транзистор. Пусть текущий поток течет вместе с ними.

Чтобы отправлять команды в машину, нам нужно имитировать нажатие кнопок на пульте дистанционного управления. Здесь в игру вступают транзисторы. Как работают транзисторы NPN, выходит за рамки этого руководства, но если вам интересно узнать, я настоятельно рекомендую это видео. Короче говоря, транзистор будет действовать как переключатель, который открывается, чтобы пропустить ток (как если бы кнопка была нажата), а затем закрывается (кнопка отпускается).

Шаг 3.1: тестирование

Перед тем как приступить к пайке, протестируем транзистор на макете.

Здесь 3,3 В, поступающие от RPi, поступают на коллектор транзистора (короткий красный провод) и через резистор на базу (средний). Анод светодиода (более длинная ножка) подключен к ножке эмиттера, а катод (более короткая ножка) подключен к GND (синий провод). Если вы вытащите резистор, светодиод должен погаснуть, потому что база транзистора не имеет тока, поэтому она закрыта - ток не проходит от коллектора к эмиттеру. Вот карта GPIO для справки (3,3 В = 3 В 3 на схеме)

Шаг 3.2: пайка печатной платы

Обрежьте и зачистите провода. Я выбрал красный для VCC, черный для GND и зеленый для сигналов управления.

Припаяйте разъемы к печатной плате. Они будут использоваться для связи с RPi. Также припаиваем резисторы.

Припаиваем провода

Спаяйте вместе разъемы с резисторами, а затем резисторы с проводами на задней стороне печатной платы.

Я также решил добавить светодиод, чтобы проверить, включена ли плата. Этот шаг не обязателен

С помощью перемычек подключите разъем VCC к 3,3 В GPIO на RPi, а землю - к GND. Если вы припаяли светодиод, как я, он должен загореться. На этом пайка печатной платы завершена, перейдем к пульту дистанционного управления.

Шаг 3.3: автомобильный пульт

Разберите запасной пульт дистанционного управления. Отметьте, какая кнопка что делает (блокировка, разблокировка, багажник и т. Д.)

Теперь распаяйте настоящие кнопки

Припаяйте красный (VCC) и черный (GND) провода, идущие от печатной платы, к пульту дистанционного управления, где раньше была батарея. Теперь у нас должно быть постоянное питание от RPi. Припаяйте транзисторы в места, где раньше были кнопки, подключив ножку коллектора транзистора к VCC, а ножку эмиттера к земле (я использовал мультиметр для определения VCC). Обратите внимание, что это, скорее всего, плохая практика, поскольку транзисторы также должны быть припаяны к печатной плате, но для простоты я сделал это так

Затем припаяйте зеленые провода к основанию резисторов и используйте перемычки для подключения заголовков к контактам GPIO, которые будут отвечать за отправку сигналов на пульт. Я выбрал GPIO 16, 20 и 21 для блокировки, разблокировки и ствола соответственно. Вот снова картография

Не забудьте очистить кожу ватным тампоном и медицинским спиртом. 50%, вероятно, не очень хорошо, так как он содержит больше воды, чем более высокий процент, но на данный момент подойдет

Часть 4: настройка сервера localhost и ngrok

Мы будем запускать локальный сервер NodeJS / Express, который предоставляет конечные точки для связи с Alexa.

Прежде всего, если у вас еще не установлен NodeJS на Raspberry PI, сделайте это. Затем запустите эти команды в терминале на Raspberry PI:

mkdir my-car-server && cd my-car-server
npm init
touch index.js
mkdir routes && cd routes
touch rest.js
cd ..

С этого момента вы можете редактировать код с помощью nano, набрав в терминале

nano index.js

или используйте Geany IDE из меню приложений - ›Программирование -› Geany

Команда npm init должна была создать файл package.json внутри каталога my-car-server. Откройте его и вставьте следующие зависимости:

"dependencies": {
    "express": "^4.16.2",
    "nodemon": "^1.17.1",
    "onoff": "^2.0.0",
  }

затем беги

npm install

это установит вышеуказанные зависимости (эй, капитан, очевидно!)

Вот мое git репо, если хотите взглянуть / клонировать. В противном случае откройте index.js и вставьте:

const express = require('express');
const path = require('path');
const http = require('http');
const bodyParser = require('body-parser');
const port = 4200;
const app = express();
const server = http.createServer(app);
app.locals.title = "Your title";
const rest = require('./routes/rest');
app.use('/rest', rest);
app.set('view engine', 'ejs');
server.listen(port, () => console.log(`listening on ${port}`));
module.exports = app;

Файл index.js теперь содержит все необходимое для запуска локального сервера. Теперь нам нужно создать фактические конечные точки, с которыми может разговаривать Alexa.

Перейдите в каталог routes и откройте rest.js. Вставьте следующее:

const express = require('express');
const router  = express.Router();
const path    = require('path');
const GPIO    = require('onoff').Gpio;

const carLock = new GPIO(16, 'out');
const carUnlock = new GPIO(20, 'out');
const carTrunk = new GPIO(21, 'out');

carLock.writeSync(0);
carUnlock.writeSync(0);
carTrunk.writeSync(0);

router.get('/lock', (req, res, next) => {
	carLock.writeSync(1);
	setTimeout(() => {
		carLock.writeSync(0);
		}, 1000);
	console.log("lock car received");
	res.send(200);
	});
	
	
router.get('/unlock', (req, res, next) => {
	carUnlock.writeSync(1);
	setTimeout(() => {
		carUnlock.writeSync(0);
		}, 1000);
	console.log("unlock car received");
	res.sendStatus(200);
	});	
	

router.get('/trunk', (req, res, next) => {
	carTrunk.writeSync(1);
	setTimeout(() => {
		carTrunk.writeSync(0);
		}, 1000);
	console.log("trunk received");
	res.sendStatus(200);
	});
	
	
router.get('/windows', (req, res, next) => {
	console.log("windows received");
	carUnlock.writeSync(1);
	setTimeout(() => {
		carUnlock.writeSync(0);
		res.sendStatus(200);
		}, 6000);
	
	
	});
	
module.exports = router;

Пульт дистанционного управления моей машины поддерживает

  • Замок
  • Разблокировать
  • Сундук
  • Тревога
  • Windows опущена (удерживайте разблокировку несколько секунд)

Настройте код в соответствии с вашими удаленными возможностями. Чтобы имитировать нажатие кнопки, я установил вывод GPIO на высокий уровень (writeSync (1)) на определенное время (1000, 2000, 6000 мс), а затем на низкий (writeSync (0)).

Это очень простой пример, который не включает никаких мер безопасности. В идеале вам нужно, чтобы Alexa отправляла какой-то токен с каждым запросом в конечную точку. Затем сервер проверяет его и либо выполняет код, либо отправляет обратно статусный код HTTP 401 Unauthorized.

Теперь вернитесь к my-car-server из окна терминала и запустите сервер, набрав

node index.js

Вы должны увидеть сообщение в окне терминала:

listening on 4200

Это замечательно, НО прямо сейчас сервер работает локально, что означает, что он виден только внутри вашей локальной сети. У вас есть 2 варианта (о которых я знаю), чтобы раскрыть его:

  1. Https://ngrok.com/
  2. Https://localtunnel.github.io/www/

Эти службы туннелируют данные извне на созданный вами локальный сервер.

Выберите один и следуйте документации, чтобы установить и запустить его. Я лично предпочитаю ngrok, потому что у меня возникли проблемы с отключением соединения по локальному туннелю. С другой стороны, localtunnel позволяет вам выбирать доменные имена бесплатно, в то время как ngrok генерирует случайные, если вы не платите за подписку (5 долларов в месяц дает вам 3 зарезервированных домена)

Часть 5: настройка функции AWS Lambda

Я предполагаю, что вы прошли курс Amazon Alexa в codecademy, на который я ссылался ранее в статье и который уже в некоторой степени знаком с Lambda. Войдите в консоль AWS, перейдите в Lambda и создайте новую функцию. Выберите Чертежи - ›alexa-skill-kit-sdk-factskill -› и нажмите Настроить.

Заполните основную информацию и выберите существующую роль с именем lambda_basic_execution. Нажмите Создать функцию. Вы должны попасть на экран конфигурации функций. Добавьте триггер, обратите внимание на ARN и убедитесь, что для региона установлено значение Северная Вирджиния (верхний правый угол).

Прокрутите вниз до редактора кода, сотрите весь код и вставьте следующее:

"use strict";
var Alexa = require("alexa-sdk");
var https = require('https');
const myCar = "Infinit G35";
const api = "https://yourdomain.ngrok.io/rest";
var handlers = {
  "LockIntent": function () {
    let alexa_this = this;
    https.get(`${api}/lock`, function(res) {
       res.on('data', (d) => {
      });
        res.on('end', function(res) {
          alexa_this.response.speak("Your car is locked"); 
          alexa_this.emit(':responseReady');
        });
    });
    
    
  },
  "UnlockIntent": function () {
    let alexa_this = this;
    https.get(`${api}/unlock`, res => {
      res.on('data', (d) => {
});
      res.on('end', function(res) {
          alexa_this.response.speak("Your car is unlocked"); 
          alexa_this.emit(':responseReady');
        });
    })
  },
  "TrunkIntent": function () {
    let alexa_this = this;
    https.get(`${api}/trunk`, res => {
      res.on('data', (d) => {
});
      res.on('end', function(res) {
          alexa_this.response.speak("Trunk is open"); 
          alexa_this.emit(':responseReady');
        });
    })
  },
  "WindowsIntent": function () {
    let alexa_this = this;
    https.get(`${api}/windows`, res => {
      res.on('data', (d) => {
});
      res.on('end', function(res) {
          alexa_this.response.speak("Windows down"); 
          alexa_this.emit(':responseReady');
        });
    })
  },
  "LaunchRequest": function () {
    this.response.speak("Hello. You can say lock, unlock or trunk to interact with " + myCar); 
    this.emit(':responseReady');
  }
};
exports.handler = function(event, context, callback){
  var alexa = Alexa.handler(event, context);
    alexa.registerHandlers(handlers);
    alexa.execute();
};

Опять же, код не идеален и служит просто базовым примером. Настройте его в соответствии с вашими потребностями и сохраните.

Часть 6: настройка навыка Alexa

Давайте войдем в Консоль разработчика набора навыков Alexa и создадим новый навык. После того, как вы заполнили основную информацию о навыках, вы должны увидеть экран создания навыков. Продолжайте и добавляйте желаемые намерения. Вот как выглядит мой:

После этого нажмите «Построить модель» и перейдите в подменю конечной точки. Установите переключатель в положение AWS Lambda ARN и вставьте ARN, который вы записали на предыдущем шаге, в поле Default Region:

На этом этапе навык должен быть полностью установлен, но рекомендуется сначала проверить его, поэтому, если сборка готова, перейдите в меню Тест и введите / произнесите некоторые высказывания, которые вы добавили в намерения ранее:

Это оно! Теперь у вас все готово! Молодец товарищ!

Часть 7: тестирование на вашем автомобиле

Вы дошли до последней главы, поздравляю! На этот раз похлопайте себя по плечу обеими руками, и давайте закончим, ладно?

Вы можете либо отправиться в свою машину и проверить его там, либо сначала провести несколько тестов на макетной плате, подключив светодиоды к контактам GPIO (не забудьте вставить резисторы между ними!), Которые мы установили ранее, и проверить, загораются ли они. вверх на основе ваших голосовых команд. Твой выбор :)

Прежде чем отправиться в машину, обязательно настройте точку доступа WIFI на своем телефоне и подключите к нему Raspberry Pi, чтобы он автоматически подключался позже. На данный момент это подойдет, но если вы планируете оставить Alexa в машине, возможно, вы захотите инвестировать в что-то вроде AT&T Velocity. Самый дешевый план включает 2 ГБ данных на 90 дней за 25 долларов, которых должно хватить для взаимодействия с Alexa.

Я использовал блок питания для питания Raspberry PI, но вы также можете включить его от розетки 12 В в машине, если у вас есть адаптер.

Дальнейшее развитие

Я планирую продолжить работу над этим проектом, добавив распознавание лиц и управление другими вещами, такими как кондиционер, радио, освещение и т. Д. В идеале я бы хотел иметь возможность запускать / останавливать машину, но механическая коробка передач, иммобилайзер и блокировка рулевого колеса делают это очень трудно реализовать :( Если у вас есть какие-либо идеи, пожалуйста, поделитесь ими. Кроме того, если у вас есть какие-либо видео / фотографии того, что вы создали на основе этой статьи, я определенно хотел бы их увидеть! Ура!