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.
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 SkillsYou 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.
Comments