Open/close sensor with SMS text alarm

Our garage faces the alley and it is not unusual to hear of people leaving the garage door open and get stuff stolen. The trade offs of leaving inside the loop in Houston as it is for any large city in the world (even Oslo). Now it has been 3 times that we forget the garage door open, and this last time we left it overnight! Lucky us, the garage was intact and this is unusual, more than 8 hours open and nothing taken, more than unusual I’ll classify it as miracle. Anyway, I needed to do something about it so I thought of using one of the ESP8266 modules and add an email service in it, but ultimately send SMS messages to me and my wife.

It is a simple mechanism. I pulled a 1k resistor to 3.3 V on  the GPIO2 of the ESP8266 and a switch to ground. When the switch is open, there is voltage in the GPIO2 so its state is 1, when the switch closes, it sends the GIPO2 to ground, voltage is 0, state is 0.

Screen Shot 2015-07-31 at 4.03.43 PM

I programmed the ESP8266 to monitor changes in GPIO2 as follows:

  • If switch closes, wait a number of minutes (typically lets say 5 minutes) before sending a text message.
  • If switch opens before the 5 minutes are passed, do nothing, the door has just been normally opened and closed.
  • If switch is closed and 5 minutes passed, send a text message
  • Keep sending a message every 5 minutes until switch closes

Thats it.

IMG_6314

IMG_6313

IMG_6312

Here is the code:

pin=4
open_mess_sent = 0
dofile(“sendmail.lua”)

function onAlarm()
value = gpio.read(pin)
if value == 0 then
open_mess_sent = 0
print(“Sending open message”)
tmr.alarm(1,300000,1, open_msg)
elseif value == 1 then
tmr.stop(1)
if open_mess_sent == 1 then
print(“Sending close message”)
close_msg()
open_mess_sent = 0
end
end
end

function open_msg()
send_email(“5555555555@txt.att.net”, “WARNING”, “Garage door is open”)
open_mess_sent = 1
end

function close_msg()
send_email(“5555555555@txt.att.net”, “RESOLVED”, “Garage door is now closed”)
end

function init_STA()
gpio.mode(pin,gpio.INPUT)
gpio.mode(pin,gpio.INT)
gpio.trig(pin, ‘both’, onAlarm)
end

Posted in Uncategorized | 4 Comments

WiFi Analog/Digital Module reads analog or digital data, returns the values and responds according to programmable limits. MQTT protocol

Ready to use boards available at Tindie

WiFi Analog/Digital Module reads analog or digital data, returns the values and responds according to programmable limits. MQTT protocol

The analog/digital control module reads analog data and digital data through its 2 input terminals. Input analog data limits are zero VDC to 3.3VDC, and this maps into output values of 0 to 1024 Input digital data limits are zero, for a digital zero, and 3.3VDC for a digital 1 The module sends the value of the measured analog data periodically every Interval milliseconds, and it sends the value of the measured digital data when this chances from 0 to 1 or from 1 to 0. The user can also request the module to send the measured values of analog and/or digital data at any time by publishing a specific MQTT topic. The module provides a triggering signal whenever the digital data changes (Figure 1) The module provides a triggering signal when the analog signal is less than a preset value or larger than a preset value (Figure 2)

Figure 1: Digital data response
DigitalDataResponseGraph

Figure 2: Analog data response
AnalogDataResponseGraph
Once the module is connected to the WiFi router it will stablish communication with the MQTT server and port as specified above and will attempt to connect. Wait a few seconds and all 4 LEDs will blink in sequence indicating a successful connection. If this fails, reset the board and wait a few seconds for the LED sequence. The module uses MQTT protocol for communication. MQTT topics are composed of a four letter acronym followed by the ESP822 chipid (the chipid is listed with your documentation), XXXXchipid Once a connection with the MQTT sever is established, the module is ready for communication and therefore reading analog and digital data and sending commands.

A typical MQTT instruction is composed of a topic followed by a message.

MQTT Topics and Messages

RANLchipid : this topic instructs the module to read a sample of the analog data and send it back via an MQTT topic and message. The module in response sends a topic and value as follows:
DANLchipid value ; you can get the analog value by subscribing to the topic DANLchipid and getting the value from the message
RDIGchipid : this topic instructs the module to read a sample of the digital data and send it back via an MQTT topic with the value as a message. The module in response sends a topic and value as follows:
RANLchipid value ; you can get the digital value by subscribing to the topic RANLchipid and getting the value from the message
MANLchipid min_analog_trigger (min 0, max 1024, def 300): this topic allows the user to set the module’s minimum analog value used for triggering the LED and signal . The change takes immediate effect.
XANLchipid max_analog_trigger (min 0, max 1024, def 800):: this topic allows the user to set the module’s maximum analog value used for triggering the LED and signal. The change takes immediate effect.
INTEchipid Interval_in_milliseconds (min 500 ms, max 240000 ms, def 5000 ms): this topic allows the user to set a new interval in milliseconds for receiving analog data. The change takes immediate effect.
RESTchipid: this topic allows the user to reset the module remotely.

Note that the analog value is sent by the module at regular intervals (controlled by the value of Interval_in_milliseconds) as specified during configuration or changed during operation, while the digital value is sent only when it changes. You can always request the analog or digital value at any time by publishing the respective topic.

Posted in Uncategorized | 2 Comments

WIFI Color Detection with the ESP8266 and MQTT messaging

The previous implementation of the WIFI color detection was done with an ad-hoc messaging system. Now, the most bang for the buck would be to have MQTT integrated, as it is much more flexible in terms of the message format and content.

I got the color detection, which involves frequency decoding of each of the filtered signals for R,G,B and no-filter, and MQTT working like a charm.

The protocol is simple. An MQTT message is sent to topic “AcquireColor”. Response is obtained by listening to topics “GetColorP” for color percentage and “GetColorF” for raw frequency (proportional to color intensity). The returned info comes back as a JSON string as follows:

Percentages:

{“RGBP”: [{ “Red:”: “37”, “Green”: “30”, “Blue:”: “32”}]}

Frequencies:

{“RGBF”: [{ “Red:”: “6578”, “Green”: “5291”, “Blue:”: “5649”, “All:”: “8695”}]}

This module can be purchased at my Tindie store

IMG_5828

Here is the code:

file.writeline([[red=0 ]])
file.writeline([[green=0 ]])
file.writeline([[blue=0 ]])
file.writeline([[all=0 ]])
file.writeline([[IP_posted = 0]])
file.writeline([[color_done=0]])
file.writeline([[pin=5]])
file.writeline([[cur_color=0]])
file.writeline([[start=0]])
file.writeline([[count=0]])
file.writeline([[s_length=10000]])
file.writeline([[freq_multi=1000000]])

file.writeline([[collectgarbage()]])

file.writeline([[– Configuration to connect to the MQTT broker.]])
file.writeline([[BROKER = “your_mqtt_broker_IP_address” — Ip/hostname of MQTT broker]])
file.writeline([[BRPORT = 1883 — MQTT broker port]])
file.writeline([[BRUSER = “user” — If MQTT authenitcation is used then define the user]])
file.writeline([[BRPWD = “pwd” — The above user password]])
file.writeline([[CLIENTID = “ESP8266-” .. node.chipid() — The MQTT ID. Change to something you like]])
file.writeline([[BFSIZE = 16]])

file.writeline([[– MQTT topics to subscribe]])
file.writeline([[topics = {“AcquireColor”} ]])

file.writeline([[– Control variables.]])
file.writeline([[pub_sem = 0 ]])
file.writeline([[current_topic = 1 ]])
file.writeline([[topicsub_delay = 50]])

file.writeline([[– Publishing structures]])
file.writeline([[pub_topic = {}]])
file.writeline([[pub_message = {}]])
file.writeline([[pub_head = 1]])
file.writeline([[pub_tail = 1]])

file.writeline([[collectgarbage()]])

file.writeline([[print(“heap: ” .. node.heap() )]])
file.writeline([[m = mqtt.Client( CLIENTID, 120, BRUSER, BRPWD)]])

file.writeline([[print “Connecting to MQTT broker. Please wait…”]])
file.writeline([[m:connect( BROKER , BRPORT, 0, function(conn)]])
file.writeline([[ print(“Connected to MQTT:” .. BROKER .. “:” .. BRPORT ..” as ” .. CLIENTID )]])
file.writeline([[ mqtt_sub() ]])
file.writeline([[end)]])

file.writeline([[function mqtt_sub()]])

file.writeline([[ if table.getn(topics) < current_topic then]])
file.writeline([[ init_STA()]])
file.writeline([[ else]])
file.writeline([[collectgarbage()]])
file.writeline([[ m:subscribe(topics[current_topic] , 0, function(conn) ]])
file.writeline([[ end)]])
file.writeline([[ current_topic = current_topic + 1 ]])
file.writeline([[ tmr.alarm(5, topicsub_delay, 0, mqtt_sub )]])
file.writeline([[ end]])
file.writeline([[collectgarbage()]])

file.writeline([[end]])

file.writeline([[function publish_data()]])
file.writeline([[collectgarbage()]])
file.writeline([[ freq_all =(freq_multi/all)]])
file.writeline([[ freq_red =(freq_multi/red)]])
file.writeline([[ freq_green =(freq_multi/green)]])
file.writeline([[ freq_blue =(freq_multi/blue)]])
file.writeline([[ col_sum =freq_red+freq_green+freq_blue]])
file.writeline([[ perc_red = (100*freq_red)/col_sum]])
file.writeline([[ perc_green = (100*freq_green)/col_sum]])
file.writeline([[ perc_blue = (100*freq_blue)/col_sum]])

file.writeline([[payload = ‘{“RGBF”: [{ “Red:”: “‘ .. freq_red .. ‘”, “Green”: “‘ .. freq_green .. ‘”, “Blue:”: “‘ .. freq_blue .. ‘”, “All:”: “‘ .. freq_all .. ‘”}]}’]])
file.writeline([[m:publish( “GetColorF”, payload ,0 ,0 , function(conn) ]])
file.writeline([[end)]])
file.writeline([[payload = ‘{“RGBP”: [{ “Red:”: “‘ .. perc_red .. ‘”, “Green”: “‘ .. perc_green .. ‘”, “Blue:”: “‘ .. perc_blue .. ‘”}]}’]])
file.writeline([[m:publish( “GetColorP”, payload ,0 ,0 , function(conn) ]])
file.writeline([[end)]])
file.writeline([[payload = nil]])
file.writeline([[collectgarbage()]])
file.writeline([[end]])
file.writeline([[function pin1cb(level)]])
file.writeline([[if cur_color == 0 and count == 0 then]])
file.writeline([[ gpio.mode(6,gpio.OUTPUT)]])
file.writeline([[ gpio.mode(7,gpio.OUTPUT)]])
file.writeline([[ gpio.write(6,gpio.HIGH)]])
file.writeline([[ gpio.write(7,gpio.LOW)]])
file.writeline([[elseif cur_color == 1 and count == 0 then]])
file.writeline([[ gpio.mode(6,gpio.OUTPUT)]])
file.writeline([[ gpio.mode(7,gpio.OUTPUT)]])
file.writeline([[ gpio.write(6,gpio.LOW)]])
file.writeline([[ gpio.write(7,gpio.LOW)]])
file.writeline([[elseif cur_color == 2 and count == 0 then]])
file.writeline([[ gpio.mode(6,gpio.OUTPUT)]])
file.writeline([[ gpio.mode(7,gpio.OUTPUT)]])
file.writeline([[ gpio.write(6,gpio.HIGH)]])
file.writeline([[ gpio.write(7,gpio.HIGH)]])
file.writeline([[elseif cur_color == 3 and count == 0 then]])
file.writeline([[ gpio.mode(6,gpio.OUTPUT)]])
file.writeline([[ gpio.mode(7,gpio.OUTPUT)]])
file.writeline([[ gpio.write(6,gpio.LOW)]])
file.writeline([[ gpio.write(7,gpio.HIGH)]])
file.writeline([[end]])
file.writeline([[if count == 0 then]])
file.writeline([[ start = tmr.now()]])
file.writeline([[end]])
file.writeline([[tmr.wdclr()]])
file.writeline([[count=count+1]])
file.writeline([[if count > s_length then]])
file.writeline([[ if cur_color == 0 then]])
file.writeline([[ all=(tmr.now()-start)/s_length]])
file.writeline([[ cur_color=1]])
file.writeline([[ print(all )]])
file.writeline([[ elseif cur_color == 1 then]])
file.writeline([[ red=(tmr.now()-start)/s_length ]])
file.writeline([[ cur_color=2]])
file.writeline([[ print(red )]])
file.writeline([[ elseif cur_color == 2 then]])
file.writeline([[ green=(tmr.now()-start)/s_length]])
file.writeline([[ cur_color=3]])
file.writeline([[ print(green )]])
file.writeline([[ elseif cur_color == 3 then]])
file.writeline([[ blue=(tmr.now()-start)/s_length]])
ile.writeline([[ cur_color=0]])
file.writeline([[ color_done=1 ]])
file.writeline([[ gpio.mode(pin,gpio.INPUT)]])
file.writeline([[ print(blue )]])
file.writeline([[ publish_data()]])
file.writeline([[ end]])
file.writeline([[ count=0]])
file.writeline([[end]])
file.writeline([[end]])

file.writeline([[function init_STA()]]) — 1
file.writeline([[collectgarbage()]])

file.writeline([[m:on(“message”, function(conn, topic, payload)]])
file.writeline([[print(topic .. “:” )]])
file.writeline([[ –if (payload ~= nil ) then]])
file.writeline([[ — print ( payload )]])
file.writeline([[ –end]])
file.writeline([[collectgarbage()]])
file.writeline([[cur_color=0]])
file.writeline([[red=0 ]])
file.writeline([[green=0 ]])
file.writeline([[blue=0 ]])
file.writeline([[all=0 ]])
file.writeline([[IP_posted = 0]])
file.writeline([[color_done=0]])
file.writeline([[cur_color=0]])
file.writeline([[start=0]])
file.writeline([[count=0]])
file.writeline([[gpio.mode(pin,gpio.INT)]])
file.writeline([[gpio.trig(pin, “down”, pin1cb)]])

file.writeline([[end )]])
file.writeline([[end]]) — 1

Screen Shot 2015-05-29 at 4.08.15 PM

Posted in Uncategorized | 2 Comments

WIFI Color Detection with the ESP8266

IMG_5950:

The reading of the color components is done via a TCP request to the board. The reading returns a frequency in KHz proportional to the intensity of the color. The frequencies in KHz are returned in a JSON string. The value of the intensity for all colors is also returned. Percentage components of color can be calculated from the frequency readings as these are proportional to the color intensity.

The sequence for reading is done by sending the following strings via TCP on port 9999:

acquire

(wait 5 seconds for acquisition to complete)

readf to read the frequency values

readp to read the percent values

The return message is in JSON format as follows:

Frequency:

{“RGBF”: [{ “Red:”: “1640”, “Green”: “1230”, “Blue:”: “2250”, “All:”: “6250”}]}}]}

each number representing a frequency in KHz proportional to the intensity of the light for red, green, blue and unfiltered (all).

 

Percentage:

{“RGBP”: [{ “Red:”: “33”, “Green”: “42”, “Blue:”: “25”}]}}]}

each number representing a percentage of the intensity of the light for red, green, blue.

This might seem stupid, but given the memory issues on the LUA API, this at least works nicely. Lets see in I can squeeze in MQTT.

Posted in Uncategorized | Leave a comment

MQTT and ESP8266, using i2c sensor things work

Forget the DHT11. Implementing the protocol to read temperature and humidity eats all your memory on the ESP8266 and there is nothing left if you want to support MQTT messaging. However, and I2C sensor works. The I2C implementation using an LM75A can be done and integrated with MQTT.

I am preparing a post with the details on what I did.

Posted in Uncategorized | Leave a comment

MQTT and ESP8266

Got the vibration detection board working with MQTT. This was really an ordeal given that the memory issues with LUA and the ESP8266 are really frustrating. Its trial and error. Finally and after stripping the code to the bare minimum, i.e., remove all the fancy web page interface to the board configuration, things got working pretty good.

I installed my own MQTT broker on a MacBook, Mosquitto, and got it to work without major issues.

MQTT is really great for IoT, of course if you have a broker running or want to go through a public broker, otherwise my ad-hoc messaging solution I think it is a bit easier for home projects. But again, MQTT is the way to go if you want to control several devices, send and receive various commands, etc.

On my future boards I will offer ad-hoc messaging or MQTT, check them out on Tindie

Posted in Uncategorized | 2 Comments

Color recognition board using the ESP8266 and the TAOS TCS230 color-to-frequency module

This is a wifi enabled board that reads color components Red, Green and Blue of any material placed closed to the sensor.

The reading of the color components is done via a TCP request to the board and the percentage color component values are returned in a JSON string.

The sequence for reading is done by sending the following strings via TCP on port 9999:

acquire

(wait 5 seconds for acquisition to complete)

read

The return message is in JSON format as follows:

{“RGB”: [{ “Red:”: “53”, “Green”: “23”, “Blue:”: “24”}]}

each number representing the percentage of that color. The board can be configured via web browser without the need for a serial interface to program it!

This board can be purchased at Tindie, press here to go to Tindie store

Posted in Uncategorized | 2 Comments

ESP8266: Handling analog signals without an analog input, just GPIO!

Experimenting with the ESP8266 at one point I came across the need of dealing with analog signals. There are a lot of versions of the module and most of them have GPIO accessibility but not ADC access. Some of the lates versions of the module have ADC though, but I have a few modules in stock that do not have it. And I need ADC handling.

Well, it is totally possible and here is how to do it.

There are 4 basic things that need to be done:

  • convert the analog signal into pulse width modulation (PWM)
  • read the PWM on any GPIO
  • read the PWM duty cycle on the ESP8266
  • calibrate the PWM to analog level response

This module can be purchased at my Tindie store

IMG_5923

I am using NodeMCU Lua API. Lets look in more detail:

Convert the analog signal into pulse width modulation (PWM)

This is quite simple. The popular LM555 will do the trick. Here is the circuit:

Screen Shot 2015-04-20 at 11.37.38 AM

A sawtooth signal ramping up from 0 to 5v simulates the analog signal, the 555 spits out a PWM, with duty cycle proportional to the analog level. The 555 output is then connected to a GPIO pin.

Read the PWM on any GPIO

This is even simpler. Just pipe the output of the 555 to any GPIO pin.

Read the PWM duty cycle on the ESP8266

To do this, watch for the GPIO pin ‘up’ and ‘down’ events:

file.writeline([[gpio.trig(pin, 'both', callback)]])

In the callback function, read the pin, track the time when the up and downs happen and calculate the ratio, that is the duty cycle:

file.writeline([[time_read= time_read-time_base]])
file.writeline([[rp=gpio.read(pin)]])
file.writeline([[if cnt == 0 and rp == 0 then low_start=time_read]])
file.writeline([[end]])
file.writeline([[if cnt == 1 and rp == 1 then low_end=time_read]])
file.writeline([[end]])
file.writeline([[if cnt == 2 and rp == 0 then high_end=time_read]])
file.writeline([[high_start = low_end]])
file.writeline([[end]])
file.writeline([[cnt=cnt+1]])
file.writeline([[if (high_end-low_start) > 0 and cnt == 3 then]])
file.writeline([[duty = (100*(high_end - high_start))/(high_end-low_start)]])
file.writeline([[print("Duty: " .. duty) ]])
file.writeline([[cnt = 0]])

Read the PWM duty cycle on the ESP8266

Finally, pick a few calibration points between the PWM duty cycle you are reading and the actual analog signal value and calibrate the reading.

My prototypes are available on Tindie.

Posted in Uncategorized | 1 Comment

WIFI vibration sensor using the ESP8266

A simple vibration sensor can be connected to the ESP8266 GPIO pin and an alarm can be triggered via TCP to report vibration. This could be useful for a number of things, including industrial monitoring, security, etc. The prototype uses a sensor originally designed for Arduino, but can easily be connected to one of the GPIOs in the ESP8266. The firmware checks whether the GPIO has triggered and if so it sends a TCP message to a server listening. SSID and password for the WIFI can be programmed remotely via web as with my other prototypes and the nice things is that the server address and the port number the server is listening at can also be programmed remotely via web, no serial connection required and it is persistent!!!

 

VibSensor

Vibration switch

VibrationSensor1

Vibration switch connected to ESP8266 board

Screen Shot 2015-04-16 at 6.19.16 PM

TCP trigger received overtime there is a vibration

 Check my other and future boards on Tindie

 

Posted in Uncategorized | 2 Comments

Temperature and Humidity sensor and control using ESP8266-03

Temperature and humidity sensor and control

Temperature and humidity sensor and control

This module is available for preorder at Tindie click here

This project implements a temperature and humidity sensor using the ESP8266 WIFI module and a DHT11 temp/hum sensor.

The board can be configured via web in a similar way as previous projects. Connect to the  ESP8266 station (ESP8266-XXXXXXX) and on a web browser point to IP 192.168.4.1, then you are prompted to enter wifi network SSID and password. Within a few seconds, the IP address of the ESP8266 module will appear on the web page.

Any TCP message sent to the module IP address will return a JSON feed  with the current temperature and humidity:

{“dth11”: [{ “Temperature:”: “24”, “Humidity”: “39”,}]}

Now the interesting part. By sending a TCP special string, I can set a minimum and maximum temperature and humidity. When the minimum temperature is reached, then a relay is triggered; similarly, when the maximum temperature that has been set is reached, another relay is triggered and the other one is reset. The same can be done for humidity. Now we have a sensor that reacts.

The control string is of the form

LT=010-HT=020-LH=030-HH=060

and can be sent at any time to set the min/max limits, in return you always get the current temp and hum as

{“dth11”: [{ “Temperature:”: “24”, “Humidity”: “39”,}]}

A video of the project can be accessed here

Posted in Uncategorized | 20 Comments