remote sensing LLAP to SMS gateway

Our smallholding is an island site with no power and no broadband. No power means things like a Raspberry Pi are marginal – we’re looking at a current drain of about 500mA for a Model A. For a 85AH leisure battery of which you only want to use half the capacity for good service life that’s about 80 hours. So it’s time to look at the system architecture of a remote sensing network to try and reduce the power used at the remote site. The aim is to offload the processing for graphing to a site with mains power (home), so the system has sensors, a gateway that collates all the sensor data and sends it via SMS in my case, and a data processor.

Remote sensing network system architecture

At a site with mains power the gateway and data processor can be the same thing. The architecture of such a system is therefore two-level –

  • many sensors out in the field
  • a gateway/data processor

At home I have a Raspberry Pi that collects data from my sensors using a RF board, Ciseco’s Slice of Radio. The same Raspberry Pi runs RRDtool to do the graphing and SFTP to put the graphs onto the web.

Sensor network on a mains-powered sirte - the Raspberry Pi does most of the work
Sensor network on a mains-powered site – the Raspberry Pi does most of the work

At the farm, however, because of the power constraint I need to use a gateway to transfer the data onto the mobile network using SMS.

That sort of site typically consists of three levels –

  • many sensors, out in the field doing the data collection,
  • a gateway, that collects all the sensor data
  • a data processor – that consolidates the data from the sensors, graphs it and saves it, perhaps uploading to the web

So the next stage down from a Pi is something like an Arduino

The Arduino OKG and Sainsmart SMS to serial device reduce power usage by 80%
The Arduino OKG and Sainsmart SMS to serial device reduce power usage by 80%

The Raspberry Pi can be at home so its power consumption isn’t an issue any more. It takes an SMS message of various sensor readings and munges this via Python and some scripts into a RRD database which then goes with RRDgraph. Which gives the single-sensor plot as shown below. The battery voltage chart shows that something rather nasty is happening to the main battery – it looks like the charge controller is not disconnecting the solar panels from the battery when the battery voltage is high enough – if so this is the second Kemo charge controller I’ve had from Maplin that has failed in service.

Simplified sensor chart
Simplified sensor chart

What, no IoT platform?

I’ve gone off third-party IOT services, because the RPi lets me run RRDtool, and shifts the conversion from simple CSV text files to home. I get to control what goes on, I am not subject to the whim of third-party changes, cessations of service, charging for what was free and all the other hurt that goes with relying on people you don’t pay. I found the Xively Arduino stack memory leaky and buggy despite my initial enthusiasm, and now I can run a Raspberry Pi at home I can insource the job, and get the Ethernet stack off the Arduino.

In that way the data gets processed more as it is staged along the signal path as the processing power of my devices and electrical power available to them increases. Electrical power is shortest at the sensor, which draws an average of about 1mA. It gets consolidated at the OKG gateway, which is powered by a 12V leisure battery and draws about 60mA, handling all the sensors. Once it gets to the Raspberry Pi at home that is mains powered I can live with the 500mA-700mA@5V and that does the collating, data transforming into a RRD database, graphing and uploading to the Web.

Sensor design

For my system architecture I have pinched ideas from the design of industrial process control system – historically these used wired sensors, firstly using 4-20mA analogue signalling using current (this independent of wire resistance). With zero response the sensor would draw 4mA and at full scale it would draw 20mA. These fed into a console for display.

However, I don’t want to run wires all over the farm, so I will use Ciseco’s LLAP serial data format over radio. This replaces the naalogue current loops and wiring and lets me reduce cost and power at the sensor, which can sleep for most of the time, only waking every 10 minutes to send a 12-byte packet on the radio network to be received at the gateway. That’s just as well, since losing the wiring means the sensors each have to be autonomously powered.

thermistor board with XRF
Ciseco’s thermistor board with XRF

Ciseco already make some sensors using the processor on the XRF radio – you simply upload a different firmware to the XRF – there’s an example in the picture, and this is powered from a CR2032 coin cell on the board just under the XRF.

thermistor board in box
thermistor board in box

These make a neat small sensor, and great for measuring the temperature in a shed where sunlight doesn’t fall directly on the black box (generating large readings unrepresentative of the air temperature) but they aren’t great for soil temperature measurements.

soil temperature measurements from a buried probe and a LLAP thermistor sensor in black box on the soil surface
soil temperature measurements from a buried probe and a LLAP thermistor sensor in black box on the soil surface

The blue line is the LLAP sensor in a box – placed next to the soil sensor – they are physically very close, but the box on the soil experiences a much wider temperature range!

Sensors deployed in a polytunnel
Sensors deployed in a polytunnel

Not only is there the sunlight problem, but being on the soil keeps the radio low which minimises range, hence the choppy blue line. However, it wouldn’t be hard to mod one of these with a jack switched socket to use an internal thermistor unless an external one was plugged in, and they’re quick and easy to deploy, which is great. They can also be run off two NiMH AA cells instead of the Li battery, which opens up the possibility of using solar power for unattended operation (the CR2032 battery is good for 6 months at least at a 10min update rate).

To get more out of the limited data rate on the SMS gateway, I’ve also got a LLAP sensor design with two sensors and a PIC microcontroller than encodes two temperatures onto one LLAP packet. I use two of the the Dallas18B20 digital temperature sensors for that.

PIC miocrocontroller/XRF dual dallas 18B20 control box
PIC microcontroller/XRF dual dallas 18B20 control box. Powered off 4xAA NiMH maintained by a solar cell

The Gateway

Ciseco do a Arduino Uno based gateway PCB that has an UNO and sockets for their XRF modules, called the OpenKontrol Gateway. This also has space for a Real Time clock which is nice. I only needed the Arduino, the RTC and the XRF hence the gobs of unused space on the LHS. I wired this via the serial port to a Sainsmart TC35 used as a SMS gateway, mounted on the bottom of the box. Unfortunately the XRF ends up between two ground planes, which doesn’t do wonders for the RF sensitivity. However, I was ready for that, bringing out the serial connections to a DIN socket, so I can mount the XRF remotely and up high if necessary, taking just power and 9600-baud RS232 back to the box.

Ciseco OpenKontrol Gateway on lid of device, with Dallas 1307 RTC implemented
Ciseco OpenKontrol Gateway on lid of device, with Dallas 1307 RTC implemented
the finished LLAP to SMS gateway
the finished LLAP to SMS gateway

So far I have learned a lot from this deployment – it’s proved the principle, but I need to improve the RF performance of the OKG/SMS gateway with a remote XRF receiver to be in with a good chance of covering a significant part of the smallholding.

A denser LLAP serial RF data format

Ciseco’s LLAP format is a nice lightweight and PIC microcontroller and Arduino friendly serial protocol. I use their XRF modules for RF communication, these support power-down so they are well-suited to intermittent operation off a battery. Standing current on receive is 23mA so continuous operation is more of a challenge, for instance at the RF to SMS gateway. It has 12 bytes like so:

LLAP Message format

Each message is exactly 12 characters long and in three distinct sections:

  • One start byte
  • Two bytes for the device identifier
  • Nine data bytes, padded by dashes if necessary.

<SB> <ID> <ID> <D> <D> <D> <D> <D> <D> <D> <D> <D>

See Appendix 3 for details of the permissible characters in each field.

Their examples, however, send only one data value per LLAP message, with a descriptive section. Hence

aAATMPA12345

Which is wasteful IMO. A lot of sensors have two data points,for instance temperature difference measurements, or temperature and relative humidity.

Few real world sensors  can justify the precision of using all the digits; I don’t have any with an accuracy of more than three digits. Sensing temperature to an accuracy of 0.1C is unusual – the popular dalas 18B20 is accurate to 0.5C but to do much more implies a piece of laboratory equipment. Useful values of temperature in the UK would be -20 to 120 °C, Relative humidity is 0 to 100 – cheap sensors don’t really justify a .x so allocating four digits covers most bases. Negative values give the ugly -21. as the – takes up a digit but it’s only a machine that sees it. So I can make a double density device as

aAA12.34X5.67

and keep within the spec. I use **** for failed or missing sensors, and the X is replaced by L,M or H for battery status. M and H are operational, L means may be about to switch off in a few cycles. In sensors that support H then M means would still accept charge, H is enough. However I use a simple comparator at about 4.4 V on a PIC 16F628 so I can only show L and M.

This saves me precious power, and allows me to consolidate two temperature sensors to one radio saving cost of the radio and aggravation of maintaining batteries.

 

two-sensor PIC and XRF device
two-sensor PIC and XRF device

I couldn’t use JAL for this because I laid out the board to use the 16F628’s internal oscillator that runs at 4MHz and the JAL one-wire lib wants to run at 20MHz. So I had to code it in assembler 🙁 Next time I’ll leave space for a 20MHz resonator on the board that will save me all that grief.

I now get to read two temp sensor and the battery status, all in one LLAP message 🙂

 

 

AM2302 (DHT22 ) Temp Humidity sensor and JAL on a 16F628 at 4MHz clock

Having decided I can’t be bothered with digital sensors with oddball serial interfaces like the DHT22 it was time to suck it up when I needed a number of sensors. Cost adds up with lots of sensors – though that Honeywell product more than paid for itself a few times over in much better hatch rates (fertile eggs are about £2 a pop by post, that’s how much of a loss you eat for every failure to hatch!) not every sensor application affects the bottom line like that. Sometimes low cost trumps accuracy, reliability and serviceability. Enter the AM2302, apparently a.k.a. DHT22, produced by the fine Aosong corporation. Their website looks like line noise on my browser, but apparently they are based in Guangzhou, which is China’s third largest city, a conurbation of nearly thirteen million souls.

AM2302, humidity and temperature sensor, a.k.a. DHT22 apparently
AM2302, humidity and temperature sensor, a.k.a. DHT22 apparently

The sensors are cheap, nasty and have poor accuracy, but the price is right, it’s the cheapest way to get a humidity and temperature sensor. Five for £17.70 or a unit price of £3.54 from a Chinese supplier on ebay, Buyincoins ISTR. They have a non-standard one-wire interface. That requires you to be able to tell a 30μS high duration from a 68μS high duration. No problem, eh, even with a PIC running on the internal 4MHz oscillator so each clock cycle is 1μS?

There was already a JAL library for this, called temperature_humidity_dht11.jal so I am in development heaven.

Except it doesn’t work – it acts up after about 20s in the video. It sort of works some times, tantalising short runs of OK in amongst loads of timeout errors. I fiddle with the power supply a little as the AM2302 is claimed to be finicky on the need for 5V. No luck. Tracing the library code I find it barfs around

Continue reading “AM2302 (DHT22 ) Temp Humidity sensor and JAL on a 16F628 at 4MHz clock”

16F628 PIC A/D using JAL

The 16F628 pic doesn’t actually have a A/D converter. It has a couple of comparators and a software controllable voltage reference which does pretty well for most applications. I’m looking at using it for a low-battery cutoff device to protect 12V lead-acid batteries.The two comparators would work for that – one for the low-water mark, and one set a little bit above for a level the charge needs to reach before the load is reapplied, with some time delay probably too.

However, I came across Microchip’s Application note AN700 Make a Delta-Sigma Converter Using a Microcontroller’s Analog Comparator Module which shows how to use the comparator as an A/D  converter. There are plenty of PICs that already have an A/D converter – the 16F88 has several analogue channels, but the 16F628 is cheaper. A lot of applications need just one analogue value sampled, and my application also wants an A/D that includes 12V. If I used a chip with an onboard A/D I’m going to need two resistors anyway to pad 12V down to the 5V range, and AN700 fig 7 shows how to take advantage of the external parts to shift the A/D range up to about 12V.

Trouble is, I want to use JAL, to make life easier when I write the rest of the code, and the assembler mode of JAL didn’t work. I swiped this from here probably derived from here but it didn’t work for me. I took a look at the code and suspected the assembler part, because what was happening was as soon as I called the DeltaSigA2D() the whole program seemed to sit down and start again from the top, resulting in endless printing of “STARTED” and little else.

Thinking about what JAL is probably doing with assembler, I suspected some of the clever space-saving constructs like the bit in eat5cycles that goes

goto +1

which was supposed to be

goto $+1

could be asking for trouble unless I could really assume that next instruction is the next one in the program space. In the end if you’re going to use something like JAL you aren’t trying to eke out every last drop of code space, so I figured I would nut the cleverness and use stacked nops. And it worked.

 

-- JAL 2.4i
-- Just the A/D 15 June 2013
-- modded by Richard
--
-- adc_test_16f628_v03
-- after DeltaSig.asm v1.00 from Dan Butler, Microchip Technology Inc. 02 December 1998
-- after http://den-nekonoko.blog.so-net.ne.jp/2010-11-25 and AN700
-- continually spews 10-bit value on TXD at 9600 baud, 5V=1024 0V=0
-- AN700 Fig 2
include 16f628_inc_all
-- We'll use internal oscillator. It work @ 4MHz
pragma target clock       4_000_000
const word _fuses         = 0x3fff ; default value
pragma target osc         INTRC_NOCLKOUT
pragma target WDT    off
pragma target MCLRE  off
pragma target PWRTE  on
pragma target BODEN    on
pragma target LVP    off
-- HS, -BOD, ,-LVP, -WDT, -CP  = 0x3F22
; pragma target fuses       0x3D02
--enable_digital_io()

; const bit enhanced_flash_eeprom = false
include pic_general
include delay

var word result
var byte result_l
var byte result_h
var byte counter1
var byte counter2

const byte booted[] = "STARTED"

pin_a0_direction = input
pin_a1_direction = input
pin_a2_direction = input ; comparator in / vref out
pin_a3_direction = output ; comp1 out
pin_a4_direction = output ; comp2 out (OD)
pin_b2_direction=output ; RS232 TX

const bit usart_hw_serial = TRUE
const serial_hw_baudrate = 9600
include serial_hardware
serial_hw_init()

include print
include format

Procedure InitDeltaSigA2D() is
VRCON=0b11101100 --    0xEC
CMCON=0b00000110   -- 0x06 two common ref comps with outputs
end procedure

;
; Delta Sigma A2D
; The below contains a lot of nops and goto next instruction. These
; are necessary to ensure each pass through the Elop1 takes the same
; amount of , no the path through the code.
;
Procedure DeltaSigA2D() is
assembler
         LOCAL    elop1,comphigh,complow,eat2cycles,endelop1,eat5cycles,exit1
--DeltaSigA2D
        clrf counter1
        clrf counter2
        clrf result_l
        clrf result_h
        movlw 0x03 ; set up for 2 analog comparators with common reference
        movwf cmcon
elop1:
        btfsc c1out ; is comparator high or low?
--        btfsc cmcon,c1out ; is comparator high or low?
        goto complow ; go the low route
comphigh:
        nop ; necessary to timing even
        bcf porta,3 ; porta.3 = 0
        incfsz result_l,f ; bump counter
        goto eat2cycles ;
        incf result_h,f ;
        goto endelop1 ;
complow:
        bsf porta,3 ; comparator is low
        nop ; necessary to keep timing even
        goto eat2cycles ; same here
eat2cycles:
        goto endelop1 ; eat 2 more cycles
endelop1:
        incfsz counter1,f ; count this lap through the elop1.
        goto eat5cycles ;
        incf counter2,f ;
        movf counter2,w ;
        andlw 0x04 ; are we done? (we're done when bit2 of
--        btfsc status,_z ; the high order byte overflows to 1).
        btfsc Z --status,z ; the high order byte overflows to 1).
        goto elop1 ;
        goto exit1
eat5cycles:
        nop  -- this really seems to hate the goto $+1, keeps resetting. I am not so short of code space, case to be made to turn everything into nops
        nop
        --goto +1 ; more wasted time to keep the elop1s even
        nop ;
        goto elop1 ;
exit1:
        movlw 0x06 ; set up for 2 analog comparators with common reference
        movwf cmcon
end assembler
end procedure

function rescale(WORD IN value) RETURN WORD is
-- 1024 corresponds to 5V
-- multiply by 50000/1024 (~49)
var word temp =value*49
temp=temp/100 -- now lose excess precision
return temp

end function

InitDeltaSigA2D()

print_string(serial_hw_data,booted)

forever loop
DeltaSigA2D()
result=word(result_h)*256 + word(result_l) -- you must explicity make result_h a word as described on p11 of JAL manual
result=rescale(result)
format_word_dec(serial_hw_data, result, 3, 2)
serial_hw_data = " "
serial_hw_data = 13 -- CR
serial_hw_data = 10 -- LF
delay_1ms(500)   -- this is purely to allow the terminal display to catch up and not overload buffer of the slow device
end loop

Files

adc_test_16f628_v03.jal

and the hex file

adc_test_16f628_v03.hex

There’s a case to be made for using a voltage reference and setting it to be some convenient power of 2 like 2.05 V to save all the messy integer calculation in rescale

This is a video of the display on the serial port compared with a multimeter on the input, connected to a 5k pot between 0V and +5V. I should have moved the control a bit slower to allow the 0.5s sampling to catch up at times, but it shows it is reasonably accurate.