Project tutorial

Voice Activated Media Appliances Using Arduino and Alexa © GPL3+

The unit developed here makes your appliances like TV, amplifier, CD and DVD players control with voice commands using Alexa and Arduino.

  • 1,498 views
  • 0 comments
  • 11 respects

Components and supplies

Apps and online services

About this project

The unit developed here makes your appliances like TV, amplifier, CD and DVD players control with voice commands using Alexa and Arduino. Advantage of this unit is that you have to just give voice commands. This unit can work with all appliances that uses RS-232 port ports. These ports are very much useful in connections. They are mostly used in media devices. Now, no need to use IR remotes.

The unit is inexpensive. It contains, Arduino Board. You can use any arduino board but i prefer Arduino Nano because it is compact. The other things are ESP 8266, Amazon Alexa, RS 232-TTL Converter. I have also included instructions for Particle.

Connecting Arduino to ESP 8266:

Connect the Arduino’s 3v3 (3.3V) output to ESP8266. The ESP8266 works with 3.3V and not 5V, so this is necessary.

Connect the RES or RESET pin, When you ground the reset pin, the Arduino works as a dumb USB to serial connector, which is what we want to talk to the ESP8266.

Connect the RXD pin of the Arduino to the RX pin of the ESP8266.

Connect the TXD pin of the Arduino to the TX pin of the ESP. When we want two things to talk to each other over serial, we connect the TX pin of one to the RX of the other (send goes to receive and the opposite). Here we do not have the Arduino talk to the ESP8266 though, our computer is talking to it viathe Arduino.

Connect GND and VCC.

Finally CH_PD connects.

Connecting RS 232-TTL Converter

Now, it is easy to connect RS 232-TTL converter to Arduino and ESP which we connected earlier as connections mentioned below:

Connect GND of Arduino/Particle to GND of converter

Connect VCC of Arduino/Particle to VCC of converter

Connect TX of Arduino/Particle to TX of converter

Connect RX of Arduino/Particle to RX of converter

And if you are using Particle, then follow this:

Creating Alexa Skills

You need a developer account with Amazon, if you don't have one you can sign for free. Go to https://developer.amazon.com/alexa

In developer account go to Alexa skills kit.

Then click "Create a new skill"

You have to select followings:

"Smart Home Skill API" in Skill Type

In payload version, select v3

And then click Save.

Once saving, next step shows you your Application ID.

Click next button

Then comes the configuration window.

Here you have to use curl command where in user ID place the access token and in www.example.com you need to give particle website.

curl -v -k https://example.com/endpoint --data-binary '{
"version" : "string",
"session" : {
"new" : boolean,
"sessionId" : "string",
"attributes" : {
"string" : object
},
"user" : {
"userId" : "string"
}
},
"request" : object
}
}'

Configuration:

For this you have to login to https://aws.amazon.com/.

Select Author form Scratch option.

Then, copy the code below:

var https = require('https');var serialPortControllerId = "SAKA_Krell_10102017";var serialPortEchoId = "SAKA_Krell_Echo_10102017"var particleServer = "api.particle.io";var particlePath = "/v1/devices/";var particleId = "put_here_your_particle_device_id";var powerOn = "1PWRZ";var powerOff = "0PWRZ";var volumeUp = "V10UZ"; //up by 10var volumeDown = "V10DZ"; //down by 10var setVolumeToXXXLevel = "MVLZ"; //append in front volume level xxxMVLZvar muteEnable = "MUTZ";var muteDisable = "UMTZ";var selectInput1 = "SS1MZ";var selectInput2 = "SS2MZ";var selectInput3 = "SS3MZ";exports.handler = function(event, context) {    log('Input', event);    switch (event.directive.header.namespace) {        /**    * The namespace of "Discovery" indicates a request is being made to the lambda for    * discovering all appliances associated with the customer's appliance cloud account.    * can use the accessToken that is made available as part of the payload to determine    * the customer.    */    case 'Alexa.Discovery':        handleDiscovery(event, context);        break;    case 'Alexa.PowerController':        handleControl(event, context);        break;    case 'Alexa.Speaker':        handleControl(event, context);        break;    case 'Alexa.InputController':        handleControl(event, context);        break;    case 'Alexa.ChannelController':        handleControl(event, context);        break;    default:        log('Err', 'No supported namespace: ' + event.directive.header.namespace);        context.fail('Something went wrong');        break;    }};/*** This method is invoked when we receive a "Discovery" message from Alexa Connected Home Skill.* We are expected to respond back with a list of appliances that we have discovered for a given* customer. */function handleDiscovery(event, context) {    var payload = {        "endpoints":[            {            "endpointId": serialPortControllerId,            "friendlyName": "Stereo",            "description": "Serial port controller for Krell amplifier S-300i",            "manufacturerName": "SAKA",            "displayCategories": ["OTHER"],            "cookie": {                "deviceId" : particleId                },            "capabilities": [            {                "type": "AlexaInterface",                "interface": "Alexa.Speaker",                "version": "1.0",                "properties":{                     "supported": [                        {                            "name": "volume"                        },                        {                            "name": "muted"                        }                    ]                }            },            {                "type": "AlexaInterface",                "interface": "Alexa.PowerController",                "version": "1.0",                "properties": {                    "supported" : [                        {                            "name": "powerState"                        }                    ]                }            },            {                "type": "AlexaInterface",                "interface": "Alexa.InputController",                "version": "1.0",                "properties": {                    "supported": [                        {                            "name": "input"                        }                    ]                }            },            {                "type": "AlexaInterface",                "interface": "Alexa.ChannelController",                "version": "1.0",                "properties": {                "supported": [                        {                            "name": "channel"                        }                    ]                }            }        ]},    ]};    /**    * Craft the final response back to Alexa Connected Home Skill. This will include all the     * discoverd appliances.    */    var header = event.directive.header;    header.name = "Discover.Response";    context.succeed({ event: {    header: header, payload: payload    } });    //log('Discovery', result);}/** * Control events are processed here. * This is called when Alexa requests an action (IE turn off appliance). */function handleControl(event, context) {    var namespace = event.directive.header.namespace;    var messageId = event.directive.header.messageId;    var correlationToken = event.directive.header.correlationToken;    var accessToken = event.directive.endpoint.scope.token;    var endpointId = event.directive.endpoint.endpointId;    var deviceId = event.directive.endpoint.cookie.deviceId;    var name = "";    var value = "";    var UTCDate = new Date();    var jsonDate = JSON.stringify(UTCDate);    var strDate = JSON.parse(jsonDate);     var funcName = "KrellSerial";    if ((namespace === "Alexa.PowerController") ||         (namespace === "Alexa.Speaker") ||        (namespace === "Alexa.InputController") ||        (namespace === "Alexa.ChannelController")){        var param = "";        var index = "0";        var executeParticle = true;        if (namespace === "Alexa.PowerController") {            if(event.directive.header.name == "TurnOn"){                krellSerialCommand = powerOn;                name = "powerState";                value = "ON";            }            else if(event.directive.header.name == "TurnOff"){                krellSerialCommand = powerOff;                name = "powerState";                value = "OFF";            }        }        else if (namespace === "Alexa.Speaker") {            if(event.directive.header.name == "SetVolume"){                value = event.directive.payload.volume;                krellSerialCommand = pad(value, 3) + setVolumeToXXXLevel;                name = "volume";            }            else if(event.directive.header.name == "SetMute"){                var mute = event.directive.payload.mute;                if (mute) {                    krellSerialCommand = muteEnable;                    value = true;}                else if (!mute) {                    krellSerialCommand = muteDisable;                    value = false;}                name = "muted";            }            else if(event.directive.header.name == "AdjustVolume"){                var volume = event.directive.payload.volume;                if (volume >= 0) {                    krellSerialCommand = volumeUp;                    value = 10;}                else if (volume << 0) {                    krellSerialCommand = volumeDown;                    value = -10;}                name = "volume";            }        }        else if (namespace === "Alexa.InputController") {            if(event.directive.header.name == "SelectInput"){                var inputNumber = event.directive.payload.input;                if (inputNumber == "1")                     {                        krellSerialCommand = selectInput1;                    }                else if (inputNumber == "2")                    {                        krellSerialCommand = selectInput2;                    }                else if (inputNumber == "3")                    {                        krellSerialCommand = selectInput3;                    }                else {                    krellSerialCommand = inputNumber;                    executeParticle = false;                    context.succeed(generateControlError(event, 'INVALID_VALUE', 'Input name or number not recognized'));                    }                name = "input";            }        }        else if (namespace === "Alexa.ChannelController") {            if(event.directive.header.name == "ChangeChannel"){                var channelNumber = event.directive.payload.channel.number;                value = event.directive.payload.channel;                if (channelNumber == "1")                     {                        krellSerialCommand = selectInput1;                    }                else if (channelNumber == "2")                    {                        krellSerialCommand = selectInput2;                    }                else if (channelNumber == "3")                    {                        krellSerialCommand = selectInput3;                    }                else {                    krellSerialCommand = channelNumber;                    executeParticle = false;                    context.succeed(generateControlError(event, 'INVALID_VALUE', 'Input name or number not recognized'));                    }                name = "channel";            }        }        if(deviceId == particleId){            index = "0";        }        param = krellSerialCommand;        var options = {            hostname: particleServer,            port: 443,            path: particlePath + deviceId + "/" + funcName,            method: 'POST',            headers: {                'Content-Type': 'application/x-www-form-urlencoded'            }        };        log(options);        var data = "access_token=" + accessToken + "&" + "args=" + param;        log(data);        var serverError = function (e) {            log('Error', e.message);            context.fail(generateControlError(event, 'ENDPOINT_UNREACHABLE', 'Unable to connect to server'));        };        if (executeParticle) {            var callback = function(response) {                var str = '';                response.on('data', function(chunk) {                    str += chunk.toString('utf-8');                });                response.on('end', function() {                log('Return Value');                log(str);                var result = {                    "context": {                        "properties": [ {                        "namespace": namespace,                            "name": name,                            "value": value,                            "timeOfSample": strDate,                            "uncertaintyInMilliseconds": 500                            } ]                        },                        "event": {                            "header": {                                "namespace": "Alexa",                                "name": "Response",                                "payloadVersion": "3",                                "messageId": messageId,                                "correlationToken": correlationToken                            },                            "endpoint": {                                "scope": {                                    "type": "BearerToken",                                    "token": accessToken                                },                            "endpointId": endpointId                            },                            "payload": {}                            }                        };                    context.succeed(result);                });                response.on('error', serverError);            };            var req = https.request(options, callback);            req.on('error', serverError);            req.write(data);            req.end();        }    }}/** * Utility functions. */function log(title, msg) {    console.log(title + ": " + msg);}function generateControlError(event, code, description) {    var messageId = event.directive.header.messageId;    var correlationToken = event.directive.header.correlationToken;    var accessToken = event.directive.endpoint.scope.token;    var endpointId = event.directive.endpoint.endpointId;    var response = {        "header": {            "namespace": "Alexa",            "name": "ErrorResponse",            "messageId": messageId,            "correlationToken": correlationToken,            "payloadVersion": "3"            },            "endpoint":{                "scope":{                    "type":"BearerToken",                    "token":accessToken                },                "endpointId":endpointId            },            "payload": {                "type": code,                "message": description            }        };    var result = { event : {response}};    return result;}//Function to format the volume with leading zerosfunction pad(num, size) {    var s = "000" + num;    return s.substr(s.length-size);} 

Set your Device ID in your program.

You need to change the commands to your specific device.

After doing all the steps, test the skills in Lambda Configuration.

For Arduino:

Connect to wifi using the following code given in code section.

Then, run the WEMO server, it is the best method for ESP8266.

Now, we have to install the ESPAsyncTCP library.

The testing code is provided in code section. Here it can listen to voice commands which are given to Amazon Echo Dot.

Try saying "Alexa Turn on TV"

Note: You have to first provide IR code for simple turning on Tv to Arduino!

Thus, in this way you can make your own voice controlling unit using Arduino or Particle.

Code

Example Code for Serial Connections of ArduinoC/C++
void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(57600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }


  Serial.println("Goodnight moon!");

  // set the data rate for the SoftwareSerial port
  mySerial.begin(4800);
  mySerial.println("Hello, world?");
}

void loop() { // run over and over
  if (mySerial.available()) {
    Serial.write(mySerial.read());
  }
  if (Serial.available()) {
    mySerial.write(Serial.read());
  }
}
Connecting to WifiC/C++
#include "debug.h"              // Serial debugger printing
#include "WifiConnection.h"     // Wifi connection // this file is part of my tutorial code
#include <IRremoteESP8266.h>    // IR library 


WifiConnection* wifi;           // wifi connection
IRsend* irSend;                 // infrared sender


//SET YOUR WIFI CREDS 
const char* myWifiSsid = "***";
const char* myWifiPassword = "*******";

//SET TO MATCH YOUR HARDWARE 
#define SERIAL_BAUD_RATE    9600

//PIN 0 is D3 ON THE CHIP 
#define IR_PIN              0



/*---------------------------------------*/
//Runs once, when device is powered on or code has just been flashed 
void setup()
{
    //if set wrong, your serial debugger will not be readable 
    Serial.begin(SERIAL_BAUD_RATE);

    //initialize wifi connection 
    wifi = new WifiConnection(myWifiSsid, myWifiPassword);
    wifi->begin();

    //connect to wifi 
    if (wifi->connect())
    {
        debugPrint("Wifi Connected");
    }
}


/*---------------------------------------*/
//Runs constantly 
void loop()
{
}
Code for testingC/C++
#include "debug.h"              // Serial debugger printing
#include "WifiConnection.h"     // Wifi connection 
#include "Wemulator.h"          // Our Wemo emulator 
#include <IRremoteESP8266.h>    // IR library 


WifiConnection* wifi;           // wifi connection
Wemulator* wemulator;           // wemo emulator
IRsend* irSend;                 // infrared sender


//SET YOUR WIFI CREDS 
const char* myWifiSsid = "***";
const char* myWifiPassword = "*******";

//SET TO MATCH YOUR HARDWARE 
#define SERIAL_BAUD_RATE    9600

//PIN 0 is D3 ON THE CHIP 
#define IR_PIN              0
    
    
/*---------------------------------------*/
//Runs once, when device is powered on or code has just been flashed 
void setup()
{
    //if set wrong, your serial debugger will not be readable 
    Serial.begin(SERIAL_BAUD_RATE);

    //initialize wifi connection 
    wifi = new WifiConnection(myWifiSsid, myWifiPassword);
    wifi->begin();

    //initialize the IR 
    irSend = new IRsend(IR_PIN, false);
    irSend->begin();

    //initialize wemo emulator 
    wemulator = new Wemulator();

    //connect to wifi 
    if (wifi->connect())
    {
        wemulator->begin(); 

        //start the wemo emulator (it runs as a series of webservers) 
        wemulator->addDevice("tv", new WemoCallbackHandler(&commandReceived));
        wemulator->addDevice("television", new WemoCallbackHandler(&commandReceived));
        wemulator->addDevice("my tv", new WemoCallbackHandler(&commandReceived));
        wemulator->addDevice("my television", new WemoCallbackHandler(&commandReceived));
    }
}


/*---------------------------------------*/
//Runs constantly 
void loop()
{
    //let the wemulator listen for voice commands 
    if (wifi->isConnected)
    {
        wemulator->listen();
    }
}

Schematics

Connecting Arduino to esp8266
Uno esp connection ho79gxjivx yqsivepodd

Comments

Similar projects you might like

Arduino Uno-Based, Easy-to-Build Pet Feeder

Project tutorial by edr1924

  • 1,357 views
  • 2 comments
  • 15 respects

HOW PIR SENSOR WORK

Project tutorial by DIY Partners

  • 1,997 views
  • 6 comments
  • 19 respects

4-Stroke Digital Clock With Arduino

Project tutorial by LAGSILVA

  • 7,176 views
  • 8 comments
  • 30 respects

Dead Bug Valentine

Project tutorial by wrightmac

  • 944 views
  • 0 comments
  • 7 respects

Low Cost Accurate 3D Positioning

Project tutorial by Sumit Aich

  • 4,452 views
  • 5 comments
  • 7 respects
Add projectSign up / Login