Picaxe to internet via TP-Link WR703N router with openWrt

lbenson

Senior Member
While we're waiting for our Raspberry Pi, here's another option for going to the internet from the picaxe via usb serial with a small device running the linux openWrt operating system--the TP-Link WR703N. This tiny computer has usb, an ethernet socket, and wireless, for $24.20US shipped with openWrt pre-installed.

http://www.volumerates.com/product/tp-link-tl-wr703n-openwrt-compatible-pocket-11n-150m-3g-mobile-wireless-broadband-router--blue-ship-with-openwrt-pre-installed-upon-customers-request-103048

Here is my little setup:


I use a usb-to-ttl-serial dongle which also provides 5 volts (or 3.3) to the picaxe. This is available here from ebay for $2.88US shipped: http://www.ebay.com/itm/USB-2-0-UART-TTL-6PIN-Connector-Module-Serial-Converter-CP2102-New-/350499583299?pt=LH_DefaultDomain_0&hash=item519b673543

This particular picaxe board reads a single DS18B20 temperature sensor, but my standard programming allows for 3 temperature sensors per board, so I send changed values as a 1-byte code and three temperatures separated by spaces. In this case, I just repeat the one temperature 3 times, so a reading might be "A 23 23 23". This means that sensor "A" returns a temperature of 23C.

I send a newline charactor (0xa) at the end of each line. This allows for a simple script to read each line, break it into 4 values, and append a time-stamp before appending it to a log file. I have another program running on the TP device every 5 minutes, which reads the log file, updates a web page, and sends an email if the temperature gets out of range high or low. Here is the script for reading the serial input:

Code:
#!/bin/sh
stty -F /dev/ttyUSB0 2400 clocal cread cs8 -cstopb -parenb -crtscts
cat /dev/ttyUSB0 2>/dev/null | while read v1 v2 v3 v4; do
  echo "$v1 $v2 $v3 $v4 $(date +%y%m%d%H%M%S)" >> /home/user0/Rx01.txt
done
For each line input, the output of this script will be something like "A 23 23 23 120127142342". The "stty" command sets the serial parameters--2400 bps, etc.

There is a drawback to openWrt on the WR703N--it doesn't come with the proper serial driver for the usb dongle I use, and it lacks the "stty" command. For most openWrt devices, these commands could be downloaded, but not for the WR703N. I intend to post to the developers to ask that they be included, but in the meantime, it is necessary to build your own version of openWrt--something I have done dozens of times for a half-dozen different devices, but not necessarily trivial for first-time users. If there is interest, I might be able to host an image somewhere which could be flashed.

The picaxe code is not necessarily of much interest--anything which sends serial could be used. My program is a mangled mess which has grown and shrunk over the course of 3 years or so. My latest addition was to try to get rid of dithering around a degree change by doing readtemp12, and making sure that there has been a change of at least a whole degree before sending an update. The program has the remnants of code which was intended to minimize power usage for running on batteries--not an issue now with power from the WR703N's usb port.

Code:
' 08TxM2D3f: DS18B20 to dock81 hardwired with cp210x 120123
'  C  send if change in readtemp12 > 0xF
'     or if from/to 0, if >= +1 or <= -1
'  inTemp1Pin on 1, out with sertxd on pin 0, 4800
'  for wl60, Milton 2nd floor monitor

#picaxe 08M
'      task IDs--different for each sensor detector module
symbol MyMsgNo1 = "F" ' DR temp & upstairs temp
symbol MyMsgNo2 = "P" ' Battery level
symbol TxMode = 1     ' 1=3 retries, no Rx; 2=Rx
symbol baudrate = T2400_4 

symbol bNegativeFlag     = bit0
symbol bLastNegativeFlag = bit1
symbol bSendMsgFlag      = bit2
symbol bChangeFlag       = bit3

symbol Flags = b0      ' reserved for bit values
symbol MsgNo= b1
symbol inTempPin = b1
symbol passCount = b2
symbol Tmpvar = b3
symbol Temp12 = w2 ' b4 & b5
symbol lastTemp12 = w3 ' b6 & b7
symbol Data1= b8 ' temperature data
symbol Data2= b9 ' temperature data
symbol Data3= b10 ' used for temperature
symbol timePeriod = b11 ' major loop counter of 6-minute periods--240 per day
symbol TempDiff = w6 ' b12 & b13

'output pins 0-5
symbol onLED = 0  ' output
symbol Tx433 = 0  ' output
symbol TxRS232 = 4  ' output
symbol inTemp1Pin = 1  ' ds18b20
'symbol inTemp2Pin = 4  ' ds18b20
'symbol inTemp3Pin = 2  ' ds18b20

symbol ADCON0 = $1f   ' ADC control SFR register to turn off ADC module
symbol OSCCON = $8f   ' Oscillator control SFR register for speed up/down

' register memory 0x50 - 0x7e (peek/poke--prefix 'r')
symbol rlasttemp1 = 0x50 ' & 0x51
symbol rlasttemp2 = 0x52 ' & 0x53
symbol rlasttemp3 = 0x54 ' & 0x55

start:
'pause 1000
'disablebod
'disconnect
initiate:   ' or roll over to new day by rough counting
'  sertxd("Module ",MyMsgNo1,CR,LF)
  timePeriod = 239  ' set to roll to effective end of 24 hours
'  high onLED
  pause 4000
'  low onLED
  sertxd("08TxM2D3",MyMsgNo1,lf)
newday:  ' once a day, resend all
  lastTemp12 = 0xffff
  poke rlasttemp1, word lastTemp12
  poke rlasttemp2, word lastTemp12
'  poke rlasttemp3, word lastTemp12
'  lastTemp12_1 = 254
'  lastTemp12_2 = 254
'  lastTemp12_3 = 254
    
main:
  do   ' this loop completes about once every 6 minutes
'   for b2 = 0 to 4
'    scratchb13 = rlasttemp1 + b2
'    peek scratchb13, lasttemp
    bSendMsgFlag = 0
    inTempPin = inTemp1Pin
    peek rlasttemp1, word lastTemp12
    gosub checkTempChange
    if bchangeFlag = 1 then
      poke rlasttemp1, word lastTemp12
      Data1 = Temp12 / 16
      bSendMsgFlag = 1
    endif
'    inTempPin = inTemp1Pin
'    peek rlasttemp2, word lastTemp12
'    gosub checkTempChange
'    if bchangeFlag = 1 then
'      poke rlasttemp2, word lastTemp12
'      Data2 = Temp12 / 16
'      bSendMsgFlag = 1
'    endif
    if bSendMsgFlag = 1 then
;      readtemp inTemp1Pin,Data1
'      readtemp inTemp2Pin,Data2
'      readtemp inTemp3Pin,Data3
      gosub TxData
    endif
'sleep 130 ' 5 minutes
'sleep 26 ' 1 minute
pause 3000
'pause 60000 ' one minute
'pause 60000 ' one minute
'pause 60000 ' one minute
'pause 60000 ' one minute
'pause 60000 ' one minute
'   next b2
'  goto initiate  ' for testing
#rem
    inc timePeriod
    if timePeriod = 240 then   ' approximately 24 hours
      timePeriod = 0  ' reset
      b0 = 0  ' reset all flags for day
      goto newday
    endif
#endrem
  loop
  
TxData:
'  MsgNo = MyMsgNo1
  serout TxRS232,baudrate,(MyMsgNo1," ",#Data1," ",#Data2," ",#Data1,lf)
  sertxd(MyMsgNo1," ",#Data1," ",#Data2," ",#Data1,lf)
  return

checkTempChange:
    bChangeFlag = 0
    readtemp12 inTempPin,Temp12
' 0 and 85 are common erroneous values
    if Temp12 = 0 then ' check again
      pause 500
      readtemp12 inTempPin,Temp12
      if Temp12 = 0 then
        pause 500
        readtemp12 inTempPin,Temp12
      endif
    endif

    bNegativeFlag = Temp12 & $f800 / 2048 ' 1 if negative
    bLastNegativeFlag = lastTemp12 & $f800 / 2048 ' 1 if negative
    if bNegativeFlag = bLastNegativeFlag then ' look for dif >0xf
      if Temp12 > lastTemp12 then
        TempDiff = Temp12 - lastTemp12
      else
        TempDiff = lastTemp12 - Temp12
      endif
      if TempDiff > 15 then
        bchangeFlag = 1
'sertxd("1 ",#Temp12," ",#lastTemp12," ",#TempDiff," ",#b0)
      endif
    else  ' change of sign: look for new or old > 0
      lastTemp12 = lastTemp12 & 0x07ff / 16
      if lastTemp12 > 0 then 
        bchangeFlag = 1
      else
        lastTemp12 = Temp12 & 0x07ff / 16
        if lastTemp12 > 0 then 
          bchangeFlag = 1
        endif
      endif
'sertxd("2 ",#Temp12," ",#lastTemp12," ",#TempDiff," ",#b0)
    endif
    lastTemp12 = Temp12
  return
The WR703N is connected wirelessly to my network.

This device would also be perfect for implementing the "openbridge" concept of steliosm, as shown here: http://www.picaxeforum.co.uk/showthread.php?15907
 

lbenson

Senior Member
A couple of updates here. The openWrt package complement has now been filled in for the WR703N, so it is no longer necessary to build your own system to flash--you can use use openWrt if you buy a version which comes installed on the device, or you can flash a pre-built version from snapshots. Then from the device you can install needed packages--for my purposes, the serial drivers, coreutils-stty, kmod-usb-serial-ch341, kmod-usb-serial-cp210x, kmod-usb-serial-pl2303 (for various usb serial dongles).

A problem with the usb-to-ttl-serial device which I used (based on cp210x) is that it idles high, and so is not suitable for programming a picaxe. I have just ordered some similar dongles which are based on the PL2303. The PL2303s which I have with DB9 connections idle low, and can be used for programming. Here is what I have ordered:

http://www.ebay.com/itm/PL2303HX-USB-TTL-Converter-Module-/180734359719?pt=LH_DefaultDomain_0&hash=item2a149b78a7

This one may also idle high, so a modification of the configuration of the chip might be needed. I have a slight preference for the upright headers on this version over the right-angle headers of the other I used.
 

mch

New Member
Hello. Do you have a circuit design for the PICAXE circuit you can share? Also, can you share your OpenWRT network configuration? I've been able to get mine setup as a client, but I'm having trouble getting the web server exposed to the wireless side - even with the firewall turned off, it only responds when I'm connected with an Ethernet cable. I really like the 703N as a wireless gateway to PICAXE, and the serial adapter is a great idea - its just too bad they take so long to come from China!

Thanks!
Matt

A couple of updates here. The openWrt package complement has now been filled in for the WR703N, so it is no longer necessary to build your own system to flash--you can use use openWrt if you buy a version which comes installed on the device, or you can flash a pre-built version from snapshots. Then from the device you can install needed packages--for my purposes, the serial drivers, coreutils-stty, kmod-usb-serial-ch341, kmod-usb-serial-cp210x, kmod-usb-serial-pl2303 (for various usb serial dongles).

A problem with the usb-to-ttl-serial device which I used (based on cp210x) is that it idles high, and so is not suitable for programming a picaxe. I have just ordered some similar dongles which are based on the PL2303. The PL2303s which I have with DB9 connections idle low, and can be used for programming. Here is what I have ordered:

http://www.ebay.com/itm/PL2303HX-USB-TTL-Converter-Module-/180734359719?pt=LH_DefaultDomain_0&hash=item2a149b78a7

This one may also idle high, so a modification of the configuration of the chip might be needed. I have a slight preference for the upright headers on this version over the right-angle headers of the other I used.
 

lbenson

Senior Member
Sorry to be late in replying. My simple circuit is as shown in the photo in the first post--a ds18b20 on pin 4, and serial out on pin 2. Otherwise, power and ground come from the cp2101 usb-to-serial board. The circuit is on a 14M board I made, but I'm just using an 08M.

I haven't used a web server on this yet--I'm just sending temperature changes to the wr703n, which then emails me once a day, or right away if an emergency condition is detected. I tried putting up a web server this morning and connecting wirelessly, but I couldn't get to it--tho obviously it can get out to send the email, and I can ping www.google.com and "opkg update" to download packages from openWrt. I don't know what's up with that. I'll get back to it, since it's something I want to do, but it may be several days (every time I want to do something, two other things have to be done first, and each of those requires two other things, and so on).
 

lbenson

Senior Member
Sorry to be so long in getting back with an answer regarding web serving.

Wifi and lan appear to need to be on separate networks. I put wifi on 192.168.1.51 and wired on 192.168.0.51. Here are the config files.

cat /etc/config/wireless
Code:
config wifi-device  radio0
        option type     mac80211
        option channel  auto
        option macaddr  38:83:45:d3:10:4c
        option hwmode   11ng
        option htmode   HT20
        list ht_capab   SHORT-GI-20
        list ht_capab   SHORT-GI-40
        list ht_capab   RX-STBC1
        list ht_capab   DSSS_CCK-40
        # REMOVE THIS LINE TO ENABLE WIFI:
#       option disabled 1

config wifi-iface
        option device   radio0
        option network  wireless
        option mode     sta
        option ssid     Omnibus1
        option encryption none
cat /etc/config/network
Code:
config 'interface' 'loopback'
        option 'ifname' 'lo'
        option 'proto' 'static'
        option 'ipaddr' '127.0.0.1'
        option 'netmask' '255.0.0.0'

config 'interface' 'lan'
        option 'ifname' 'eth0'
        option 'type' 'bridge'
        option 'proto' 'static'
        option 'ipaddr' '192.168.0.51'
        option 'netmask' '255.255.255.0'
        option 'dns' '8.8.8.8'
        option 'gateway' '192.168.1.1'

config 'interface' 'wireless'
       option 'ifname' 'radio0'
#       option 'proto' 'dhcp'
       option 'proto' 'static'
       option 'ipaddr' '192.168.1.51'
       option 'netmask' '255.255.255.0'
       option 'dns' '8.8.8.8'
       option 'gateway' '192.168.1.1'
With this setup, with no ethernet connected to the WR703N, I can ssh to 192.168.1.51 and can browse to the same address to view web pages. I made no changes to the firewall settings.
 

mrburnette

Senior Member
Wifi and lan appear to need to be on separate networks.
lbenson: if the WiFi has a router integral to the unit (most have, excepting Access Points) then your statement about separate sub-nets is correct. Here I have WiMax after the internal router/firewall output on 192.168.15.1 and the DHCP is set for only 2 addresses: 1, 2 so that I can manager the Moto modem even if connected to my Cisco Wireless/4-port device. I have the Cisco set to turn off the firewall (reduces latency) but the output of the router is 192.168.100.100 with management on address 100.254. The Cisco is WiFi is "G" and I have two access points feeding the remainder of the property: "N" and "A/B". I mucked around with an old Netgear wireless router and managed to configure it to work as a quasi-accesspoint rather than a router, but I got annoyed after getting it working because trying to document all of the settings is just too ugly.

- Ray
 

lbenson

Senior Member
Thank you for the comments. The TP-Link WR703N is working fine with the wireless I have set up, accessible for anything through the wireless link, including using a web page to send commands to a picaxe. If it should become unavailable through wireless, I would have to change the ip address on my laptop (no big deal) to be able to access it via wire to reconfigure. It's a nice little device (about 2 1/4 inches square by an inch high.
 

craigcurtin

Senior Member
Did you get anywhere with this Pl2303 version ?

A couple of updates here. The openWrt package complement has now been filled in for the WR703N, so it is no longer necessary to build your own system to flash--you can use use openWrt if you buy a version which comes installed on the device, or you can flash a pre-built version from snapshots. Then from the device you can install needed packages--for my purposes, the serial drivers, coreutils-stty, kmod-usb-serial-ch341, kmod-usb-serial-cp210x, kmod-usb-serial-pl2303 (for various usb serial dongles).

A problem with the usb-to-ttl-serial device which I used (based on cp210x) is that it idles high, and so is not suitable for programming a picaxe. I have just ordered some similar dongles which are based on the PL2303. The PL2303s which I have with DB9 connections idle low, and can be used for programming. Here is what I have ordered:

http://www.ebay.com/itm/PL2303HX-USB-TTL-Converter-Module-/180734359719?pt=LH_DefaultDomain_0&hash=item2a149b78a7

This one may also idle high, so a modification of the configuration of the chip might be needed. I have a slight preference for the upright headers on this version over the right-angle headers of the other I used.
Wondering if you found out if this does indeed idle high or not ?

Also do you know anywhere else to source these routers at a reasonable price - Volumerates is not taking orders at the moment

Craig
 

lbenson

Senior Member
Yes, the PL2303 usb/serial dongle (not db9) does idle high--at about 1.8 volts when set for 3V3, and about 3 volts when set for 5V (per my cheap DMM--I haven't looked at it with a scope).

Ebay has these devices--but at higher prices than volumerates offers.
 

mch

New Member
Hello.
So I've got my TP-Link working, I have my USB to serial converter and my PICAXE proto board. I'm trying to make my test setup simple. I have a 20M2 with a ds18b20 and a HIH-4000 humidity sensor. I can verify with a simple debug command that both are reading correctly.
I've got the RXD pin from the USB to serial converter connected to the SEROUT, pin #19, per the PIXAXE manual.

My test code is as follows:
Code:
main: low 0 ; off LED
	pause 1000
	high 0 ; on LED
	readtemp C.1, b1
	readadc C.2, b2 ; read in humidity value from HIH-4000
	b3 = b2 - 41 * 100 / 157 ; convert to %RH
	sertxd ("The RH value is ",#b3,cr,lf)
	sertxd ("The temp value is ",#b1,cr,lf)
	;debug
	pause 1000
	goto main
On the TP-Link, from the ssh session, I've run these commands from the shell prompt:
Code:
stty -F /dev/ttyUSB0 2400 clocal cread cs8 -cstopb -parenb -crtscts
cat /dev/ttyUSB0
I'm expecting to see the output from my PICAXE code, but nothing ever shows up. If I hit simulate in the PICAXE programmer, the serial output buffer windows shows the output I would expect to see.

Am I doing something obviously wrong? From the picture you have above, it looks like you don't have anything connected to the RXD pin on the USB to Serial converter. I've tried the using the TXD pin, but I don't get anything from it either, and it seems to me I want the USB converter to RECEIVE the messages from the PICAXE, so I should be using RXD, right? The only other problem might be the pin on the PICAXE, but I'm #19 on the 20M2, which is "A.0/Serial Out" according to the manual.

As a side not, I'm also curious, but isn't the 5V you are using from the USB cable to the PICAXE too much for it? Doesn't it need to be closer to 4.5V?

I'd appreciate any help.

Thanks!
Matt
 

lbenson

Senior Member
For sertxd, the baud rate is 4800. Try that.

Except for those picaxes which are limited to 3.3 volts, 5 volts is fine. 4.5 is what you nominally get from 3 AA batteries.
 

inglewoodpete

Senior Member
As a side not, I'm also curious, but isn't the 5V you are using from the USB cable to the PICAXE too much for it? Doesn't it need to be closer to 4.5V?
The safe working range for supply voltage for most of the current PICAXE chips is up to 5.5 volts. I either use 4.5v (3 x alkaline AA cells) or 5v regulated mains supply. Anything over 5.5volts is placing the chip at risk, particularly if the supply should drift upwards a little (they're not always 'perfect').
 

mch

New Member
For sertxd, the baud rate is 4800. Try that.

Except for those picaxes which are limited to 3.3 volts, 5 volts is fine. 4.5 is what you nominally get from 3 AA batteries.
So I tried
Code:
stty -F /dev/ttyUSB0 4800 clocal cread cs8 -cstopb -parenb -crtscts
cat /dev/ttyUSB0
I have pin #19 of the 20M2 connected to the RXD pin on the USB converter. I still don't get any data from the cat /dev/ttyUSB0 command. I've verified I have the coreutils-stty, kmod-usb-serial-cp210x, kmod-usb-serial, and kmod-usb-serial-ftdi packages all installed.
I'm not sure how else I can test the serial connection to the TP-Link, or how I can verify the output from the PICAXE (other than the simulator on the PICAXE Programmer). Any suggestions?

Thanks
Matt
 

MPep

Senior Member
how I can verify the output from the PICAXE (other than the simulator on the PICAXE Programmer)
One quick way to test a data line, is to use a LED with resistor (try 1k). If the LED pulses then there is indeed data there. My 2c worth. :)
 

mch

New Member
One quick way to test a data line, is to use a LED with resistor (try 1k). If the LED pulses then there is indeed data there. My 2c worth. :)
Ok, so I get a flashing LED. I tried using minicom instead of "cat /dev/ttyUSB0", but I'm getting garbage. If I disconnect the output pin on the PICAXE, the garbage stops, so clearly that's where it's coming from. I changed the output string in my PICAXE code to just plain "TEST.",cr,lf - and I get this string in minicom: ".]V.4y=". It's 7 characters, so clearly something is getting messed up in translation. I'm also only getting data in Minicom when the output pin on the PICAXE is connected to the "TXD" pin on the USB to serial converter - which seems odd to me, but also seems to be the way lbenson's setup is working, so maybe that's to be expected.

Thanks
Matt
 

MPep

Senior Member
Sounding good so far then. Have you tried inverting the data lines from the PICAXE? ie T4800 from N4800, or vice versa? Just re-read previous and mentions using SERTXD. This is fixed polarity.
Can you try another output line?
Also in relation to the LED test, is the LED 'on' and then pulses 'off', or 'off' and then pulses 'on'?
 

lbenson

Senior Member
Good catch, MPep==the polarity issue. SERTXD will idle low, whereas the usb/serial device expects idle high. As suggested, try SEROUT with T4800.
 

mch

New Member
Good catch, MPep==the polarity issue. SERTXD will idle low, whereas the usb/serial device expects idle high. As suggested, try SEROUT with T4800.
Awesome! Thanks, this now works:
Code:
main: low 0
	pause 1000
	high 0
	readtemp C.1, b1
	b4 = b1 * 9/5 + 32 ; convert to farenheit
	readadc C.2, b2 ; read in humidity value from HIH-4000
	b3 = b2 - 41 * 100 / 157 ; convert to %RH
	serout b.3,T4800,("The RH value is ",#b3,cr,lf)
	serout b.3,T4800,("The temp value is ",#b4,cr,lf)
	;debug
	pause 1000
	goto main
I can now get the right output in minicom on the TP-Link, but I don't get anything from "cat /dev/ttyUSB0". Any idea why?

Thanks
Matt
 

MPep

Senior Member
Pleased to read that it now works (almost!) :).
One thing I just noticed was that in your code you start off using PAUSE 1000, then at the end, again, you have PAUSE 1000. A single PAUSE 2000 does the same thing.

Sorry can't help with "cat /dev/ttyUSB0".
 

craigcurtin

Senior Member
Just to resurrect this

A good link to firmware that has everything we need as picaxe users to enable this off the bat

http://www.madox.net/blog/projects/tp-link-tl-wr703n/

And here is a guy using it to connect to an arduino

http://www.thebmwz3.co.uk/article.php?story=20120611144749730

Now i just have to get the unit to host a web page that will let me send info to the picaxe to get it to perform various functions (in this case it will be an internet enabled Mains relay control)

Will report back when working

Craig
 

lbenson

Senior Member
Craig,

This is an example of what I am using now to turn a relay off and on. The WR703N is a wireless client, accessible on my network at 192.168.1.51. The html file is furnace.html, so I access it from a browser at http://192.168.1.51/furnace.html. This is what it looks like.

Here is the html code for the display: /www/furnace.html.
Code:
<html>
<head>
<title>702 Furnace</title>
</head>

<body>
<form name="form1" method="get" action="/cgi-bin/set-furnace.sh">
  <p>
    Click a button to set furnace runtime
  </p>
  <p>
<TABLE BORDER="1" CELLSPACING="0" CELLPADDING="5">
<TR><TD>Furnace</TD></TR>
<TR><TD>Run Time</TD></TR>
<TR><TD>
    <input name="Radio_Button" type="radio" value="p0" onClick="this.form.submit()"> off<br>
</TD></TR>
<TR><TD>
    <input name="Radio_Button" type="radio" value="p1" onClick="this.form.submit()"> 15 minutes
</TD></TR>
<TR><TD>
    <input name="Radio_Button" type="radio" value="p2" onClick="this.form.submit()"> 30 minutes<br>
</TD></TR>
<TR><TD>  
    <input name="Radio_Button" type="radio" value="p3" onClick="this.form.submit()"> 45 minutes
</TD></TR>
<TR><TD>
    <input name="Radio_Button" type="radio" value="p4" onClick="this.form.submit()"> 1 hour<br>
</TD></TR>
<TR><TD>
    <input name="Radio_Button" type="radio" value="p5" onClick="this.form.submit()"> 75 minutes<br>
</TD></TR>
<TR><TD>
    <input name="Radio_Button" type="radio" value="p6" onClick="this.form.submit()"> 90 minutes<br>
</TD></TR>
<TR><TD>
    <input name="Radio_Button" type="radio" value="p7" onClick="this.form.submit()"> 105 minutes<br>
</TD></TR>
<TR><TD>
    <input name="Radio_Button" type="radio" value="p8" onClick="this.form.submit()"> 2 hours
</TD></TR></TABLE>
  </p>
</form>
</body>
</html>
Notice this uses the "get" method, and the action file is /cgi-bin/set-furnace.sh (note that /cgi-gin is within /www). Here is that file
Code:
#!/bin/sh
#read QUERY_STRING
stty -F /dev/ttyUSB0 2400 clocal cread cs8 -cstopb -parenb -crtscts
tmp=$(echo "$QUERY_STRING"|awk -F'=' '{print $2}')
if test $tmp = "p0" 
then
  echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" > /dev/ttyUSB0
  sleep 1s
  echo "~px!#0" > /dev/ttyUSB0
#  echo "~~~~px!#0"
else
  cmd=${tmp:0:1}
  parm=${tmp:1:1}
#1  echo "$cmd $parm"
  if test $cmd = "p" 
  then
    echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" > /dev/ttyUSB0
    sleep 1s
    echo "~px!#1" > /dev/ttyUSB0
#1    echo "~~~~px!#1"
    case $parm in
      "1") min=15;;
      "2") min=30;;
      "3") min=45;;
      "4") min=60;;
      "5") min=75;;
      "6") min=90;;
      "7") min=105;;
      "8") min=120;;
      *)   min=0;;
    esac
    if test $min -eq 0 
    then
      sleep 1s
      echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" > /dev/ttyUSB0
      sleep 1s
      echo "~px!#0" > /dev/ttyUSB0
    else
      today=$(date +%s)
      target=$(expr $min \* 60 + $today)
      echo $(date -d @$target +%H%M) > /www/cgi-bin/offtime
    fi
  fi
fi
#echo "$tmp" > /dev/ttyUSB0
echo "$tmp" >> /var/log/furnace.log
echo "Content-type: text/html"
echo ""
cat /www/furnace.html
I like this method for a not-very-complex form because use of the radio button allows you to not even need a "submit" button--one click and your selection is submitted (because of the clause, onClick="this.form.submit()".

This cgi program is a linux command-line script (I've also used Lua scripts). It uses awk to strip off the value in the query-string which follows the "=" character--the value of the radio button, in this case "p0"-"p8".

The program sends only two values to the picaxe, (preceeded by a possibly unnecessary string of "~~~"--"px!#0" (which means turn the relay off), or "px!#1" (which means turn the relay on).

The rest of the cgi program figures out how many minutes the user wants the relay to remain on, and writes 4-digit time in the format "HHMM" (24-hour) to the file, /www/cgi-bin/offtime. A cron program runs once a minute on the WR703N to check this file and determine when the relay should be turned off. As a failsafe, the picaxe program keeps time roughly and turns off the relay if it has been on for too long.

Hope this helps.
 
Last edited:

craigcurtin

Senior Member
yes that does help thanks

Craig,

This is an example of what I am using now to turn a relay off and on. The WR703N is a wireless client, accessible on my network at 192.168.1.51. The html file is furnace.html, so I access it from a browser at http://192.168.1.51/furnace.html. This is what it looks like.

Here is the html code for the display: /www/furnace.html.
Code:
<html>
<head>
<title>702 Furnace</title>
</head>

<body>
<form name="form1" method="get" action="/cgi-bin/set-furnace.sh">
  <p>
    Click a button to set furnace runtime
  </p>
  <p>
<TABLE BORDER="1" CELLSPACING="0" CELLPADDING="5">
<TR><TD>Furnace</TD></TR>
<TR><TD>Run Time</TD></TR>
<TR><TD>
    <input name="Radio_Button" type="radio" value="p0" onClick="this.form.submit()"> off<br>
</TD></TR>
<TR><TD>
    <input name="Radio_Button" type="radio" value="p1" onClick="this.form.submit()"> 15 minutes
</TD></TR>
<TR><TD>
    <input name="Radio_Button" type="radio" value="p2" onClick="this.form.submit()"> 30 minutes<br>
</TD></TR>
<TR><TD>  
    <input name="Radio_Button" type="radio" value="p3" onClick="this.form.submit()"> 45 minutes
</TD></TR>
<TR><TD>
    <input name="Radio_Button" type="radio" value="p4" onClick="this.form.submit()"> 1 hour<br>
</TD></TR>
<TR><TD>
    <input name="Radio_Button" type="radio" value="p5" onClick="this.form.submit()"> 75 minutes<br>
</TD></TR>
<TR><TD>
    <input name="Radio_Button" type="radio" value="p6" onClick="this.form.submit()"> 90 minutes<br>
</TD></TR>
<TR><TD>
    <input name="Radio_Button" type="radio" value="p7" onClick="this.form.submit()"> 105 minutes<br>
</TD></TR>
<TR><TD>
    <input name="Radio_Button" type="radio" value="p8" onClick="this.form.submit()"> 2 hours
</TD></TR></TABLE>
  </p>
</form>
</body>
</html>
Notice this uses the "get" method, and the action file is /cgi-bin/set-furnace.sh (note that /cgi-gin is within /www). Here is that file
Code:
#!/bin/sh
#read QUERY_STRING
stty -F /dev/ttyUSB0 2400 clocal cread cs8 -cstopb -parenb -crtscts
tmp=$(echo "$QUERY_STRING"|awk -F'=' '{print $2}')
if test $tmp = "p0" 
then
  echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" > /dev/ttyUSB0
  sleep 1s
  echo "~px!#0" > /dev/ttyUSB0
#  echo "~~~~px!#0"
else
  cmd=${tmp:0:1}
  parm=${tmp:1:1}
#1  echo "$cmd $parm"
  if test $cmd = "p" 
  then
    echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" > /dev/ttyUSB0
    sleep 1s
    echo "~px!#1" > /dev/ttyUSB0
#1    echo "~~~~px!#1"
    case $parm in
      "1") min=15;;
      "2") min=30;;
      "3") min=45;;
      "4") min=60;;
      "5") min=75;;
      "6") min=90;;
      "7") min=105;;
      "8") min=120;;
      *)   min=0;;
    esac
    if test $min -eq 0 
    then
      sleep 1s
      echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" > /dev/ttyUSB0
      sleep 1s
      echo "~px!#0" > /dev/ttyUSB0
    else
      today=$(date +%s)
      target=$(expr $min \* 60 + $today)
      echo $(date -d @$target +%H%M) > /www/cgi-bin/offtime
    fi
  fi
fi
#echo "$tmp" > /dev/ttyUSB0
echo "$tmp" >> /var/log/furnace.log
echo "Content-type: text/html"
echo ""
cat /www/furnace.html
I like this method for a not-very-complex form because use of the radio button allows you to not even need a "submit" button--one click and your selection is submitted (because of the clause, onClick="this.form.submit()".

This cgi program is a linux command-line script (I've also used Lua scripts). It uses awk to strip off the value in the query-string which follows the "=" character--the value of the radio button, in this case "p0"-"p8".

The program sends only two values to the picaxe, (preceeded by a possibly unnecessary string of "~~~"--"px!#0" (which means turn the relay off), or "px!#1" (which means turn the relay on).

The rest of the cgi program figures out how many minutes the user wants the relay to remain on, and writes 4-digit time in the format "HHMM" (24-hour) to the file, /www/cgi-bin/offtime. A cron program runs once a minute on the WR703N to check this file and determine when the relay should be turned off. As a failsafe, the picaxe program keeps time roughly and turns off the relay if it has been on for too long.

Hope this helps.
I found some posts last night on the openwrt forum with people doing something similar and have started to cobble something together.

basically i want to send a query to the picaxe every minute to tell me the state of the relays and i will display this - i intend to do that part through a cron job

I will then have 8 radio buttons which will enable the turning on or off of relays

Almost there and then i will get onto the picaxe side of things.

I have got to say (even though i am in IT) it has taken a while to get to this point but for a $25 box the size and capabilities of the unit are outstanding

Craig
 

lbenson

Senior Member
>basically i want to send a query to the picaxe every minute to tell me the state of the relays and i will display this - i intend to do that part through a cron job

I'd be more inclined to have a job running in the background on the linux device, constantly monitoring the serial line from the picaxe. The picaxe sends a notification whenever it detects a change in status, terminated with CRLF (0x0d0a). Here's a Lua program which does that, and logs the incoming serial to a file with a date stamp.
Code:
-- log.lua -- write incoming from /dev/ttyUSB0 to /home/user0/Rx01.txt
--fileout = io.open("/home/user0/3rd_mon.started","w")
fileout = io.open("/home/user0/Mil_mon.started","a")
fileout:write(os.date("%y%m%d%H%M%S\n",time))
fileout:close()

x = os.execute("stty -F /dev/ttyUSB0 2400 clocal cread cs8 -cstopb -parenb -crtscts")
--print("stty return: "..x)
failedFlag = false
filein = io.open("/dev/ttyUSB0","r")
if filein == nil then
  filein = io.open("/dev/ttyUSB1","r")
  if filein == nil then
    failedFlag = true
  else
    port = "ttyUSB1"
  end
else
   port = "ttyUSB0"
end

if failedFlag == true then   
  print("Unable to open ttyUSB? port")
  os.exit()
else
  print("Opened "..port)
end

--fileout = io.open("/home/user0/3rd_mon.started","w")
fileout = io.open("/home/user0/Mil_mon.started","a")
fileout:write(os.date("%y%m%d%H%M%S ",time)..port.."\n")
fileout:close()

while true do
  line = filein:read("*l")   -- read a line or nil
  if line ~= nil then 
    if string.len(line) > 6 and string.len(line) < 20 then
      print(line)
      fileout = io.open("/home/user0/Rx01.txt","a")
      if fileout == nil then -- pause 1+ seconds
        iSec=tonumber(os.date("%S",time))+2
        if iSec > 59 then iSec = 59 end
        while tonumber(os.date("%S",time)) < iSec do end
        fileout = io.open("/home/user0/Rx01.txt","a")
      end
      if fileout ~= nil then 
        fileout:write(string.format("%s %s\n",line,os.date("%y%m%d%H%M%S",time)))
        fileout:close()
      end
    end
  end
end
A cron job monitors the log file in my case, but the lua program could directly update a web page.
 

craigcurtin

Senior Member
OK you could be right

yes that could work - i was just a little worried about the picaxe having to monitor the serial line for commands from the Webpage and accidentally conflicting with a "timed" update to the OpenWRT.

My thinking was that if everything was driven from the OpenWRT then the picaxes job was just to sit there and listen and report back - seems a little more robust than sometimes sending sometimes receiving etc ?

Craig
 

lbenson

Senior Member
There's no reason why the picaxe couldn't wait for a request before it sends to the linux device. The problem to me seemed to be that if multiple things happened on the picaxe that it wanted to report, it would have to queue them somehow until it got the request to respond. With the detect-and-report method, you don't have to worry about a queue. On the openWrt side, linux is multi-tasking, and the serial input line is buffered (somehow--how deep, I don't know). I don't think you would have to worry about losing a transmission from the picaxe.

This way the picaxe doesn't report, upon request, the status of things--it reports any change in status when it is detected. Your picaxe program determines what constitues a change--whether it's a logic level change, a threshold crossing for an ADC value, or a change in temperature (I've gone to using readtemp12 with software hysteresis to avoid degree-change oscillations with a ds18b20). I've found it easier to let the openWrt device do the queuing (behind the scenes on the serial input device) rather than the picaxe.

I'm not sure what the case would be with other languages, but with Lua, as in the program above, when you read a "line" from the serial device, if the buffer doesn't include a linefeed character, indicating that a line is available, then the value returned is nil, so you just loop, continuing to read, until the value is not nil.

As for data coming from openWrt to the picaxe, you can avoid the problem of not listening at the proper time by using hserin background receive.
 
Top