Lots of stuff and my random thoughts

Welcome to Andy Brown's personal website - thebmwz3.co.uk
Wednesday, May 22 2013

Welcome

GeneralWelcome everyone,
I've finally got round to writing up a blog, so I'm going to generally post information and snippets on here, mainly because my memory is so bad, that I need a reference site for things I've thought of, etc.

If you'd like to contribute, or comment, then please do, I'd love to hear from you, especially if you've found any information of any use, or applied/tested anything and the results.


As per normal, everything here is (C) me, and also I'm not liable for any problems trying anything here causes, information here is not the thoughts or opinions of my employer, any groups I'm affiliated with or anybody else in my family, its the random gibberings of an idiot, so please take it as that and check anything twice, at least! tmp

Linksys WRT54GL bricked

General

For years I've used the Linksys WRT54 range of wifi routers, I like these units as they have a decent form-factor, generally just keep on running for years without any attention and two wifi antennas that have screw-terminals on them so can easily add or change the aerial. I've always flashed these routers with different firmware, generally I use DDWRT as this has a new GUI, easy setup and quite a few advanced functions to switch WIFI on and off at certain times, captive portals, firewall rules, etc.

Recently I was going to upgrade my firmware, so did the usual, downloaded from DDWRT and uploaded it, then waited for the reboot, wifi didn't come back. Let it do its longer reboot, still nothing and it just wouldn't come back. I checked on the unit and the power light was constantly flashing, this is a bad sign, this generally means the FLASH/firmware isn't working correctly and its stuck in a boot loop. The recovery options on the Linksys/Broadcom hardware are to try their failsafe IP, this is 192.168.1.1 and initialise during their CFE bootloader. The trick here is to see if you can get a ping from 192.168.1.1 during power on. Unfortunately, this also didn't work for me, so it looked increasingly likely that I'd lost the unit completely, so it would be down to using a JTAG re-flash of the system to recover. This isn't easy! So popped the cover off and located the JTAG port. JTAG is a 12-pin (6x6 pins) port that you can access the Broadcom chipset directly to re-flash and debug it. In my case I was trying to use my FTDI cable FT232RL. I now realise this was STUPID of me! This is simply a low-voltage (3v) TTL to serial/usb converter cable, not a JTAG. So I started to give up hope. Until I realised, on the Linksys board was a SERIAL pin header. I soldered up some pins and connected up at 115200-8-N-1 and powered on. Sure enough I saw the bootloader!

This was a relief, it showed me that the bootloader wasn't damaged, but it just hun as it tried to load the O/S (As expected). It also confirmed that it should have been listening on 192.168.1.1 but the time it waited was tiny, almost 1-2 seconds! But it gave me hope as I reckon I could try to recover it from this point. Here is the screen output I had:

 

CFE version 1.0.37 for BCM947XX (32bit,SP,LE)
Build Date: Tue Jun 20 16:22:41 CST 2006 (root@localhost.localdomain)
Copyright (C) 2000,2001,2002,2003 Broadcom Corporation.
 
Initializing Arena
Initializing Devices.
 
No DPN
et0: Broadcom BCM47xx 10/100 Mbps Ethernet Controller 3.90.37.0
CPU type 0x29008: 200MHz
Total memory: 16384 KBytes
 
Total memory used by CFE:  0x80300000 - 0x803A39C0 (670144)
Initialized Data:          0x803398D0 - 0x8033BFE0 (10000)
BSS Area:                  0x8033BFE0 - 0x8033D9C0 (6624)
Local Heap:                0x8033D9C0 - 0x803A19C0 (409600)
Stack Area:                0x803A19C0 - 0x803A39C0 (8192)
Text (code) segment:       0x80300000 - 0x803398D0 (235728)
Boot area (physical):      0x003A4000 - 0x003E4000
Relocation Factor:         I:00000000 - D:00000000
 
Boot version: v3.7
The boot is CFE
 
mac_init(): Find mac [00:1C:10:36:41:9E] in location 0
Nothing...
 
eou_key_init(): Find key pair in location 0
The eou device id is same
The eou public key is same
The eou private key is same
Device eth0:  hwaddr 00-1C-10-36-41-9E, ipaddr 192.168.1.1, mask 255.255.255.0
        gateway not set, nameserver not set
Loader:raw Filesys:raw Dev:flash0.os File: Options:(null)
Loading: .. 3916 bytes read
Entry at 0x80001000
Closing network.
Starting program at 0x80001000
 
You can see it was giving me its IP and trying to boot. So now to try and interrupt it and get a ping reply. It also occurred to me at this point, previously trying to connect/talk to it I had plugged the cable directly from the router into my laptop. This was problematic as linux was trying to auto-negotiate and DHCP to the interface, which seemed to also introduce a delay, the delays were small but when I'd see the bootloader via serial I realised how time-sensitive the whole approach was. So using a mini-hub I connected the two together and started the ping again. Again I rebooted and found it didn't reply to pings.
The CFE bootloader can be interrupted by a CTRL-C to go interactive (like grub, lilo, etc) so the next trick was to try and interrupt it. Again this was time-sensitive and I found I had to keep hammering away at CTRL-C whilst plugging power into the router. A very tricky thing to do, but keep trying. Probably 10-20 attempts. Finally I got in and it responded:
 
mac_init(): Find mac [00:1C:10:36:41:9E] in location 0
Nothing...

eou_key_init(): Find key pair in location 0
The eou device id is same
The eou public key is same
The eou private key is same
Device eth0:  hwaddr 00-1C-10-36-41-9E, ipaddr 192.168.1.1, mask 255.255.255.0
        gateway not set, nameserver not set
Automatic startup canceled via Ctrl-C
CFE> ^C
CFE> ^C
CFE> help
Available commands:

rndis               Broadcom USB RNDIS utility.
et                  Broadcom Ethernet utility.
modify              Modify flash data.
nvram               NVRAM utility.
reboot              Reboot.
flash               Update a flash memory device
memtest             Test memory.
f                   Fill contents of memory.
e                   Modify contents of memory.
d                   Dump memory.
u                   Disassemble instructions.
autoboot            Automatic system bootstrap.
batch               Load a batch file into memory and execute it
go                  Verify and boot OS image.
boot                Load an executable file into memory and execute it
load                Load an executable file into memory without executing it
save                Save a region of memory to a remote file via TFTP
ping                Ping a remote IP host.
arp                 Display or modify the ARP Table
ifconfig            Configure the Ethernet interface
show devices        Display information about the installed devices.
unsetenv            Delete an environment variable.
printenv            Display the environment variables
setenv              Set an environment variable.
 
As you can see, we can now get to the bootloader commands, whilst this appeared my pings to 192.168.1.1 worked, so I now had a chance to get into it! I immediately tried sending a new firmware via TFTP to the Linksys. Trying to send the firmware over tftp was failing, so I was a little confused, until I read about CFE and how it works, and realised, by interrupting its boot process, it stopped its ability to receive firmware. So I now started to read about the commands, as I wanted to do it all in one go now, no more reboots as who knows if I'd get back into this mode again! Checking the commands I saw the erase and flash options. Checking again at DDWRT it showed that I could erase the existing/faulty flash 'nvram erase' which confirmed back with a 0 (for ok). I then found parameters to the flash command, and this accepted flashing from a TFTP source, so by doing:
flash -ctheader : flash1.trx
I could start the flash, at the same time sending the file via tftp it started to upload:
 
CFE> nvram erase
*** command status = 0
CFE> flash -ctheader : flash1.trx
Reading :: CODE Pattern is CORRECT!
upgrade_ver[v4.20.6] upgrade_ver[42006] 4712_ver[15000]
Done. 3032064 bytes read
fname=flash1.trx 
CODE Pattern is correct! (W54G)
Programming...done. 3032032 bytes written
*** command status = 0
 
At that point I typed 'go' which told it to boot, and sure enough after a few seconds DDWRT kernel boot messages appeared and eventually got the DDWRT root prompt, so I'm back in.
 
Hopefully the above will be handy to anyone in the same situation and thinking their router is toast. Persistance and keep on reading for solutions, good luck!
 

 

Arduino and Sky box innards

General

 Well as its Christmas I've had a bit of time on my hands so thought I'd start on a project a friend of mine, Adam thought of. He's key developer on TVHeadend and liked the idea of replacing the Sky+ box. That's been the drive behind TVHeadend, XBMC, etc. So why not go a step further? Take that old Sky plus hardware/case and re-use it for the XBMC PC with fully functioning front-panel.

I've had a few Sky+ boxes lying in my garage for a while now (Faulty capacitors, or just old hardware so they just sit there), so I thought I'd rip one open and see whats going on. Firstly we know the insides of the Sky+ box,

its 1 main motherboard, a PSU board and hard-drive. Then a ribbon cable feeds the front panel. So HDD comes out, and I pull apart carefully the front panel. Luckily they're made to disassemble, so a couple of screws at the side and the front panel then can unclip with gently prising the locking tabs all round it.

This revealed the front panel innards, and a 2-part circuit board with a lot of circuitry on it.

   

Not what I was expecting, I was thinking more along the lines of either I2C or a simple LED cluster that fed back to the motherboard. I powered up and started to probe the pins to see what I was getting. Unfortunately I don't have an oscilloscope so I couldn't see any data/signalling, so just went on voltage initially. Unfortunately all I found was ground, power and standby-power. Pretty disappointing. I then tried to find out what the LEDs that light up the Sky playback circle (The sequence of LEDs that go round in a circle when playing back video, etc). Unfortunately as I don't have an active SKY card in, even the demo won't display this sequence, so again I've had to give up on this. So I've decided to pull the circuit board out, and do my own thing! Fit a cluster of LEDs in the back and just feed those back to my Arduino board.

The idea is that I'll plug the arduino into the XBMC/Openelec box using USB. I can then write a serial communication language that will send status to the arduino that will then display on the LEDs. On top of that I'm going to cut out part of the front panel of the Sky box and put in a backlit LCD screen, that will show current channel, now/next, something like that (Not fully decided). Last night I got as far as mounting the LEDs behind the facia and started to check they were aligned (tricky!). Next will be to start wiring that to the arduino to see if I can get the 'animation' of the LEDs looking anywhere near OK.

If anyone has done any more interfacing with the Sky+ front panels or figured out the control lines, etc, please let me know! I'd love to get the original circuit board running somehow.

 

 

Borri UPS for home use

General

Around a week ago my APC Smart UPS SC420 decided its battery needed replacing (again!). I only seem to get around 2-3 years out of mine which started me thinking, why on earth do I get such short life from something 'relatively' expensive. These units come in at around £120 and batteries around half that. For 420va that doesn't seem too great, as all I do is power 2 machines (desktops with a few add-ons) and a network switch/wifi. Mainly to protect the computers from nasty spikes and unexpected shutdowns more than running without power (since the internet router is in the house, not connected to a UPS).

However, I wanted to replace the UPS to keep the protection up, mainly as the power in my area seems to spike and brownout quite a bit and I've had a lot of things go pop as a result of this (X10 kit hates this kind of choppy power, hence most of my X10 home control stuff going bang). So I duly went to APC and looked up the replacement battery. It came out at around £50 after postage, etc. So I then looked at the APC upgrade wizard, see what they would offer me for a trade-in, as I particularly like the idea of trading in old hardware to get new for a bit of discount and I feel I've done the environment some good with them having batteries inside, etc. For trade-in I was disappointed. I could get a replacement unit for around £100, thats with the same 420va limitation, which since I run that at around 80-90% load isn't great (and I suspect why I go through batteries so often). So looking at the next up capacity 450va, this was £151 for really very little difference, or the 550va model for around the same price. Not very impressive.

So I started doing my usual answer to everything, google for recommendations or alternative brands, Borri kept coming up as they appear to do all sorts of UPS and generator equipment from SOHO right up to datacentres, etc, and looking quite promising I looked at the B60 range. These started at 800va and went up to 2000va, and shopping around for prices. I was pleasantly surprised, the B60-800va version would be £71 delivered, etc. So thats approximately double the rating for a nice £71.

The next issue before ordering, was it linux compatible? For years I've used APC units and used the ever popular opensource APCUPSD to shut down servers when batteries neared depletion, etc. Firstly Borri provided a download of linux software. An excellent start. Checking the software it wasn't what I'd hoped, it was a java-based server/applet that basically talked to the ups over USB and presented output via a flash-based web-ui on a custom java-tomcat url on your machine. OK, not the end of the world. I did more digging and thought of NUT for linux. This looked to support it, so worth giving it a go.

UPS arrived next day and it's quite a nice looking unit, really clear permanently lit LCD on the front telling you input volts, output volts and current status (Battery level in bars, current load level). I plugged it into my laptop to play around with and get an idea of the java tomcat web interface. It actually was quite neat, just a pity it was flash and didn't seem to have a raw data port/method of extracting data from it otherwise I'd have stuck with it.

Installing NUT and setting it up for the Borri wasn't too bad, it's partially supported according to NUT using the blazer_usb driver, but this doesn't give you battery level/capacity and time to depletion. No real issue, I can survive!

I've yet to add my load of machines to it and see how it copes, but so far its looking pretty good. If I figure out the battery level/capacity part of it I'll be very happy with this solution.

 

Arduino - Cheap wifi connectivity

General
Building a cheap ethernet connection for my Arduino. I needed to relay data from my Arduino back to my home server. The location
makes wired prohibitive, but I also don't have CAT5 cabled to the location I had the Arduino in. I then looked at the various
shields available, the Ethernet shield wasn't too expensive at around £20, but this would mean wiring, and the location in the kitchen
was particularly difficult to get wiring to.
 
I then looked at wifi shields, these came in at around £85 and way too expensive for just a little hobby project, the in-between options
of using Zigbee interfaces, which is a slightly cheaper option, but I was concerned about the distance and complexity of setting
this up with my server.
 
I therefore started posting to mailing lists and trying to find a way of doing a wifi-bridge cheap, or USB over wifi. All I needed was
to get the usb/serial data out from my Arduino to my server so that I could graph it, monitor it, etc.
A kind chap on an ISP mailing list brought forward the TP-Link TL-WR703N suggesting that this device can be flashed with OpenWRT
and then act as a wifi bridge. This sounded interesting, and you can get them on eBay for less than £15 inc delivery. This was sounding
good.
 
The TP-Link TL-WR703N has 3 physical ports (RJ45, USB host and power (via a micro-usb port)). It also has integrated WIFI. So my
idea was to connect the wifi up to my house wifi, then use the USB port to monitor the serial output from Arduino. Ideal!
 
The TL-WR703N arrived, all in its chinese writing and unfortunately its chinese web admin interface. Luckily for me, the OpenWRT
site for this device was very detailed and told me exactly what to click to upload OpenWRT.
Then OpenWRT site at http://wiki.openwrt.org/toh/tp-link/tl-wr703n Had all the details to flash it, very simple and quick.
Once flashed with OpenWRT a little more tweaking was needed. I've generally not done much with OpenWRT in the past, I stick to DDWRT
which has a nice web-gui, so OpenWRT involved SSH'ing to the unit and setting the rules correctly for what I wanted.
 
I did a bit of reading on the OpenWRT recipies site on what I needed which was to be a client on a mixed WPA2-Personal AES 
encrypted wifi with MAC protection.
The basic method is follow the outline of a MASQUERADE CLIENT on OpenWRT and adjust accordingly. So my /etc/config/network looked like:
 
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.1.1'
option netmask '255.255.255.0'
 
config interface 'wan'
option ifname 'wlan0'
option proto 'dhcp'
 
(Note that I left LAN on the 192.168.1.1 setup, this meant that if the WAN or dhcp failed I can plug into it and still admin the thing)
 
/etc/config/wireless was a bit more tricky:
 
config wifi-device 'radio0'
option type 'mac80211'
option channel '1'
option macaddr '8c:21:0a:d8:7b:57'
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'
 
config wifi-iface
option device 'radio0'
option mode 'sta'
option ssid 'MYSSID'
option encryption 'psk2+ccmp'
option key 'MYPSKPASSWORD'
 
To find these settings you issue 'iwlist scan' and look for your SSID and the other settings. So in my case I set the channel of 1.
The encryption of psk2+ccmp (This refers to wpa2 with AES encryption). After doing that you can then do 'ifup wan' and 'wifi' which
should then get things working. Except in my case it didn't. I checked, I had the MAC address in my wifi router, all looked fine but it
wouldn't join the WIFI. The settings in OpenWRT are a little hazy so I assumed this was the problem and spent a while here, but in the end
I found turning MAC protection off temporarily on my DDWRT allowed it to connect, enabled it, saved and it all works each time now,
so unsure if I hit a bug in my DDWRT on my wifi access point or something, but for future, debugging with MAC protection turned off
is a lot easier!
 
Now I had it connected I needed to get info from the Arduino over the USB port. I plugged it in hoping for the /dev/ttyACM0 to be
created, but no luck. I got the USB insert message:
[   10.020000] usb 1-1: new full-speed USB device number 2 using ehci-platform
So it looks like the kernel driver doesn't exist.
Luckily the OpenWRT group have a packaging system that includes a lot of drivers and add-ons, so using the package management to install:
 
opkg update
opkg install kmod-usb-acm
 
Reboot, and when I plugin the arduino, success, I see:
[   10.020000] usb 1-1: new full-speed USB device number 2 using ehci-platform
[   10.160000] usbcore: registered new interface driver cdc_acm
[   10.160000] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
[   10.210000] cdc_acm 1-1:1.0: ttyACM0: USB ACM device
 
And the /dev/ttyACM0 is there. Last trick is how to get a couple of lines of data from the serial connection and SSH/SCP it up
to my server. This proved a little tricky, as first of all getting just a couple of lines of data from a constantly flowing serial
terminal, then the scp function itself.
 
To get just a couple of lines of serial I firstly tried the stty trick "stty -F /dev/ttyACM0 9600 -echo -onlcr time 50 min 0" and then
cat /dev/ttyACM0 which will read data for a specific amount of time. This was very unreliable and often hung the /dev/ACM0 interface.
So I looked to alternatives. I then tried a constant/background "cat /dev/ttyACM0 > /tmp/serial.log", periodically from cron reading
it and zero'ing it. Problem here was the filesize growing and causing the device to hang due to the limited ram on the device. Also when
/dev/null'ing the /tmp/serial.log the cat then failed and a kill/hup to the cat caused the ACM0 to hang again! So no good there.
Finally I tried "head -n 12 /dev/ttyACM0 > /tmp/arduino.log" So this output the last 12 lines from the serial console to a file.
(Overwriting the file each time keeps it low filesize). Then I can parse this for the info I need, and then scp it over. Except scp
doesn't exist as the ssh is just dropbear! So again to opkg and install the ssh client tools so I get the scp binary. Generate an
id_rsa key and then I can scp my output over: "scp -i /etc/dropbear/id_rsa /tmp/arduino.log root@192.168.xx.xx:/tmp"
Success! I can now parse this with my graphing tools.
 
Enjoy, and thank you to the TP-Link TL-WR703N for a cheap and nifty solution! (PS: Got any direct questions? See me on twitter: www.twitter.com/andyb2000 )

Arduino garden helper

General

 Over the recent bank holiday weekend we decided to plant a few vegetables in the garden. Nothing too radical, a few Onions, Peppers, Chilli and re-plant our little strawberry plant. We invested in one of those small polythene tunnels too, so help give them a bit of a boost start and see if we can get the plants happy despite the miserable cold weather we've been having. To this end I finally thought up a use for my Arduino I've had kicking around. So I started to think about a soil moisture and poly-tunnel temperature sensor type array that would feed back to the Arduino and tell us when it wanted watering, and also what the highs and lows are for temperature.

So I set about making a soil moisture sensor. My basic background in electronics helped and I knew the simplest method is to use a resistance type technique, so provide +DC to a probe, and them measure the resistance between that and a second probe. This should be easy for the Arudino as it has a few analogue inputs that I can use. The second input was temperature, so I used a temperature sensor I'd previously bought from oomlout.co.uk (TMP36) which has a nice range of -40oC up to 125oC so perfect for this. It's supplied in a standard semiconductor package so first I had to make it a little more weatherproof. Soldering up the 3 wires to a long length of cable (burglar alarm cable, which is my fave cable for general purpose as its 6-core and pretty reasonable in terms of weathering and loss of signal). I then coated each of the exposed wires with a bit of heatgun glue, followed by electricians tape round each leg, so each were electrically insulated and also hopefully sufficiently weather proofed. (Not sure how well that would survive totally exposed to the elements, but as this was going in the poly-tunnel I thought it would be fine).

Next was to build the soil moisture sensor. There are a few different ones on the net, so I went with one that seemed a common way of doing it. Set two probes (in my case 2 brass screws) in a piece of electrically non-conducting packing foam. So this lets the screws push down into the earth whilst keeping the rest of the screws insulated. At the top I then wire wrapped the alarm wire around the screws and added a few blobs of solder for good measure. A bit more electricians tape finished them off.

Here is the sensor that I came up with. You can see the TMP36 semiconductor sticking out the top, and the screw probes out the bottom.

 

After the probe was sorted, I ran it round outside into the poly-tunnel:

 

So the final part was the circuit into the Arduino, and also the code to make it function. The breadboard I had already connected to my Arduino had the LCD attached so I left that to give constant output on the Temperature and soil moisture, so all I had to add was the connections out to the remote probes. I found an interesting issue, at first the soil moisture values varied wildly, even when the probe wasn't in the soil, until I realised that this was because nothing was 'pulling' the input to ground, adding a quick resistor into the setup so that it pulled the input to 0 when it didn't have any other value sorted that out and I got values depending on the resistance being presented. At first I'd connected the soil moisture probe to +5ve and the other probe to my analogue input. One problem I'd found reported quite frequently online was about electrolysis of the metal probes (where electricity passing through them caused corrosion to take place). To counter this I moved the moisture probe to an output pin, and so I'll only switch on current to the probe when I wish to measure it, hopefully reducing the amount of electrolysis taking place.

A few iterations of code were required to get the reading showing anything sensible, and de-bouncing the inputs was essential. I found 4 iterations of the sensor read loop followed by an average calculation stopped a lot of the large fluctuations taking place and gave me what appear to be stable readings, and when compared with the temperature read-out from the car, the outdoor temperature looked around the right values. Soil moisture though is still a bit of an issue as I need to self-calibrate the sensor by checking the soil and deciding when it gets too dry to set that as the lower threshold.

I'll post the final code up here shortly as I'm still fine-tuning it, and also hopefully connecting my Arduino up so I can access the readings remotely and graph them using my rrd graphing system I use for other things around the house (heating, electricity, etc).

Here are a few images of the Arduino in its plastic (indoor) enclosure in operation. The Green LED lights up when the soil moisture drops below the triggered limit, and the Red LED lights when the readings are being taken. Debugging is also output via the serial port.

  

 

Aruino code + schematics to follow!

 

 

Update 10/May/2012 - Here is the current Arduino code I've been using, sorry about the messy code!

<pre>

// AndyB 7-may-2012 Outdoor temperature and soil moisture circuit

// ---------------------------------------------------------------

// include the library code:

#include <LiquidCrystal.h>

#include <EEPROM.h>

#include <Time.h>

#include <TimeAlarms.h>

 

// PINS

//   2 3 4 5 11 12 - LCD

//  9 = watering LED

// 10 = soil power pin

// 13 = Data collection LED

//  8 = LCD display light

//  6 = LCD display button light up

 

// initialize the library with the numbers of the interface pins

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

int sensorPin = A0;       // Temperature sensor

int soilMoisturePin = A1; // soil moisture

int sensorValue1 = 0;

int addr = 0;

int SoilValue1 = 0;

float temperatureC = 0;

const int buttonPin = 7;     // the number of the pushbutton pin

int buttonState = 0;         // variable for reading the pushbutton status

const int ledPin =  13;      // the number of the LED pin

const int waterPin = 9;      // the LED for watering

const int soilPowerPin = 10;  // Pin to power up the soil moisture sensor

const int lcdPowerPin = 8;    // Pin to light up the LCD

const int lcdButtonPin = 6;  // Switch to light up the LCD for a few loops

 

int lcdlightloop=0;

 

int logloop = 0;

 

int debug = 0;  // Debug setting

 

void setup() {

  Serial.begin(9600);

  if (debug == 1) {Serial.println("Program initialised");};

  pinMode(ledPin, OUTPUT);  

  pinMode(buttonPin, INPUT);

  pinMode(waterPin, OUTPUT);

  pinMode(soilPowerPin, OUTPUT);

  pinMode(lcdPowerPin, OUTPUT);

  pinMode(lcdButtonPin, INPUT);

  // set up the LCD's number of columns and rows: 

  lcd.begin(16, 2);

  digitalWrite(lcdPowerPin, HIGH);

  // Print a message to the LCD.

  // lcd.print("       oC");

  // write a 0 to all 512 bytes of the EEPROM

//  for (int i = 0; i < 512; i++) {

//    EEPROM.write(i, 0);

//  };

  // do not reset the EEprom, find the last value and set the pointer, avoids power resets loosing old data

  if (debug == 1) {Serial.println("reading EEPROM");};

  for (int i = 0; i < 512; i++) {

    byte tmp_val = EEPROM.read(i);

    Serial.print("EEPROM ");

    Serial.print(i);

    Serial.print(": ");

    Serial.println(tmp_val, DEC);

    int tmp_val_int=tmp_val;

    if (tmp_val_int == 0) {

        addr=i;

        if (debug == 1) {Serial.print("EEPROM empty at ");};

        if (debug == 1) {Serial.println(i);};

        break;

    };

  };

  digitalWrite(soilPowerPin, LOW);

//  sensorValue1 = analogRead(sensorPin);

//  float voltage = sensorValue1 * 5.0;

//  voltage /= 1024.0;

//  temperatureC = (voltage - 0.5) * 100;

//  SoilValue1 = analogRead(soilMoisturePin);

//  Serial.println("Back from reading sensors");

//  logdatatoeeprom();

  if (debug == 1) {Serial.println("Setup completed");};

  // Alarm.timerRepeat(9000, logdatatoeeprom); // every 15 minutes

  // Alarm.timerRepeat(15, logdatatoeeprom);

  digitalWrite(lcdPowerPin, LOW);

}

 

void loop() {

  if (debug == 1) {Serial.println("Starting main loop");};

  // check the button status

  buttonState = digitalRead(buttonPin);

  if (buttonState == HIGH) {     

    // Button pressed - Reset all of the EEPROM values

    if (debug == 1) {Serial.println("Button pressed - resetting EEPROM");};

    digitalWrite(ledPin, HIGH);  

    // write a 0 to all 512 bytes of the EEPROM

    for (int i = 0; i < 512; i++) {

      EEPROM.write(i, 0);

    };

    Serial.println("EEPROM ERASED");

    addr=0;

    logdatatoeeprom();

    digitalWrite(ledPin, LOW);

  };

  // check for LCD display button

  if (digitalRead(lcdButtonPin) == HIGH) {

      // LCD button was pressed

      lcdlightloop=1;

  };

  if (lcdlightloop > 0) {

      lcdlightloop += 1;

      digitalWrite(lcdPowerPin, HIGH);

  };

  if (lcdlightloop > 20) {

    lcdlightloop=0;

    digitalWrite(lcdPowerPin, LOW);

  };

  if (debug == 1) {Serial.println("Button checks complete");};

  // set the cursor to column 0, line 1

  // (note: line 1 is the second row, since counting begins with 0):

  digitalWrite(ledPin, HIGH);

  if (debug == 1) {Serial.println("Read temp sensor");};

  

  // READ SENSORS HERE

  temperatureC = readinput_temp();

  SoilValue1 = readinput_soil();

  

  if (SoilValue1 < 40) {

    digitalWrite(waterPin, HIGH);

  } else {

    digitalWrite(waterPin, LOW);

  };

 if (debug == 1) {Serial.println("Display to LCD");};

 Serial.println("Temp: ");

 Serial.println(temperatureC);

 Serial.println("Moisture: ");

 Serial.println(SoilValue1);

  lcd.clear();

  lcd.setCursor(0,0);

  lcd.print("temp: ");

  lcd.print(temperatureC,1);

  lcd.print(" oC");

  lcd.setCursor(0,1);

  lcd.print("soil: ");

  lcd.print(SoilValue1);

if (debug == 1) {Serial.println("Done writing LCD");};

    // we write to the eeprom every 10 iterations

    logloop=logloop+1;

    if (debug == 1) {Serial.print("Testing for logloop ");};

    if (debug == 1) {Serial.println(logloop);};

      if (logloop > 9) {

        logdatatoeeprom();

        logloop = 0;

      };

  digitalWrite(ledPin, LOW);

  if (debug == 1) {Serial.println("LED off");};

  Alarm.delay(10000); // wait ten second between clock display

  if (debug == 1) {Serial.println("Delay set");};

}

 

void logdatatoeeprom(){

  digitalWrite(ledPin, HIGH);

  lcd.setCursor(15,1);

  lcd.print("E");

  if (debug == 1) {Serial.println("logdatatoeeprom started");};

  if (debug == 1) {Serial.print("writing to eeprom ");};

  if (debug == 1) {Serial.print(addr);};

  if (debug == 1) {Serial.print(" : ");};

  if (debug == 1) {Serial.println(temperatureC);};

  EEPROM.write(addr, temperatureC);

  if (debug == 1) {Serial.println("back from writing to eeprom");};

  digitalWrite(ledPin, LOW);

  digitalWrite(ledPin, HIGH);

  digitalWrite(ledPin, LOW);

  // advance to the next address.  there are 512 bytes in 

  // the EEPROM, so go back to 0 when we hit 512.

  addr = addr + 1;

  if (addr == 512) {

    addr = 0;

  };

  if (debug == 1) {Serial.println("end logdatatoeeprom");};

}

 

float readinput_temp() {

  // Read inputs and de-bounce, so read 3 times and take an average

  if (debug == 1) {Serial.println("Readinputs (Temperature) function started");};

  float temp1 = 0;

  float temp2 = 0;

  int soil1 = 0;

  int soil2 = 0;

  int lpcount=0;

  

  while (lpcount<6) {

    sensorValue1 = analogRead(sensorPin);

    float voltage = sensorValue1 * 5.0;

    voltage /= 1024.0;

    temp2 = (voltage - 0.5) * 100;

    temp1 += temp2;

    if (debug == 1) {Serial.print("Temp loop :");};

    if (debug == 1) {Serial.print(lpcount);};

    if (debug == 1) {Serial.print(" : ");};

    if (debug == 1) {Serial.println(temp2);};

    lpcount=lpcount+1;

  };

  temperatureC = temp1/6;

  if (debug == 1) {Serial.print("Temperature average: ");};

  if (debug == 1) {Serial.println(temperatureC);};

  if (debug == 1) {Serial.println("Exit Readinputs (Temperature)");};

return temperatureC;

};

 

int readinput_soil() {

  if (debug == 1) {Serial.println("Readinputs (Soil) function started");};

  // Switch power pin on for the soil sensor

  digitalWrite(soilPowerPin, HIGH);

  float temp1 = 0;

  float temp2 = 0;

  int soil1 = 0;

  int soil2 = 0;

  int lpcount=0;

 

  if (debug == 1) {Serial.println("Read soil moisture sensor");};

 

  lpcount=0;

  while (lpcount<4) {

    soil2 = analogRead(soilMoisturePin);

    soil2 = (soil2 / 2);

    soil1 += soil2;

    if (debug == 1) {Serial.print("Soil loop :");};

    if (debug == 1) {Serial.print(lpcount);};

    if (debug == 1) {Serial.print(" : ");};

    if (debug == 1) {Serial.println(soil2);};

    lpcount=lpcount+1;

  };

  SoilValue1 = soil1/4;

  if (debug == 1) {Serial.print("Soil average: ");};

  if (debug == 1) {Serial.println(SoilValue1);};

  digitalWrite(soilPowerPin, LOW);

  if (debug == 1) {Serial.println("Exit Readinputs (Soil)");};

return SoilValue1;

}

 

</pre>

 ----------------------------------------------------------------------------------

Update: Tuesday 15th May 2012

I'm now graphing the output as I've hooked the Arduino up to a laptop via USB, below are the graphs (updated every hour):

    

 

Breakinguard - How old is it now!

General

  As some of you may know, a long time ago I had a need to block persistant password attackers from various servers I managed (Working for a relatively large domain hosting company at the time), and because iptables didn't exist, ipchains wasn't everywhere I wondered what to do. I was learning Perl primarily through automating jobs at my job, and so I decided to write a little script that would 'watch' certain logfiles for attempts at gaining entry via repeated password or dictionary attacks. If the attack tried several attempts within a certain time-period, and from the same source IP, then flag it up, alert and then block using one of a few techniques. Not fool-proof, not perfect but it did the job.

Perl had a handy module called File::Tail that does exactly the same (sort of) as doing a tail -f /var/log/blah in the linux shell, so just run that in a script, watch for certain patterns and act accordingly. At the time the blocking action was either add an ipchains block rule, or add a route entry pushing the offender to the loopback interface. OK so this wasn't going to stop them DOS'ing us, etc, but it kinda did the job, and at the time internet connections weren't huge, if I remember rightly we had a 4Mb line or something like that, that was for a large domain hosting company, none of this 50Mb to the home, fibre or gigabit connections! So it did the job nicely.

Well, I started to install it on more and more servers that I looked after, or helped to look after, people asked about the script and slowly I started to pass it around, just by email at first. So I then decided to package it up and distribute it. My first bit of 'freeware'/GPL software was born! The software existed quite some time before it, but the official publication date was 5/5/2005 as that was when the package was created, however the release date that you'll see most other places was 27/7/2005 as that was the date that I released it on sourceforge.net

The original code is still up there, but don't look! It's horrible perl code, badly written, but it does the job!

Just looking on sourceforge.net at the site http://breakinguard.sourceforge.net/ you'll also see very poor HTML design (something I can still never shake off, my design eye is terrible!) The release up there now is dated 08/01/2008 version 0.11 and hasn't changed a great deal since the original to be honest, a few filters and a few nicer tweaks and thats about it! I belive it is still used in some places, but to be honest its had its day.

Now, a lot of people would use simple iptables, as you can do the same natively such as:

</p>
<p>iptables -A INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --set</p>
<p>iptables -A INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP</p>
<p>

Which does the same thing really, so I think my software is dead or dying! If you do still use it, do pop a comment on or a mention as I'd appreciate it. Unfortunately I doubt I'll be doing any further updates to it, but will keep it live just for historic reasons rather than anything else!

 

Central Heating twiddles

General

 So recently I've been noticing that the heating in the house is on what seems like a lot of time, the radiators aren't always as hot as I'd expect and generally the house is a bit chilly. Now this is during the coldest time of year where I live in the UK, so temperatures outside are dropping to 1 or 2oC overnight and during the mornings not getting far beyond that. With everyone in the house out during the day I'm unsure what it goes to during this time, but on evenings/overnight is when we notice it. So I started to watch how the heating was setup and then started tinkering!

We use a gas-fired central boiler (not combi), that has timed on/off schedules for heating and hot water. The hot water/heating switch is done by changing the valve setting from the pump circulation (i.e. when hot water is set to on it will divert some/all of the heating hot water circulation into the hot water tank). So my first observation is that when heating and hot water are on at the same time then surely this will halve the efficiency of doing one or the other jobs quickly.

Radiators in each of the rooms, the majority have TRV (Thermostatic Radiator Valve)'s fitted on them, and have a 0-6 scale for setting the desired temperature. Most of these are set to maximum all the time. Only two radiators do not have TRV's, these are both in the living room/dining room (It's one large area, no partition walls, etc). This is also where the temperature room thermostat is located.

There is a single room thermostat in the dining room, this is a digital/electronic temperature sensor running off two AAA batteries (annoying when they run out), that switches the heating circulation on and off depending on the ambient temperature.

The other little niggle is that the house is quite open-plan. The downstairs is a large living room/dining room, open to the staircase, and obviously up to the upstairs landing. Therefore the majority of heat (in my limited knowledge) will escape straight upstairs to the top of the stairs! Not ideal.

So, my first steps were to change the heating programmer, to get different on/off times for the heating and hot water cycles, and to prioritise heating by only switching hot water on after I've giving the heating a chance to warm the place up. So I opted for 3 on/off sequences during the day. First one for when we get up on a morning, on 5am-8am heating only. Then for when we get home, 3am-9pm. Then one to keep the chill off at 10pm-11pm. I went for hot water going on once daily from 4pm-8pm. So that seems to keep the heating happily running and not letting the house get too cold, as I think that was an initial problem, the house dipping way too cold, so taking the heating too long to warm back up.

The room thermostat was then set to 20.5oC as that seemed a reasonable temperature that is warm but not boiling. This I think might not be helping things, as I think this might need to be higher, but more on that later.

I then attacked the radiators and the TRV's, as I know I had one of these fail in the kitchen and jam closed, so that TRV was removed, so that radiator is just on full all the time. A few of the radiators needed bleeding, so did that for a few days to make sure we didn't have any problems with air in the system. I then turned ALL TRV's down so they weren't sitting on maximum. This was because a few websites I had read stated that running a TRV at maximum is bad for the valve and heating system (can't find the quote to cite now, if you know please comment/post back!). Then went round each of the rooms and changed the TRV depending on if the room should be hot/warm/cold, the majority of bedrooms I set on 5 (one off maximum), bathrooms a little below that and thought I'd leave it at that.

Unfortunately the heating still wasn't really doing what I wanted, the children were complaining of a cold bedroom during the night/morning, our master bedroom got red-hot at night and early mornings, and the rest of the house was warm! So that didn't quite work it seems. My next discovery were the next generation of programmable TRV's. These you can set times/dates and temperatures and the unit will vary that individual radiator based on this. I thought this would be ideal for the master bedroom, as during the day/early evening it was pointlessly heating the room. So I purchased a programmable TRV from a heating/electronics firm in the UK (I'm not going to name them here, as I found their service SHOCKING, it took 2 devices and me piecing the working parts from the two together to get a single working TRV. Not impressed!).

I ordered "Radio energy-saver regulator" which is a german-manufactured device that simply plugs into your standard TRV fitting, so no draining the system, etc, just unscrew the old TRV top off and this on. You program it either via its LCD screen, or you can also use the USB computer programmer, which I chose. You then set what time-periods to use, temperatures and set it going. This has made a huge difference to the master bedroom, although some further tweaks to the schedule are needed as at the moment its like living in the antarctic! But that could also be due to the overall heating turning off too soon. Obviously the TRV will only heat the radiator up when three conditions are now met. The main heating timer is on, the downstairs thermostat is set to heat and the programmable TRV decides that its schedule and room temperature say it needs to heat. Unfortunately it has no control over the first two conditions, so therefore if the sequences aren't matched, then this fails, and I suspect this is where I'm going wrong at the moment. I'm setting the TRV schedule to warm the room before we retire to the bedroom, but at this time the rest of the house is warm enough, so the thermostat on the heating has cut out, so although our TRV wants to heat the room, it can't as the heating isn't firing. So more tweaking is needed here!

 

And thats about where I'm up to. I need to do some more tweaking with programs and temperatures to get things right, but I'm happy that I have much more control and I believe I can see where the problems are on the system now!

Windows7 Frustrations

General

 So,

Over the weekend I needed to install a new machine for the community radio station that I help out with. Their current playout system is a WindowsXP Dell machine, thats probably getting on for 7 or 8 years old I'd guess, and has practically been running 24x7 since installed. Originally at one location, and I then relocated it to their new broadcast building about 3 years ago when they got their full-time FM license. Well its about time the machine got replaced as it has everything the station needs to keep running, so I'm a little nervous that it'll fail at some point.

So a new Dell Vostro was ordered. Dual-Core Intel, 2Gb RAM, nice little machine.

So I got to installing it on Sunday, stripped down the pre-installed Windows7 system, removed all the rubbish backup applications, Dell assistance software, all the trialware and junk. Removed desktop wallpapers, screensavers, power management, etc. Basically because this is a radio station playout system you want it minimal as it just has to do one job, but without question! So all that was stripped out.

Then I got to installing the second sound card. I had an old Creative Labs Sound Blaster Live! 5.1 digital surround card, from my old desktop from about 4 years ago. So slapped that in (You need multiple inputs and outputs for playout systems so that the various faders, etc, all have separate sound channels). Booted up, and Windows7 couldn't recognise the hardware. So then starting to trawl the web, CLabs website showed the hardware was discontinued, but you could try their beta Windows7 driver. So downloaded all 40Mb of that (!), installed, and half way through got a windows driver signing error, and windows then decided to remove each of the .sys files the installer had created. No surprise, on reboot the card was partially detected, but "Had a problem", windows couldn't fix.

OK, so I gave up with that, removed the card and will just pick up another cheap PCI card, that had newer drivers, etc. No big problem (Although I'd spent quite a bit of time to now).

Next steps, was the re-create the fiddly filesystem that the playout software "SoundBox" needed. It uses windows shares for all its locations, so I created the relevant audio folders, then the 10 or so storage folders, set each one to have shared permissions with read and write access for network users (Yes I know the security is abysmal but unfortunately SoundBox works like that, so you're stuck with a wide-open system). Did that, so then started to trawl through my archives for the SoundBox installation CD. That took about 30 mins, I didn't realise I had data spread out over so many NAS and storage systems. REally do need to sort that out one day! Found the ISO and related patches and stuff, copied them over to the new machine all ready.

Ran the setup.exe, and immediately Windows7 threw a "This version is not compatible with Windows 7". Arrrgh! So next, try running it through the compatibility troubleshooter (annoying! I knew if I set compatibility to WindowsXP it should work, but it doesn't let you do that anymore, you have to use the stupid wizard!). So ran the troubleshooter, which surprise surprise set it to windowsxp for compatibility, then let me try again. This time it failed saying that the installer couldn't run on a 64-bit machine. Tried a few times with and without admin permissions (just in case!) and no go.

So basically, I'm stuck. The software supplier won't have updated the software, as its pretty much out of existance, no updates and to replace the software now would require hundreds of man-hours in training, not to mention the multi-thousands it costs to buy most radio playout software.

I'm thinking of removing Windows7 and installing WindowsXP now, even though its old, unsupported and the hardware probably won't get on with it very well, this seems my only option for the system. How annoying..... and yes, I seriously am considering re-writing the software to run under Ubuntu now!