Showing posts with label Garage. Show all posts
Showing posts with label Garage. Show all posts

Monday, April 22, 2019

Knowing The Garage Status

I've finally got it working the way I want. If you have been following my garage work, for the last 10 years, I have wanted a way to know if I closed the garage door after I left. I tried several ways, using email and other schemes to know. I finally have a way to know, and it seems quite reliable.

I have Google assistant acting as the middle agent, and with the rest of the infrastructure it seems to be very reliable. Node red knows the state, and has all winter. The voice assistant that I brought up last post is connected to node red, and I have MQTT messages going to the Google assistant. I can ask Google assistant on my phone or tabled to know the current state.

The two categories for doors in gBridge are:

gBridge/uNNN/d4149/openclose is for querying the current state. gBridge/uNNN/d4149/openclose/set is for setting the current state. If I can get the garage device to talk to node red (I am trying, stay tuned), then I will have the node-red control the garage. For now, I am still using the garage android app.



I've broken up the garage flow, and added two new functions. I created a combiner, that will mix the state of the two doors into one message. I have the combiner return a payload of open if either door is open, otherwise will retrun a payload of closed. That function looks like:

// if either door is open, return open, otherwise if both // doors are closed return closed.
context.bigDoor = context.bigDoor || 'closed';context.littleDoor = context.littleDoor || 'closed';
if (msg.topic === 'garage/bigDoor') {  context.bigDoor = msg.payload;} else if (msg.topic === 'garage/littleDoor') {  context.littleDoor = msg.payload;
if ((context.littleDoor === 'open') || (context.bigDoor === 'open')) {        msg.payload = 'open';} else {    msg.payload = 'closed';}msg.topic = 'garage/door';
return msg;


The alarm function node was simplified, to only check the state of the combined nodes and the time.

// if either door is open, after 11pm and before 6am // sound an alarm.
context.hour = context.global.hour || 12;context.door = context.door || 'closed';
if (msg.topic === 'garage/door') {  context.door = msg.payload;} else if (msg.topic === 'time/ISO-8601') {    context.hour = msg.payload.hour;}
// check the status, to know if alarm should be onif ((context.door === 'open')  &&    (context.hour > 22) || (context.hour < 6)) {    // msg.payload = "on " + context.therm + " " + context.temp;    msg.payload = 'on';} else {    msg.payload = 'off';}return msg;

This should make the alarm more reliable as well.

The new function node converts the payload "open" or "closed" to "100" or "0" that the gBridge door nodes expect. The value can be something between 0 and 100 to indicate partially open or closed. I haven't played with it, so I don't know if there is a threshold, but the voice will say "open" if the value is set to 100.

// Convert a msg payload that says "open" or "closed"// to a msg.payload "100" for open, and "0" flr closed
context.flow.value = context.flow.value || "0";context.flow.newVal = context.flow.newVal || "0";
if (msg.payload === 'open'){    context.flow.newVal = "100";} else {    context.flow.newVal = "0"}
if (context.flow.newVal === context.flow.value) {    //msg.payload = {newVal: context.flow.newVal,    //               value: context.flow.value};    //return msg;} else {    msg.payload = context.flow.newVal;    context.flow.value = context.flow.newVal;    return msg;}

I have the ConvOpenCloseTo100or0 function will only send a message on a change. If the door is closed, the MQTT message will only be sent once if either door is opened. Again, if a door is open, it will only send the MQTT message when both doors are closed.

This is something that may allow Google to invade my privacy a little. It should still keep all the logic inside my house (on the edge).


Wednesday, April 17, 2019

Voice Control

Almost everything can be voice controlled these days. Ask your phone, and it'll tell you stuff you didn't know you needed to know. Apple, Google, Amazon and others all have voice assistants that can be used for control of appliances, buying stuff or just entertainment. Node Red has nodes that support most of these assistants.

I have been mostly using the Google infrastructure, since it is typically more open. It isn't perfect, but it does allow me to develop apps and write blogs. I have had some success using their tools for automating my home.

NOTE: gbridge is no longer a solution. The company no longer supports this application. 

I am using the gbridge node. The setup is very simple, using a standard MQTT interface to their service. It does take some registration on their web site, and in the google home app. They support multiple levels of usage, and allow self hosting. The self hosting can be done on the same RaspberryPi that Node-Red/Mosquitto is running on. The free service allows 4 devices, and more than that will require a subscription, and you choose how much to pay.

Setting up something simple

In the account on the gbridge site, you can set up various devices, what traits (open, close, on, off, etc) those devices will exhibit and what the topic and payload is allowed. This must be done before adding the node to node red.

I connected this to my most complex flow, and it worked right out of the box! After following the setup steps properly. The flow is very simple:



Just an MQTT input node, a debug node and a connector. The connector goes to the heater flow in the previous post. The single "google voice" node could go right in the heater flow without adding much complexity to that flow.

The MQTT node has some configuration:

The server is the gbridge server. This is another MQTT agent that the Node-Red will talk to . It should be set up as any other MQTT agent is added to node-red (like localhost for any of the connections to mosquitto running on the Raspberry Pi).

The URL will have your user number in it. This is your number, and shouldn't be shared with anyone, unless you want others to control your home. The uNNN is my number obfuscated, so I can prevent you from controlling my house.

Once all that is set, using a google assistant (voice or typing), I enter the command "set sunroom thermostat to 80" and the thermostat setting will change to 80 degrees. The payload from the MQTT node is the temperature.

The voice assistant understands other commands like "make it cooler", "make it warmer", but my flow doesn't know what to do with those commands. The payload from the Google Voice MQTT node will send "3" for make it warmer, and "-3" for make it cooler. This could be used in a function node to adjust the current temperature, but for now, I won't use them. What happens now, the thermostat will be set to 3 degrees if the "make it warmer" command is asked.

There are other topics that can be used by node-red to allow querying the status of the node as well. The "gBridge/uNNN/d1000/tempset-ambient/set topic allows me to ask the google assistant what the current temperature is in the room.

I'd like to ask the current state of the garage as well. I've driven off many times, and been unsure if I shut the garage. MAybe in the next post, I'll show how to do that. I also want to show the library that I have made to simplify the nodeMCU development, and other things. There is lots to come.

Ask any questions.




Wednesday, March 13, 2019

An Input Node

In the last post I mentioned that I would build an input node. This node will be capable of monitoring 2 doors, and the temperature. I have this node out in the garage. There are magnetic reed switches near the two doors and a Dallas DS18B20 temperature sensor near the door.

I built the node with the ESP8266, using the Arduino IDE. There is a "Garage" Flow in my Node-Red environment for monitoring this node. The node code is very similar to the tone generator node, but only sends output. It has the capability to turn on the LED, but there isn't anything in the Flow that actually uses it.

Here is the code:


/**
 * Simple action node. Read sensors and send out status
 * 
 * garage/bigDoor to get status of garage door
 * garage/littleDoor to get status of garage door.
 * garage/outsideTemp to read ds18b20 temperature sensor. 
 * 
 * They are separate devices, but using Node Red can be connected.
 * 
 * 
 * TGB 9/30/18
 */

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <PubSubClientTools.h>
#include <OneWire.h>
#include <DallasTemperature.h>

const char* ssid = "raspi-webgui";
const char* password = "XXXXXXXX";
const char* MQTT_SERVER = "10.3.141.1";

// Data wire is plugged into port D3 on the ESP8266
#define ONE_WIRE_BUS D3

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

//DS18B20
#define ONE_WIRE_BUS D3 //Pin to which is attached a temperature sensor
#define ONE_WIRE_MAX_DEV 15 //The maximum number of devices

WiFiClient espClient;
PubSubClient client(MQTT_SERVER, 1883, espClient);
PubSubClientTools mqtt(client);

/*
ThreadController threadControl = ThreadController();
Thread thread = Thread();
*/

long lastMsg = 0;
int value = 0;
String s = "";

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

  pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output

  pinMode(D1, INPUT_PULLUP);      // big door
  pinMode(D2, INPUT_PULLUP);      // little door
  
  // Connect to WiFi
  Serial.print(s+"Connecting to WiFi: "+ssid+" ");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(s+" connected with IP: "+WiFi.localIP());

  // Connect to MQTT
  Serial.print(s+"Connecting to MQTT: "+MQTT_SERVER+" ... ");
  if (client.connect("GarageControl")) {
    Serial.println("connected");
    digitalWrite(BUILTIN_LED, HIGH); // turn LED off

    mqtt.subscribe("garage/light", topic1_subscriber);
  } else {
    Serial.println(s+"failed, rc="+client.state());
  }

  // Start up the library
  sensors.begin();
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("GarageControl")) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("outTopic","garageControl Reconnect");
      mqtt.subscribe("garage/light", topic1_subscriber);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" Resetting");
      // Wait 5 seconds before retrying
    }
  }
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  
  client.loop();
  publisher();
}

void publisher() {
  long now = millis();
  if (now - lastMsg > 5000)  // 10 second loop.
  {
    lastMsg = now;
    ++value;
    Serial.println("Publish messages: ");


    int bd = digitalRead(D1);
    int ld = digitalRead(D2);

    String bigDoor="closed";
    String littleDoor="closed";

    if (bd) {
      bigDoor = "open";
    }
    if (ld) {
      littleDoor = "open";
    }
    Serial.print(" bigDoor: ");
    Serial.println(bigDoor);
    Serial.print(" littleDoor: ");
    Serial.println(littleDoor);
            
    mqtt.publish("garage/bigDoor", bigDoor);
    mqtt.publish("garage/littleDoor", littleDoor);

    sensors.requestTemperatures(); // Send the command to get temperatures
    int temp = sensors.getTempCByIndex(0); 
    Serial.print(" temperature: ");
    Serial.println(temp);
    String tempS = String(temp);
    mqtt.publish("garage/outsideTemperature", tempS);
  }
}

void topic1_subscriber(String topic, String message) {
  Serial.println(s+"Message arrived in function 1 ["+topic+"] "+message);
  if (message.equals("on"))
  {
    digitalWrite(BUILTIN_LED, LOW);   // Turn the LED on (Note that LOW is the voltage level
  }
  else
  {
    digitalWrite(BUILTIN_LED, HIGH);
  }
}



The Dallas DS18B20 is a simple to use device that uses the Dallas 1-wire protocol for reading data. Several 1-wire devices can be added to the single pin needed, and only ground and power are needed (actually for some devices power is optional, since the devices can be powered by the serial link). The 1-wire library is all that is needed to used these devices with almost any Arduino system. 

The code starts out initializing the 1-Wire device:


#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port D3 on the ESP8266
#define ONE_WIRE_BUS D3

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

We need to include the various libraries. I've assigned the serial data to come in on the D5 ESP8266 pin. Again, I am using the 8266's library definition to avoid having to map to the Arduino GPIO pin names. I find it easier to use the library names, since that is what is silk-screen printed on the device. 

The setup function is mostly identical to the tone generator. The only difference is setting the input mode for the two reed switches and starting the sensor monitoring that checks the ds1820. The "INPUT_PULLUP" setting for the D1 and D2 allow me to have the reed switch connected to the D1 or D2 input pins and the other side connected to ground. 

  pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output

  pinMode(D1, INPUT_PULLUP);      // big door
  pinMode(D2, INPUT_PULLUP);      // little door
    // Start up the library
  sensors.begin();



Once everything is started, the main loop() just checks the WiFi connection state, and then calls publish(), a new function. The publish function checks the state of the devices and publishes the results. This is the new part that is different from the tone generator node.

void publisher() {
  long now = millis();
  if (now - lastMsg > 5000)  // 10 second loop.
  {
    lastMsg = now;
    ++value;
    Serial.println("Publish messages: ");


    int bd = digitalRead(D1);
    int ld = digitalRead(D2);

    String bigDoor="closed";
    String littleDoor="closed";

    if (bd) {
      bigDoor = "open";
    }
    if (ld) {
      littleDoor = "open";
    }
    Serial.print(" bigDoor: ");
    Serial.println(bigDoor);
    Serial.print(" littleDoor: ");
    Serial.println(littleDoor);
            
    mqtt.publish("garage/bigDoor", bigDoor);
    mqtt.publish("garage/littleDoor", littleDoor);

    sensors.requestTemperatures(); // Send the command to get temperatures
    int temp = sensors.getTempCByIndex(0); 
    Serial.print(" temperature: ");
    Serial.println(temp);
    String tempS = String(temp);
    mqtt.publish("garage/outsideTemperature", tempS);
  }
}

There is a global variable called "lastMsg" that contains the last time the sensors were checked. If the last time was more than 5000 milliseconds (5 seconds) ago, then the sensors will be checked. If less than 5 seconds ago, this function will not do anything. The two door switches are checked. If the switch is closed, the bd/ld values will be 1, otherwise those values will be 1. The MQTT payload is initialized to be "closed". If the big door switch is closed, the "bd" variable will be 1, and the bigDoor payload will be updated to "open". Once both doors have been checked, the mqtt.publish will send out the payload for the two topics, "garage/bigDoor" and "garage/littleDoor".

After the doors have had the MQTT message published, the DS1820 will be checked. The return value from the sensor.getTempCByIndex() will be the temperature in degrees C.  The temperature value will be published on the "garage/outsideTemperature" topic.


A couple thoughts about MQTT


MQTT brokers can maintain state for various topics. There are good things and bad things about maintaining state. If the state is maintained, the last payload will be kept. If a node dies, there may not be a way to determine when the last time the node reported the state. For temperature, a maintained state may not good, since it may say the value is comfortably warm, when the real temperature is very cold or hot.

Node-Red is generally stateless. That is, unless someone publishes an MQTT message, node-red will not check for state of an item. If node-red is restarted, the node states will not be known, until the next time they publish their state.

I generally have each node publish state every few seconds. Even if the state hasn't changed, I assume that node-red doesn't know. It does mean there will be messages going on the network, that may be unnecessary. MQTT messages are small, and even 802.11n WiFi is fast enough for thousands of messages a second.


Garage Flow


The garage flow shows some new concepts. There will be some programming, but should be easy to understand.




Starting on the left top, there are 2 MQTT input nodes. Both of these will use the "localhost" MQTT server. Each will be subscribed to unique MQTT topics. The littleDoor node will be subscribed to the "garage/littleDoor" topic defined above, and the bigDoor node will be subscribed to the bigDoor MQTT topic. Both MQTT nodes are connected to debug nodes, allowing me to see if the message is being received when something comes in. A third MQTT input node is subscribed to the "garage/outsideTemperature"

The temperature node is connected to another debug node, as well as the cDegToF node. The cDegToF node converts an MQTT payload containing a temperature in Celsius and converts that to a payload in degrees Fahrenheit. The output of cDegToF node is connected to a debug node, and a MQTT output node. The MQTT output node publishes the Fahrenheit temperature on the topic "outside/farenheight". Other nodes can subscribe to "garage/outsideTemperature" or "outside/farenheight" depending on their needs.

The cDegToF node is a function node (note the F on the left). This means it is a small program. Nodes can be programmed in JavaScript. The code looks like:



The msg.payload that comes in is converted using the F=9/5C+32 calculation. To edit a function, simply double click on the node after dragging it to the work area. The above dialog will appear.

The mode advanced function node in this flow is the "Door Open Alarm" node. As you can see from the cDegToF node above, functions are easy with one message coming in. For this node, there are two messages that can cause the alarm to sound. Either big door or little door messages will cause the alarm to come on. If one door is open, and the other closed, the function may not know if anything is open, if the node only looks at all msg.payloads.

I need to introduce context. State of nodes in Node-Red have several contexts. The node has a context for the instant it is running, there is a flow based context, that all nodes within a flow can know about, and there is the global node-red context that all flows share.

Code for the Door Open Alarm:

// if either door is open, after 11pm and before 6am 
// sound an alarm.

context.hour = context.global.hour || 12;
context.bigDoor = context.bigDoor || 'closed';
context.littleDoor = context.littleDoor || 'closed';

if (msg.topic === 'garage/bigDoor') {
  context.bigDoor = msg.payload;
} else if (msg.topic === 'garage/littleDoor') {
  context.littleDoor = msg.payload;
} else if (msg.topic === 'time/ISO-8601') {
    context.hour = msg.payload.hour;
}

// check the status, to know if alarm should be on
if (((context.bigDoor === 'open') || (context.littleDoor === 'open')) &&
    (context.hour > 22) || (context.hour < 6)) {
    // msg.payload = "on " + context.therm + " " + context.temp;
    msg.payload = 'on';
} else {
    msg.payload = 'off';
}
return msg;


For the "Door Open Alarm" node, I maintain state in a the node's context. The context is initialized to the current state or if unknown, to the 'closed' state. The time is global context that I have in another node (I'll talk about that in another post).

If a message comes in on a topic that the node knows about (garage big/little door), then the context for that door is updated to the current state. If either door is open during the alarm time, a new message is published containing the payload "on". This node doesn't know the recipient of the payload, only the payload.

That last node in this flow is the MQTT output node that will send the alarm payload to the tone generator. It will publish the payload passed here on the "home/alarm" topic.

This may be lots to digest. Hopefully it will give some ideas of the capabilities of a RaspberryPi and some 8266's.

More to come.





Thursday, August 13, 2015

Garage Project Update

I completed this a couple months ago. I just didn't get to posting it. Check out the other posting if you want to know what this is updating.  Of course, I updated the GUI, so it isn't just "Big Door", "Little Door" and made the app a little more robust. It remembers the last Bluetooth device, so pairing is a little more automatic. The change to the GUI allows users to click on the door they want open, and it opens. Someday, I may put in sensors so the GUI could show the current state of the doors (so when I go to bed, I can look, and know if I left any doors open). The app inventor project is at this link.



 I re-did the wiring in the garage as well. I used to have a spiderweb in the ceiling with droopy wires from the access door to the openers. Who ever installed the openers or the wiring must have run out of staples, and there were like 3 for the two openers. Now all the wiring goes through the attic, with the central wiring on a barrier strip.

The sketch I didn't change, but I noticed I didn't upload that either. I'll give that a go as well. The sketch isn't doing anything really complex. It is still based on ardudroid.


/*
 PROJECT: Garage 
 PROGRAMMER: T Brusehaver
 DATE: May 31, 2015
 FILE: garage.ino
 LICENSE: Public domain
*/

#define START_CMD_CHAR '*'
#define END_CMD_CHAR '#'
#define DIV_CMD_CHAR '|'
#define CMD_DIGITALWRITE 10
#define CMD_ANALOGWRITE 11
#define CMD_TEXT 12
#define CMD_READ_ARDUDROID 13
#define MAX_COMMAND 20  // max command number code. used for error checking.
#define MIN_COMMAND 10  // minimum command number code. used for error checking. 
#define IN_STRING_LENGHT 40
#define MAX_ANALOGWRITE 255
#define PIN_HIGH 3
#define PIN_LOW 2

String inText;

void setup() {
  Serial.begin(9600);
  Serial.println("Garage By T. Brusehaver (2015)");
  Serial.flush();
}

void loop()
{
  Serial.flush();
  int ard_command = 0;
  int pin_num = 0;
  int pin_value = 0;

  char get_char = ' ';  //read serial

  // wait for incoming data
  if (Serial.available() < 1) return; // if serial empty, return to loop().

  // parse incoming command start flag 
  get_char = Serial.read();
  if (get_char != START_CMD_CHAR) return; // if no command start flag, return to loop().

  // parse incoming command type
  ard_command = Serial.parseInt(); // read the command
  
  // parse incoming pin# and value  
  pin_num = Serial.parseInt(); // read the pin
  pin_value = Serial.parseInt();  // read the value
  
  Serial.print("Ard_command ");
  Serial.print(ard_command);
  Serial.print("  Pin=");
  Serial.print(pin_num);
  Serial.print("  Val=");
  Serial.println(pin_value);

  // 1) GET TEXT COMMAND FROM ARDUDROID
  if (ard_command == CMD_TEXT){   
    inText =""; //clears variable for new input   
    while (Serial.available())  {
      char c = Serial.read();  //gets one byte from serial buffer
      delay(5);
      if (c == END_CMD_CHAR) { // if we the complete string has been read
        // add your code here
        break;
      }              
      else {
        if (c !=  DIV_CMD_CHAR) {
          inText += c; 
          delay(5);
        }
      }
    }
  }

  // 2) GET digitalWrite DATA FROM ARDUDROID
  if (ard_command == CMD_DIGITALWRITE){  
    if (pin_value == PIN_LOW) pin_value = LOW;
    else if (pin_value == PIN_HIGH) pin_value = HIGH;
    else return; // error in pin value. return. 
    set_digitalwrite( pin_num,  pin_value);  // Uncomment this function if you wish to use 
    return;  // return from start of loop()
  }

  // 3) GET analogWrite DATA FROM ARDUDROID
  if (ard_command == CMD_ANALOGWRITE) {  
    analogWrite(  pin_num, pin_value ); 
    // add your code here
    return;  // Done. return to loop();
  }

  // 4) SEND DATA TO ARDUDROID
  if (ard_command == CMD_READ_ARDUDROID) { 
    // char send_to_android[] = "Place your text here." ;
    // Serial.println(send_to_android);   // Example: Sending text
    Serial.print(" Analog 0 = "); 
    Serial.println(analogRead(A0));  // Example: Read and send Analog pin value to Arduino
    return;  // Done. return to loop();
  }
}

// 2a) select the requested pin# for DigitalWrite action
void set_digitalwrite(int pin_num, int pin_value)
{
  switch (pin_num) {
  case 13:
    pinMode(13, OUTPUT);
    digitalWrite(13, pin_value);  
    // add your code here      
    break;
  case 12:
    pinMode(12, OUTPUT);
    digitalWrite(12, pin_value);   
    // add your code here       
    break;
  case 11:
    pinMode(11, OUTPUT);
    digitalWrite(11, pin_value);         
    // add your code here 
    break;
  case 10:
    pinMode(10, OUTPUT);
    digitalWrite(10, pin_value);         
    // add your code here 
    break;
  case 9:
    pinMode(9, OUTPUT);
    digitalWrite(9, pin_value);         
    // add your code here 
    break;
  case 8:
    pinMode(8, OUTPUT);
    //digitalWrite(8, pin_value);
    // add your code here 
    digitalWrite(8, HIGH);   // sets the LED on
    delay(1000);                  // waits for a second
    digitalWrite(8, LOW);    // sets the LED off
    break;
  case 7:
    pinMode(7, OUTPUT);
    //digitalWrite(7, pin_value);         
    // add your code here 
    digitalWrite(7, HIGH);   // sets the LED on
    delay(1000);                  // waits for a second
    digitalWrite(7, LOW);    // sets the LED off
    break;
  case 6:
    pinMode(6, OUTPUT);
    digitalWrite(6, pin_value);         
    // add your code here 
    break;
  case 5:
    pinMode(5, OUTPUT);
    digitalWrite(5, pin_value); 
    // add your code here       
    break;
  case 4:
    pinMode(4, OUTPUT);
    digitalWrite(4, pin_value);         
    // add your code here 
    break;
  case 3:
    pinMode(3, OUTPUT);
    digitalWrite(3, pin_value);         
    // add your code here 
    break;
  case 2:
    pinMode(2, OUTPUT);
    digitalWrite(2, pin_value); 
    // add your code here       
    break;      
    // default: 
    // if nothing else matches, do the default
    // default is optional
  } 
}

The relays are connected to the Arduino using an NPN transistor. One relay each on pins 7 and 8. The power supply is my old Motorola Razr charger (mini USB). The HC05 is connected using the TX and RX serial pins, so they need to be disconnected if connecting to the USB port to program the Arduino. Also Have a look at the Ardudriod page for the resistors and 3.3V connection. (Don't try 5V and don't forget the resistor on the RX pin). Remember the module is receiving on RX but sending to the TX pin.

There have been a few things I don't like about it, but overall it is serving it's purpose. Pairing basic HC05 modules with and Arduino isn't as quick or automatic as I'd like it to be. Of course, sometimes the signal is going through an aluminium door on the way to the module, so I can't blame anything but circumstances.

If you are thinking of trying this yourself, I recommend it. If nothing else, this is a good place to start.



Sunday, May 31, 2015

More Garage Stuff

I was once distracted by a silly garage project. Then I moved, and now I have another garage project. This one is similar to the Engine Monitor I keep promising to build. Heck this whole project is about me learning, and sharing those lessons so others may benefit from them.


I have a house with a 3 car garage. It isn't huge, there are two doors, one small, and one large. I know on the large side we can't put our two cars in, and open the car doors. There are still two doors, each with their own openers. The remote controls in the cars work great, but you need two, if you want to open both doors. Yes, I know they sell learning controls that will open both, but what about when you just want to open the door when not in the car? I have tools and such in the garage, and sometimes I need something, and the car may be in the garage.

I always have my phone in my pocket. Is there a way to have the phone talk to the opener? Not the stock openers, only a special opener. Well I have a bunch of Arduino stuff, and a phone that talks bluetooth, can they be connected? Well, sure they can. Again I experimented using the ArduDroid an Arduino Mega and a Bluetooth shield. Nothing to it, that all worked great. Then I moved on to a 6 pin HC-05 module and the mega, and that worked as well. The HC-05 isn't any bigger than a Arduino Nano, so I tried that. That worked as well.

Once I had all the Arduino hardware working, it was time to do something quick with the Android. The ArduDriod has an OK interface, but I wanted something that looked like it belong. I didn't want to do a full blown app, so I looked at my options. I ended up choosing App Inventor. It is probably as much work as writing an app, since I had a lot to learn, but I was able to learn the app inventor and as a result I have an app that will open and close the garage.


There are 3 buttons and a label. The buttons cause the relay corresponding to the door labeled to close for about a second. I have the project available if anyone would want it. It was done using app inventor 2. The protocol stillis the ArduDroid protocol, so I had a sketch I could start with.

If you want to try it, let me know, I'll share what I have.