This is only a preview of the December 2012 issue of Silicon Chip. You can view 24 of the 112 pages in the full issue, including the advertisments. For full access, purchase the issue for $10.00 or subscribe for access to the latest issues. Items relevant to "A 2.5GHz 12-digit Frequency Counter, Pt.1":
Items relevant to "USB Power Monitor":
Items relevant to "High-Energy Ignition System For Cars, Pt.2":
Items relevant to "High-Power Class-D Audio Amplifier, Pt.2":
Items relevant to "Modifications For The Induction Motor Speed Controller":
Items relevant to "Hacking A Mini Wireless Web Server, Pt.2":
|
Hacking A
Mini Wireless
Webserver; Pt.2
Interfacing external circuitry
and sending emails
By Andrew Snow & Nicholas Vinen
Last month, we explained how to hack the TP-LINK WR703N router
into a useful, tiny low-powered web server with built-in WiFi and
a USB port. Now we’ll show you an easy way to hook up some
external components such as sensors and relays via its USB port,
without even needing to open it up. We also explain how you can
set the router up to automatically send you emails.
I
N ORDER TO CONNECT external circuitry to the
WR703N, we use a Freetronics LeoStick. This is a
small Arduino-compatible module which uses an Atmel ATmega32U4 8-bit microcontroller. It plugs straight
into a USB port and provides six analog input pins and
14 digital input/output pins.
We’ve written some simple software that you can load
onto the LeoStick, so that you can then interrogate it and
change the output pin states via a USB virtual serial port.
It’s then quite a simple matter to get the “hacked” WR703N
router to send serial commands to the LeoStick in order
to interface with the external circuitry. The LeoStick can
either be plugged straight into the router’s USB host port
or it can be connected via a hub and/or extension cable.
The required software is available in a ZIP file which
can be downloaded from the SILICON CHIP website. You
will also need the Arduino software on your system – it
supports Windows, Mac OSX and Linux. We used version
1.0.1. Just follow the steps in the LeoStick getting started
guide at: http://www.freetronics.com/pages/leostickgetting-started-guide
With that up and running, you can then open the
“sketch” we have provided (LeoStick_serial_interface) and
90 Silicon Chip
upload it to the LeoStick using the File->Upload menu
option. If you run into trouble, refer to the Freetronics
LeoStick website guide.
Once the LeoStick has been programmed, boot up your
TP-LINK WR703N and connect to it using SSH (see Pt.1).
You should have already installed OpenWRT Linux, as per
the previous issue’s instructions. Install the driver for the
serial mode by first running the opkg update command
and then opkg install kmod-usb-acm. If you get an error,
refer to the panel later in the article for help.
Now plug the LeoStick into the WR703N and check that
it was recognised by running the following command via
SSH: dmesg | tail -n 5
It should respond with something like the following:
[ 72.530000] usbcore: registered new interface driver cdc_acm
[ 72.530000] cdc_acm: USB Abstract Control Model driver for
USB modems and ISDN adapters
[ 100.680000] usb 1-1: new full-speed USB device number 2
using ehci-platform
[ 100.840000] cdc_acm 1-1:1.0: This device cannot do calls on
its own. It is not a modem.
[ 100.840000] cdc_acm 1-1:1.0: ttyACM0: USB ACM device
siliconchip.com.au
Now it’s just a matter of programming the router to communicate with the LeoStick.
Temperature sensor
For the purposes of this example, we’re going to plug an
LM35DZ temperature sensor into the LeoStick and then set
up a web page where you can view the current temperature, with it automatically updating every 10 seconds. We
soldered the provided header socket strips to the LeoStick,
then bent the LM35DZ’s pins to fit into the 5V, GND and
A0 sockets (without them shorting). If you’d prefer, you
can simply solder the device to the pads.
The temperature sensor is just an example; there are a
lot of other things you could monitor this way, such as
battery voltages, light levels and so on. All you need do
is connect a voltage source to one of the LeoStick’s pins,
using a voltage divider if necessary (ie, if the voltage being
sensed can go over 5V).
The LM35DZ’s V+ pin goes to the 5V pad on the LeoStick, while the output pin goes to the A0 input pad. The
remaining pin is ground, so it is connected to the LeoStick’s
ground pad – see Fig.1.
Note that with this configuration, the temperature readings may be a touch high since the LeoStick board gets a
little warm during operation and this will conduct some
heat down the leads and into the LM35DZ. For a more
accurate reading, you might want to use a length of 3-core
flex (eg, ribbon cable) between the LeoStick and the sensor.
That might be more convenient to use anyway.
Lua scripting language
Now we need to read the voltage at the A0 pin of the
LeoStick, convert it to a temperature and display it on a
web page. We will use the Lua scripting language as this
will already be installed on your WR703N – it’s used for
the web configuration interface (“LuCI”). It’s also quite
suitable for the task.
To run a Lua script when a website URL is accessed, we
create a “CGI” or “Common Gateway Interface” file. This
requires us to place the script file, called “temperature”,
in the /www/cgi-bin directory on the WR703N, or a subdirectory of it. The script file contains a number of lines
of text, which form the instructions telling the WR703N
what to display when that URL is accessed. The script we
have used is as follows:
#!/usr/bin/lua
print("Content-type: text/html\nRefresh: 10\ n")
print("<HTML><HEAD><TITLE>Temperature monitor</TITLE>")
print("</HEAD><BODY>The temperature is: ")
local f = io.open("/dev/ttyACM0", "r+")
f:write("quiet\n")
f:write("A0?\n")
print(f:read("*line")*100 .. "°C.</BODY></HTML>")
f:close()
The first line tells the system that this is a Lua script.
The second line tells the web browser to process the output
as HTML (Hypertext Markup Language) and to re-load the
page every 10 seconds, to refresh the reading. The next
two lines set the web page title and provides the initial
text to display.
We then open the serial port (the /dev/ttyACM0 file)
siliconchip.com.au
5V
LEOSTICK
LM35DZ
(3) +VS
A0
GND
VOUT
(2)
LM35
(1) GND
VOUT
GND
+VS
Fig.1: here’s how to connect the LM35DZ temperature
sensor to the LeoStick. It doesn’t get any easier than
this!
These photos show the
LM35DZ sensor connected
to a LeoStick module at top
and a USB Teensy at left
and set the LeoStick software to “quiet” mode, so it won’t
send error messages if something goes wrong. That’s necessary because for some reason, the WR703N “echoes” the
output of the LeoStick back to it and we need it to ignore
that extraneous data and respond only to the commands
we are sending it.
We then send it a query to read the value of the A0
analog input pin. We then read the response, which is in
volts, and multiply it by 100 to turn it into a temperature
in degrees Celsius (the LM35DZ’s output is 10mV/°C). The
result is output to the web browser, followed by the final
text and HTML tags.
As mentioned earlier, these lines go in a file called
“temperature” which goes into the /www/cgi-bin directory
on the WR703N. You can copy it over using OpenSCP, as
explained last month. The script is available in a ZIP file
in the downloads section of the SILICON CHIP website.
Before you can use the script, it must be marked as “executable” or else the browser will refuse to run it. This is
done with the following command, via the SSH interface:
chmod u+x,g+x,o+x /www/cgi-bin/temperature
With the LeoStick plus the LM35DZ plugged into the
WR703N’s USB port, you should now be able to access
http://192.168.1.123/cgi-bin/temperature (replacing
192.168.1.123 with the address of your WR703N) and
get a temperature readout which automatically updates
every 10 seconds.
Higher voltages
We mentioned earlier that you could also monitor a
battery voltage in a similar fashion to the output of the
temperature sensor. For voltages that will always be below
5V, you can simply connect them to one of the LeoStick’s
analog input pins, in addition to the required ground connection to the voltage source.
December 2012 91
VOLTAGE
TO MONITOR
(UP TO 15V)
Fig.2: circuit for
monitoring voltages
above 5V using the
WR703N and a
LeoStick. For voltages
above 15V, the 22kΩ
resistor value must be
increased.
22k
A0
10nF
LEOSTICK
10k
GND
TO RELAY
COIL SUPPLY
VOLTAGE
RELAY1
K
D1
1N4004
A
LEOSTICK
1.5k
D0
B
C
E
GND
Q1
BC337
BC337
B
1N4004
A
K
E
C
Fig.3: this simple circuit shows how a relay or relays
can be connected to the WR703N via a LeoStick, so
that you can remotely turn those relays on or off.
But say you want to monitor something that could go
over 5V, such as a 12V lead-acid battery. In that case you
will need the circuit shown in Fig.2. You will then need
to scale the reading from the LeoStick by a factor of (22kΩ
+ 10kΩ) ÷ 10kΩ = 3.2 to get your voltage reading.
This can easily be done in the script by simply changing
the “*100” scale factor used for the temperature sensor,
to “*3.2”.
For even higher voltages you will need to increase the
value of the 22kΩ resistor and adjust the software voltage
scale factor to suit.
Controlling relays
It could also be useful to have the WR703N control some
relays or other external equipment. These relays could be
turned on and off remotely, via a web page. Another possibility is to program the router to automatically switch
relays based on a voltage level or other input but we won’t
go into that here, at least not yet; we’ll leave it as an exercise for you, the reader.
The LeoStick can in theory drive small 5V relays directly
as each pin can source or sink at least 20mA and in practice, a little more than that. But for most applications it is
better to use a small external transistor to switch the relay
coil. This way you can also use higher voltage relays (eg,
12V), assuming you have a an appropriate voltage source
to drive the relay coils, such as a DC plugpack.
Fig.3 shows the basic configuration. The output pin
drives a BC337 NPN transistor via a current-limiting resistor. When that output is high, the transistor’s base-emitter
junction is forward biased and the transistor turns on,
sinking current through Q1’s collector-emitter junction
92 Silicon Chip
and closing the relay’s NO contacts.
When the output goes low, Q1 switches off and the current through the coil is interrupted, switching the relay off.
The coil generates a back-EMF spike which is absorbed
by diode D1. By the way, if you don’t want to build the
relay drive circuitry yourself, you can get a 4-channel relay
driver module designed to interface with Arduino systems
(Jaycar Cat. XC4278).
Then we need to write a script which can tell the LeoStick to change the state of one of its output pins; the one
for the relay control circuitry. Luckily, the software we
have already loaded on the LeoStick can do this job too,
so our script, called relay, looks like this:
#!/usr/bin/lua
print("Content-type: text/html\n")
print("<HTML><HEAD><TITLE>Relay control</TITLE>")
print("</HEAD><BODY>")
local f = io.open("/dev/ttyACM0", "r+")
f:write("quiet\n")
if os.getenv("QUERY_STRING"):upper() == "ON" then
f:write("D0=1\n")
print("Relay is now on.")
elseif os.getenv("QUERY_STRING"):upper() == "OFF" then
f:write("D0=0\n")
print("Relay is now off.")
else
print("Error.")
end
f:close()
print("</BODY></HTML>\n")
Again, this file should go in /www/cgi-bin and the
chmod command must be used to make it executable (see
earlier example). This script is also available for download
from the SILICON CHIP website.
With that file in place, you can go to the following URL
to turn the relay on: http://192.168.1.123/cgi-bin/relay?on
(again, change the address to match yours) and to turn it
off, visit: http://192.168.1.123/cgi-bin/relay?off
The text after the ? on the address bar is called the
query string and this is accessed in the CGI script via the
os.getenv(“QUERY_STRING”) call. We then convert it to
upper case and check if it is “ON” or “OFF”. If it matches
either, we send an appropriate command to the LeoStick
to change its output pin state.
Rather than having to remember these URLs, you can
place them as links in a separate HTML file on the WR703N
and then you just need to click the link to turn the relay on
or off. To control multiple relays, you could create more
than one script file with different names, to suit what the
relay controls, and change the two instances of “D0” to
refer to a different output pin.
Control interface
If you don’t want to fiddle with writing scripts, you
can use the control interface script that we have devised,
named control. This can be placed in the cgi-bin directory
and when you access it, it displays the voltage at all the
analog pins and the state of all the digital pins (see Fig.4).
You can also force the digital pins high or low, or set
them back to high-impedance to allow them to operate
as inputs. You can also turn the micro’s internal pull-up
siliconchip.com.au
Using A Teensy Instead Of The LeoStick
The USB Teensy is a USB-based development board for
Atmel microcontrollers. It pre-dates the LeoStick and is what
we were using when we first started writing this series of
articles. As well as being smaller than the LeoStick, it’s also
cheaper but to get it at the lower price, you need to order it
from overseas (it’s still cheaper even when you take the postage into account).
The Teensy also has more input and output pins than the
LeoStick; there are 25 in total, including 12 analog inputs and
seven PWM-capable outputs. It draws just 5mA (ie, about
25mW at 5V). It’s available from the USA for about $23 delivered, from the maker’s own web site: http://pjrc.com
The Teensy comes supplied already flashed with its the
“HalfKay” boot loader software, which makes it simple to reprogram it via USB from any PC (Mac, Windows, and Linux
supported). As well as its function as a microcontroller development board, the Teensy v2 is also (mostly) Arduino-compatible.
We were able to make the serial interface code work on
both the LeoStick and the Teensy 2 with just a minor change.
If you want to use the Teensy, follow the instructions as for
the LeoStick but then after installing the Arduino software,
you will also need to put the “Teensyduino” software on your
system. You can get it here: http://www.pjrc.com/teensy/
teensyduino.html
It will also install a serial port driver for the Teensy, which
is different to the one used for the LeoStick.
Once that’s all done, load up the provided sketch in the
Arduino software and then go to the “Tools” menu and under
the “Board” item, select “Teensy 2.0”. Then, verify the sketch
using the tick icon in the upper-left corner of the window. Once
you’ve done that, a small separate window should appear,
asking you to press the button on the Teensy to activate it.
Plug in the Teensy, wait a few seconds, then press the button. It should say “Programming . . .” and then “Reboot OK”.
You can then unplug the Teensy from your computer and it is
ready to use with the WR703N.
resistors on each input pin either on or off.
Note that this control script gives you access to the full
set of available analog and digital pins, not all of which are
broken out to pads on the LeoStick (see Fig.4). A larger set of
these pins are available on the Teensy module (see panel).
Just ignore those which your unit lacks, or else you can
modify the script so it doesn’t display them if you prefer.
With this control script, you can experiment with the
WR703N/LeoStick combination and check that everything
works OK. You can customise the script to suit your purposes later, if you want to.
Password protection
Now you probably don’t want to give just anyone with
internet access the ability to control your relays (or whatever)! So it will be a good idea to add password protection
to your site for this kind of task. Luckily this is pretty easy
to set up. Using the SSH command shell to the router, enter
the following commands:
uci set uhttpd.main.config=/etc/httpd.conf
uci commit uhttpd
echo '/:username:password' >> /etc/httpd.conf
/etc/init.d/uhttpd reload
Replace “username” and “password” with the name and
password that you want to use to access the site. Note that
this will password-protect the entire OpenWRT website,
including the web configuration interface. Not only will
you need to provide this username/password combination
to access the web interface but you will also have to log
in as root in the usual manner after that.
If you want to protect just a subset of the files with a
particular password, you can do that too. Say you have
files in /www/myfiles and you access them via the URL
http://192.168.1.123/myfiles/ You can change the password
setting command to this:
echo '/myfiles:username:password' >> /etc/httpd.conf
siliconchip.com.au
Fig.4: our sample control interface which shows the
voltage on each of the analog input pins of the LeoStick or
Teensy (A0-A11) and the state of the digital pins (D0-D13).
You can also change the direction and level of the digital
pins by clicking the links. Note that A0 has an LM35DZ
temperature sensor connected, reading 24°C (240mV).
In this manner, you can protect multiple different directories of files using different passwords.
Sending emails
You might want to have the WR703N email you on
certain events, eg, excessive temperature or low battery
voltage. As an example, let’s set it up to send an email if
the temperature exceeds 40°C.
December 2012 93
the temperature say every 15 minutes. To do this, we use
the Scheduled Tasks feature of OpenWRT, available under
the System section of the web interface (see Fig.5). This
lets you edit the “crontab” Linux system file, which tells
it what commands to run at what times.
For this to work, you must ensure that the “cron” service
is Started and Enabled under the Startup section (also in
the web interface), and you must also click the Restart button to reboot the router whenever you make any changes
to the Scheduled Tasks.
The format of the Scheduled Tasks section is one line
per command, with five numbers at the front to specify
when to run the command. These represent Minutes,
Hours, Day of month (1-31), Month (1-12), Day of week
(0-6). An asterisk (*) can be used to indicate that you don’t
care about that particular field. To run the command above
every 15 minutes, you would add this line:
*/15 * * * * lua /root/checktemp.lua
Fig.5: the WR703N’s LuCI Scheduled Tasks page which
lets you set up scripts to run periodically. These scripts
can then send emails depending on the state of the inputs.
Sending email from OpenWRT is easy as long as you
know your email server’s IP address. First, run the command opkg install mini-sendmail via SSH to get the mailsending software. Next, you need a script to check the
temperature and send an email. Call it checktemp.lua
and place it in the /root directory. The contents look like
this:
local f = io.open("/dev/ttyACM0", "r+")
f:write("quiet\n")
f:write("A0?\n")
local temp = f:read("*line")*100
f:close()
if( temp > 40 ) then
local email = "example<at>gmail.com"
local server = "gmail-smtp-in.l.google.com"
local mail = assert(io.popen("/usr/sbin/sendmail -s"..server..
" "..email, "w"))
mail:write("Subject: Temperature too high!\n")
mail:write("To: "..email.."\n")
mail:write("\n")
mail:write("The temperature reading is currently "..temp..".\n")
mail:close()
end
The first few lines read the temperature from the LeoStick. Then if the temperature is too high, we open the
Sendmail software and write the contents of an email into
its input. You should change the email address and email
server settings to suit your own mail service.
If you’re using Google gmail, then you can leave the
server setting as it is. If you don’t know the (SMTP) mail
server address, you can usually look it up by asking your
ISP or Googling it.
You’ll want to run this command periodically, to check
94 Silicon Chip
If you want to check that it’s working you can simply
edit the Lua script to lower the temperature threshold
below the normal temperature. Once you have verified
that you are receiving emails, change it back to the actual
threshold you want to use.
Short-term logging
Now let’s say you want to be able to see what the temperature was every minute of the day but you don’t want
to be innundated with emails. What you need to do in this
case is log the temperature readings to a file in memory,
along with the date and time. We then periodically send
the contents of that file via email.
Let’s look at how to do that. First, the logging script,
located in /root, is called templog.lua and looks like this:
local f = io.open("/dev/ttyACM0", "r+")
f:write("quiet\n")
f:write("A0?\n")
local temp = f:read("*line")*100
f:close()
f = io.open("/tmp/temperature.log", "a+")
f:write("["..os.date("%d/%m/%Y %X").."] Temperature is "
..temp.."C\n")
f:close()
The first part of the script should look familiar. The
second part opens the log file in append mode (ie, to add
lines to the end of the file) and then writes the date, time
and temperature to it. We’re putting the log file in the
/tmp directory since this is stored in RAM rather than
flash memory and so it won’t wear out the flash if we are
constantly writing to a file at this location. The cron entry
under Scheduled Tasks then looks like this:
*/1 * * * * lua /root/templog.lua
Next, we create a script which will periodically email
that log file to our address. Let’s call it sendlog.lua, again
located in the /root directory:
local email = "example<at>gmail.com"
local server = "gmail-smtp-in.l.google.com"
siliconchip.com.au
OpenWRT Beta Issues
The LeoStick with its temperature
sensor plugs into the WR703N’s
USB port. The WR703N can be
set up to send an email if the
temperature (or some other logged
event) exceeds or drops below a
set value, or it can email at log a
set intervals – see text.
local logfile = "/tmp/temperature.log"
local f = io.open(logfile, "r")
local mail = assert(io.popen("/usr/sbin/sendmail -s"..server..
" "..email, "w"))
mail:write("Subject: Temperature log\n")
mail:write("To: "..email.." \n")
mail:write(" \n")
while true do
local line = f:read()
if line == nil then break end
mail:write(line.."\n")
end
mail:close()
f:close()
os.remove(logfile)
As before, change the email address and possibly the
server name to match your mail service. Then we just
need to set this up to run every hour, on the hour, in the
Scheduled Tasks list with an entry like this:
0 */1 * * * lua /root/sendlog.lua
Remember to reboot the WR703N after making these
changes and voila, you will get an hourly temperature log
with one entry per minute.
More possibilities
We’ve covered quite a bit in this article but there are
still lots of things that the WR703N can do that we haven’t
really explained. That includes playing and recording
audio, 3G wireless communications and a whole host of
other tasks that can be performed with the appropriate
USB peripherals attached.
If there’s sufficient interest from readers, we’ll cover
SC
some of these possibilities further down the track.
siliconchip.com.au
The version of OpenWRT which runs on the TP-Link
WR703N, “Attitude Adjustment”, is still in beta status. That
means that it may still contain bugs. It also means that it’s
constantly changing.
If you install the OpenWRT snapshot onto a WR703N
device and the authors make significant changes to Attitude
Adjustment, you may find that you can no longer install
certain packages. That’s because the packages on their
website will no longer be compatible with the kernel installed
on your router (the kernel is the part of the operating system
that is constantly running).
So until it’s no longer in “beta”, it’s better if you install the
system and all the packages you need at once, to avoid this
problem. If you do run into kernel compatibility problems,
you will get a message like this when trying to install a new
package:
root<at>OpenWrt:~# opkg install kmod-usb-acm
Installing kmod-usb-acm (3.3.8-1) to root...
Downloading http://downloads.openwrt.org/snapshots/trunk/
ar71xx/packages/kmod-usb-acm_3.3.8-1_ar71xx.ipk.
Collected errors:
* satisfy_dependencies_for: Cannot satisfy the following
dependencies for kmod-usb-acm:
* kernel (= 3.3.8-1-2f68a23229e31667f00b2a0a65027c00) *
* opkg_install_cmd: Cannot install package kmod-usb-acm.
The easiest way to solve this problem is to do a “Sysupgrade”. To do this, you download the upgrade version of
the Attitude Adjustment snapshot (from the same location
as explained in the previous article). Then go to the web
interface of the WR703N and under the System tab, go to
the “Backup / Flash firmware” sub-tab.
Before you do the upgrade, though, be sure to back up
all the files you have put on the device (eg, in /var/www)
using OpenSCP. They will be wiped by the upgrade. For
details on setting up and using OpenSCP, refer to last
month’s article.
Use the “Browse” button in the “Flash new firmware image” section of the web interface to select the snapshot you
downloaded earlier and click the “Flash image” button. You
will be asked if you want to back up the system settings; you
should do so. The process takes only a couple of minutes.
Once the latest version of the software is up and running,
you can copy your files back onto the router and re-install
any software packages you had installed previously (they
are also wiped by the upgrade). You should then be able
to successfully install the package(s) that were previously
giving you errors.
Where To Get A LeoStick
The Freetronics LeoStick is available from Jaycar for $29.95 (Cat.
XC4266) and includes the two low-profile female pin headers shown
in the photos. You can also get the LeoStick Prototyping Shield
pack for $7.95 (Cat XC4268). This includes the matching male
pin headers plus a small “protoboard” that can be plugged into
the LeoStick to carry the voltage dividers or relay drivers shown
earlier in this article, if required. For more information, see www.
freetronics.com
December 2012 95
|