Home Automation: Simplest Human Interface

I’m starting a reincarnation of my 20+ year old Home/Energy automation system that I wrote in Turbo PASCAL and ran on an IBM AT with a “Voice Communications Adapter” which was a Dragon Systems Text-To-Speech with a Ti DSP etc and cost $600 back in the day. But the speech was real nice, like Steve Hawkins (DECTalk I think)… So I’ve been looking at Arduino Text-To-Speech.

The low-cost possibilities like SpeakJet sound really bad to me. So I went for a DEC-Talk derivative from http://www.grandideastudio.com/ called Emic2 which is $60 from Sparkfun, Parallax etc. Info here: http://www.grandideastudio.com/portfolio/emic-2-text-to-speech-module/
Sparkfun page here: https://www.sparkfun.com/products/11711

So, my criteria for the simplest human interface for a complex home automation system is like this:

  • Input device 1 pin

  • Output device 2 pins

  • Unobtrusive going on invisible in living room, bedroom etc.

  • Can control the system with low-cost switches at various home locations

  • Can control and monitor the system lying in bed in the dark with my eyes closed.

So: my solution was/is:

  • Single parallel circuit Morse Code input
  • Voice Output

I really liked this system, and used it for 20 years. Amazing how fast my wife and kids learned “T” for temperatures, “W” for more detailed weather, and “Q” for Quiet when they didn’t want to explain to guests who was talking… And they did like it that they were alerted when the dishwasher went into dry cycle and the clothes washer was done. And in my NerdMode it told me every time the water pump ran and for how long and WAY too much other stuff.

So, I started with getting Morse IN and Voice OUT to work on Arduino. Here’s a test sketch that takes Morse in on one pin (switch to ground) and Voice out on 2 pins from Software Serial. You can use the Serial Monitor to type in phrases to hear spoken (Use “S” followed by the text, followed by Line Feed). and you can see the decoded Morse on the serial monitor. If you send morse you need to send “S” and some text and “.” period. Period is .-.-.- in Morse.

OK, not for everyone. Maybe not for many… but I like it… I’ll be updating stuff as I go along in anyone is interested. I’ll be running this on a MEGA2560 for the real system as I need lots of I/O. Code example below. Comments and suggestions appreciated.

And yes, it WILL eventually be controlled also by my smartphone and be visible on the web. But if I want to know what the Vermont temperature got down to at 4AM I only want to move one arm a little and keep my eyes closed.

/* Test Morse to Text-To-Speech
   - MorseIN 8  ( Not conflict with Software Serial)
   - TTS IN 5 TTS Out 3
 - V1.12 05/22/13
   Questions: terry@yourduino.com */

/*-----( Import needed libraries )-----*/
#include <SoftwareSerial.h>  // For communication to Emic2 Text-To-Speech module
// Module from http://www.grandideastudio.com/portfolio/emic-2-text-to-speech-module/ 
// (Sold by Parallax and Sparkfun.com)

#include <avr/pgmspace.h>    // For Morse Decoder
// This library from:   http://raronoff.wordpress.com/2010/12/16/morse-endecoder/
#include <MorseEnDecoder.h>

/*-----( Declare Constants and Pin Numbers )-----*/
const byte morseInPin = 8;  // Needs to be in this form

#define rxPin 3    // Serial input (connects to Emic 2 SOUT)
#define txPin 5    // Serial output (connects to Emic 2 SIN)

/*-----( Declare objects )-----*/
morseDecoder morseInput(morseInPin, MORSE_KEYER, MORSE_ACTIVE_LOW);
SoftwareSerial emicSerial =  SoftwareSerial(rxPin, txPin);

/*-----( Declare Variables )-----*/

void setup()   /****** SETUP: RUNS ONCE ******/
  pinMode(rxPin, INPUT);
  pinMode(txPin, OUTPUT);
  Serial.println("Morse to Text-To-Speech Demo");  
  //-----( SET UP MORSE DECODE )--------
  morseInput.setspeed(5);  // 5 words per minute : slow  
  //-----( SET UP Text-To-Speech )-----------
  emicSerial.begin(9600);             // set the data rate for the SoftwareSerial port
  emicSerial.print('\n');             // Send a CR in case the system is already up
  while (emicSerial.read() != ':');   // When the Emic 2 has initialized and is ready, it will send a single ':' character, so wait here until we receive it
  delay(10);                          // Short delay
  emicSerial.flush();                 // Flush the receive buffer
  emicSerial.print("S System Started. This is Oh Lee.\n");  // Send a string to convert to speech  
}//--(end setup )---

void loop()   /****** LOOP: RUNS CONSTANTLY ******/
  //-------------------------( Decode Morse )---------------------------------
    // Need to call this once per loop
//  delay(25);   // Simulate real program loop...

//----( RECEIVE MORSE (INPUT) )-------------
  // If a character is decoded from the input, write it to serial port and TextToSpeech
  if (morseInput.available())
    char receivedMorse = morseInput.read();
    delay (10);
    emicSerial.write(receivedMorse);   // Write to TTS
    if (receivedMorse == 0x2E) // "."
        emicSerial.write(0x0A); // End with LineFeed character to trigger TTS module
    // A little error checking    
    if (receivedMorse == '#') Serial.println("< ERROR:too many morse signals! >");
//------------------( Do typed-in Text-To-Speech )------------------------------

 // Copy Serial Data from Serial Monitor to TTS if some is typing it in
  while (Serial.available() > 0) 

}//--(end main loop )---

/*-----( Declare User-written Functions )-----*/

//*********( THE END )***********