Guillermo Perez Guillen
Created October 27, 2019 © CC BY-NC-SA

Voice Assistant System for Senior

Three Voice-activated in-home technologies: a) Humidifier, b) Fetch a cane, and c) Smart Home

AdvancedFull instructions provided2 days111

Things used in this project

Hardware components

MATRIX Creator
MATRIX Labs MATRIX Creator
×1
Raspberry Pi 3 Model B
Raspberry Pi 3 Model B
×1
ESP-WROOM-32
×1
Spresense boards (main & extension)
Sony Spresense boards (main & extension)
×1
HC-05 Bluetooth Module
HC-05 Bluetooth Module
×1
Seeed Studio Grove Water Atomization
×1
L293D Driver
×1
Buzzer
Buzzer
×1
PIR Motion Sensor (generic)
PIR Motion Sensor (generic)
×1
Lamp (generic)
×1
5V 2A Battery
×1
LED (generic)
LED (generic)
×1

Software apps and online services

Snips AIR
Snips AIR
JavaScript
Arduino IDE
Arduino IDE
MIT App Inventor 2
MIT App Inventor 2

Hand tools and fabrication machines

Smartphone - Android 9
3D Printer (generic)
3D Printer (generic)
Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Custom parts and enclosures

Humidifier's box

SECTIONS A AND B STL and GCODE files of a humidifier's box project for Living in Motion contest

Schematics

Section A: HUMIDIFIER

Diagram with the electrical connections of the voice controlled humidifier

Section B: FETCH A CANE

Schematic diagram of the system to fetch a cane

Section C: SMART HOME

Electric diagram of the Smart Home

Code

assistant.js

JavaScript
SECTION A: HUMIDIFIER
This file combines all the code from everloop.js and relay.js to control the everloop and the humidifier through voice
/////////////
//VARIABLES//
/////////////
var mqtt = require('mqtt');
var client  = mqtt.connect('mqtt://localhost', { port: 1883 });
var relay = require('./relay.js');
var everloop = require('./everloop.js');
var snipsUserName = 'guillengap';
var wakeword = 'hermes/hotword/default/detected';
var sessionEnd = 'hermes/dialogueManager/sessionEnded';
var lightState = 'hermes/intent/'+snipsUserName+':HumidifierState';

//////////////
//ON CONNECT//
//////////////
client.on('connect', function() {
   console.log('Connected to Snips MQTT server\n');
   client.subscribe('hermes/hotword/default/detected');
   client.subscribe('hermes/dialogueManager/sessionEnded');
   client.subscribe(lightState);
});
//////////////
//ON MESSAGE//
//////////////
client.on('message', function(topic,message) {
   var message = JSON.parse(message);
   switch(topic) {
       // * On Wakeword
       case wakeword:
           everloop.startWaiting();
           console.log('Wakeword Detected');
       break;
       // * Robotic Arm Change
       case lightState:
           // Turn robotic arm Here/There
           try{
               if (message.slots[0].rawValue === 'on'){
                   relay.humidifierOn();
                   everloop.stopWaiting();
                   console.log('Humidifier is On');
               }
               else if(message.slots[0].rawValue === 'off'){
                   relay.humidifierOff();
                   everloop.stopWaiting();
                   console.log('Humidifier is Off');
               }		   
           }
           // Expect error if `here` or `there` is not heard
           catch(e){
               console.log('Did not receive an On/Off/Read state')
           }
       break;
       // * On Conversation End
       case sessionEnd:
           everloop.stopWaiting();
           console.log('Session Ended\n');
       break;
   }
});

everloop.js

JavaScript
SECTION A: HUMIDIFIER
This file incorporates the code required to control the LEDs on the MATRIX Creator board
/////////////
//VARIABLES//
/////////////
const matrix = require('@matrix-io/matrix-lite');
var matrix_device_leds = 0;// Holds amount of LEDs on MATRIX device
var methods = {};// Declaration of method controls at the end
var waitingToggle = false;
var counter = 0;

setInterval(function(){
   // Turns off all LEDs
   if (waitingToggle == false) {
           // Set individual LED value
           matrix.led.set({});
   }
   // Creates pulsing LED effect
   else if (waitingToggle == true) {
           // Set individual LED value
           matrix.led.set({
               b: (Math.round((Math.sin(counter) + 1) * 100) + 10),// Math used to make pulsing effect
           });
       
   };
   counter = counter + 0.2;
   // Store the Everloop image in MATRIX configuration
},50);
///////////////////
//WAITING METHODS//
///////////////////
methods.startWaiting = function() {
   waitingToggle = true;
};
methods.stopWaiting = function() {
   waitingToggle = false;
};
module.exports = methods;// Export methods in order to make them avaialble to other files 

relay.js

JavaScript
SECTION A: HUMIDIFIER
This file will control the voice controlled humidifier
 /////////////
//VARIABLES//
/////////////
const matrix = require('@matrix-io/matrix-lite');
var methods = {};// Declaration of method controls at the end
var relayPin = 0;// The GPIO pin connected to your relay

matrix.gpio.setFunction(0, "DIGITAL");
matrix.gpio.setMode(0,"output");
////////////////////////////////////OFF METHOD
methods.humidifierOff = function() {
    matrix.gpio.setDigital(0,"OFF");
    console.log("Humidfifer Have Been Turned Off");
};
////////////////////////////////////ON METHOD
methods.humidifierOn = function() {
    matrix.gpio.setDigital(0,"ON");
    console.log("Humidifier Have Been Turned On");
};
module.exports = methods;// Export methods in order to make them avaialble to other files

cane.ino

Arduino
SECTION B: FETCH A CANE
Code to upload to the ESP-WROOM-32 board
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

BLECharacteristic *pCharacteristic;
bool deviceConnected = false;
float txValue = 0;
const int readPin = 32; // Use GPIO number. See ESP32 board pinouts
const int LED = 2; // Could be different depending on the dev board. I used the DOIT ESP32 dev board.
const int ledPin = 23;

//std::string rxValue; // Could also make this a global var to access it in loop()

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
    }
};

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string rxValue = pCharacteristic->getValue();

      if (rxValue.length() > 0) {
        Serial.println("*********");
        Serial.print("Received Value: ");

        for (int i = 0; i < rxValue.length(); i++) {
          Serial.print(rxValue[i]);
        }

        Serial.println();

        // Do stuff based on the command received from the app
        if (rxValue.find("A") != -1) { 
          Serial.print("Turning ON!");
          digitalWrite(LED, HIGH);
          digitalWrite(ledPin, HIGH);          
        }
        else if (rxValue.find("B") != -1) {
          Serial.print("Turning OFF!");
          digitalWrite(LED, LOW);
          digitalWrite(ledPin, LOW);                    
        }

        Serial.println();
        Serial.println("*********");
      }
    }
};

void setup() {
  Serial.begin(115200);

  pinMode(LED, OUTPUT);
  pinMode(ledPin, OUTPUT);

  // Create the BLE Device
  BLEDevice::init("ESP32 UART Test"); // Give it a name

  // Create the BLE Server
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Create the BLE Service
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // Create a BLE Characteristic
  pCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID_TX,
                      BLECharacteristic::PROPERTY_NOTIFY
                    );
                      
  pCharacteristic->addDescriptor(new BLE2902());

  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID_RX,
                                         BLECharacteristic::PROPERTY_WRITE
                                       );

  pCharacteristic->setCallbacks(new MyCallbacks());

  // Start the service
  pService->start();

  // Start advertising
  pServer->getAdvertising()->start();
  Serial.println("Waiting a client connection to notify...");
}

void loop() {

}

smart_home.ino

Arduino
SECTION C: SMART HOME
int LIGHT=3, DOOR_OPEN=4, DOOR_CLOSE=5, ALARM=6;

 

void setup()

{ 

  Serial.begin(9600);

  Serial2.begin(9600);

 

  pinMode(LIGHT, OUTPUT); //LIGHT

  pinMode(DOOR_OPEN, OUTPUT); //DOOR

  pinMode(DOOR_CLOSE, OUTPUT); //DOOR 

  pinMode(ALARM, OUTPUT); //ALARM

  digitalWrite(LIGHT,LOW);

  digitalWrite(DOOR_OPEN,LOW);

  digitalWrite(DOOR_CLOSE,LOW);

  digitalWrite(ALARM,LOW);  

}

 

void loop()

{  

   while (Serial2.available())

   {

       char dato= Serial2.read();

 

       switch(dato)

       {

         //Case a - Turn on Light

         case 'a':

         {

           digitalWrite(LIGHT,HIGH);          

           Serial.println("Light is on");

           delay(10);          

           break;

         }

         //Case b - Turn off Light

         case 'b':

         {

           digitalWrite(LIGHT,LOW);

           Serial.println("Light is off");

           delay(10);          

           break;

         }

         //Case c - Open the door

         case 'c':

         {

           digitalWrite(DOOR_OPEN,HIGH);

           digitalWrite(DOOR_CLOSE,LOW);

           Serial.println("Open the door");

           delay(750);

           digitalWrite(DOOR_OPEN,LOW);

           break;

         }

         //Case d - Close the door

         case 'd':

         {

           digitalWrite(DOOR_OPEN,LOW);

           digitalWrite(DOOR_CLOSE,HIGH);

           Serial.println("Close the door");

           delay(750);

           digitalWrite(DOOR_CLOSE,LOW);

           break;

         }

         //Case e - Alarm on

         case 'e':

         {         

           digitalWrite(ALARM,HIGH);                  

           Serial.println("Alarm is on");

           delay(10);

           break;

         }     

         //Case f - Alarm off

         case 'f':

         {

           digitalWrite(ALARM,LOW);                  

           Serial.println("Alarm  is off");

           delay(10);

           break;

         }

         default:                             

         for (int thisPin = 2; thisPin < 7; thisPin++) {

           digitalWrite(thisPin, LOW);

        }

    delay(50);                 

       }      

   }

}

Smartphone Android Applicationss files, and developed with MIT App Inventor 2

Section B: FETCH A CANE & Section C: SMART HOME

Credits

Guillermo Perez Guillen

Guillermo Perez Guillen

57 projects • 63 followers
Electronics and Communications Engineer (ECE) & Renewable Energy: 14 prizes in Hackster / Hackaday Prize Finalist 2021-22-23

Comments