This DVR is a fine ebay noname special, and the way to set the time is to create a file tag.txt with the following format
[date]
2014/07/27
15:43:24
sounds, sensors, stones
This DVR is a fine ebay noname special, and the way to set the time is to create a file tag.txt with the following format
[date]
2014/07/27
15:43:24
The issues with the Raspberry Pi farm camera were of waterproofing and of iffy Wi-Fi range. Both of these are addressed in the new version. The PICE waterproof case from the guys at EdVenture marshals this motley collection of bits
into something a bit more organised. There’s no getting away from it, the PICE is quite expensive at about the same as the Pi itself, but it does solve a lot of the mechanical problems of trying to run a Pi outside with a camera. The landscape version is the one i needed, since the case is only water-resistant with the top horizontal – the Pi is mounted on that and even if water does get in it falls to the bottom away from the Pi. The previous version of the PICE took the picture in portrait mode with the case oriented for best water resistance, which isn’t so useful for our aims.
This is a good interim solution – it gets the cameras into a tighter configuration, and should let me pull back the main MiFi box back to a more central location to serve the rest of the cameras. As a result each camera will draw less power which is good. The Edimax EW7711 USB WiFi unit has a better performance than the USB nano-dongle – the reason is obvious when you look at the size of the aerial of the nano
although it’s 2.4GHz the wavelength is still 13cm; you still need to get enough metal in the sky to get the 300m path length to work, unless you can mesh. Continue reading “PICE case and WiFi upgrade for the remote farm camera”
Cordless power tools often die not because they’re worn out but because the battery fails, or only holds a charge for a short time. Every tool’s battery pack seems to be different, either from the sheer cussedness of consumerism making you buy a new tool, or because nobody has standardised battery packs, You can fight back, because though the battery packs are all sorts of sizes, the parts inside are usually drawn from standard sized parts, they’re merely packed in different ways.
I had a cordless strimmer, once advertised years ago in the Guardian, from a no-name supplier with two battery packs. Both of which are now duff – a strimmer is a fairly hard life for the battery packs with about 50-100W. Here’s how I remanufactured the battery packs. These are NiCd battery packs – the key issue to to replace like with like. You can replace NiCd with NiMh but don’t cross any other chemistries.
Clive from the Raspberry Pi Foundation very kindly let us have a Pi Model A and camera, so it’s time to take this project forward a stage. At the moment the alpha test version is in service keeping an eye on our new piglets. Although the original purpose was to keep an eye on our newly arrived cattle pigs are more enterprising, so it’s good to know where they are
Development was stalled however since it’s not easy to work on a piece of kit in service. Ideally one MiFi box could serve a number of cameras. This would reduce the camera power drain and consolidate.
The trouble is that the site is on the edge of town, a couple of hundred metres from the nearest houses, and I want to use BT Wi-Fi
I acquired one of these from ebay I didn’t have much hope for the integrity of the device, and to gain height I needed to go 250m further way from any likely source of WiFi. But it worked a treat, as a WISP client, I’m amazed. I was able to see 18 access points, five of which were BT WiFi , 3 of which were 5dB or above. The TP-Link gives a decent link at more than 5 and nothing at 2. I streamed a video to confirm the stability of the link.
I use it with a TP-Link TL-WA5110G which has the advantage of having a sma antenna socket and a native power supply of 12V. Although the adaptor is specced at 1A I measured the power drain at about 210 mA (~2.5W @12V). Which isn’t great but not terrible
The trouble with using the tP link as a WISP client is the signal is presented as Ethernet, and I’d then want to re-radiate the signal on a different Wi-Fi network. I could set it as a repeater, but then every Raspberry Pi would have the hurt of logging into BT WiFi. Whereas if I use a Raspberry Pi connected via ethernet to the TP-link and a WiPi dongle to connect to the farm I can collect pictures from the cameras on the farm network and perhaps power-manage the TP Link to only update every so often.
So an unexpected win, and I can look at using a Model B as a concentrator
At The Oak Tree we have acquired two bullocks/steers, and it would be good to be able to monitor these guys to check they are okay.
The obvious way is a GSM trail camera, which has got some merit. However, these are typically tripped by movement, and you get a lot of that outside. It might work to use a trail camera with a 15 minute trigger lockout – it’d be tripped all the time but wouldn’t spam you senseless with the 15 min delay. But it’s going to be dear to run as they tend to use MMS – giffgaff charge 16p per MMS for instance, whereas their data rates are 20p per 20Mb . CCTV solutions have the same problem – they are event triggered, whereas we want to be able to see a picture taken sometime in the last 15 minutes. Well, obviously we’d really like realtime streaming video by a pic at most 15 minutes old is a decent second best 🙂
What we ideally want is a camera you can send a message to to take a picture.
I used to have a Youthnet V900 which you could send an SMS to take a picture, but it was the most maddening hunk of junk I have ever purchased. Configuring the settings was done by SMS, and I only ever got it to work with Virgin mobile once. Then Virgin must have changed something and I never got this to work again, either with Virgin or with Giffgaff. In the end I put a hammer through it so it wouldn’t waste any more of my time and money. The satisfaction of doing that was the most value I got out of it.
I took a look at this trail cam and recognised the same commands as the Youthnet . I’m just not going to go there again if it uses the same software. Plus there’s the fact that it doesn’t really suit what I want it to do.
So it’s time to break out the Raspberry Pi. Unfortunately the USB subsystem of the Pi means I couldn’t use Gammu directly with a Huawei E156G USB 3G dongle. It would work for a while and then conk out, and only come good again when the Pi was power cycled, not even a restart would fix it. That’s a real shame – this would save me a lot of power drain. Maybe it’s specific to this dongle, but there is always a world of hurt when it comes to the Pi and USB because of the power problem, and a 3G dongle has a high power usage when connected. Even running the E156G off an approved USB separately powered hub and the Pi off an approved PSU didn’t make it any better.
Obviously if your site has WiFi you don’t need to wrangle with 3G, but there is a lively market in boxes to put a WiFi hotspot using 3G, called MiFi devices. You need to configure these to make use of your 3G dongle (and make sure they are compatible), the type I used is a TP-Link MR-3220
So I used a MICRONEXT MN-WD552B WiFi dongle in the A’s single USB port, which seems reliable. Of course I now eat the power drain of the Pi, WiFi is never low power and the TP-Link 3020 MiFi device gives me another power hit. But it works, and I needed results fast rather than good, so it’ll do for now.
The camera module that the Pi foundation sell for of the Pi is rather good – the larger version of the pic above is already scaled down by half in the camera to reduce the file size. And I compressed it a fair bit. You can control the camera in Python too, using Picamera. Python seems to be the default language for the RPi.
Although the Raspberry Pi is credit card sized, it’s remarkable how big it gets if you want to do anything with it. I used a box I already had – if I decide this works well enough for a permanent version then I will use a PICE waterproof case, but for the prototype a temporary rig is fine.
At the moment both are powered up all the time, and a cron job takes a picture and SFTPs it up every 15 minutes during the day. The Pi and the TP3020 are powered via one of those dual-output 12V car to USB converters, the power drain at 12V is 250mA which is horrible, meaning using 40Ah of a 80Ah leisure battery will take 40*4=160 hours, nearly a week. Which is nasty, but livable with. There is massive opportunity to cut the power drain by bringing up the TP-Link 30210 and the Pi only once every 15 minutes when it’s light – they can be up and do their stuff in 5 minutes so I’d get a 3x drop in power drain from that, and not running in the night would save me another third.
The installation is bush-league, but this is going to need a bit of optimisation anyway
and a close-up shows just how bad it is – waterproofing by electrical tape is living on borrowed time. But that’s where those nice people at PICE come in, so there’s no point in putting any real work in that.
This shows one of the hazards of this location, in that the crows sit on the bar surveying their domain and crap on the IBC. There’s no crap on the bars though, so I might get away with it. Some anti-bird spikes might be in order.
#!/usr/bin/python #$Id: takepic.py 53 2014-06-26 16:30:17Z richard $ import time import picamera import paramiko import os import socket import datetime # import RPi.GPIO as GPIO # GPIO.setmode(GPIO.BOARD) # USE Pi BOARD pins, not the BCM ver # GPIO.setup(7, GPIO.IN, pull_up_down=GPIO.PUD_UP) # 7 is next to gnd on pin 9, so set pull up # defs camerafail=False; DIR='/home/pi/mine/' imagename='cam01.jpg' remotename='mysite.com' # assuming this is reachable by ssh and www try : with picamera.PiCamera() as camera: #camera.resolution = (2592, 1944) # The following is equivalent #camera.resolution = camera.MAX_IMAGE_RESOLUTION # run half res to test out connectivity etc and save money #camera.led = False camera.resolution = camera.MAX_IMAGE_RESOLUTION #camera.resolution = (1296, 972) # do half real to eliminate Bayer softness and save TX bandwidth camera.start_preview() time.sleep(2) camera.capture(DIR+imagename, resize=(800,600), format='jpeg', quality=15) except picamera.PiCameraError,e : print e camerafail=True finally : camera.close() time.sleep(10) # hopefully nw is up by now if not(camerafail) : timedout=False connected=False counter=0 while (not timedout) and not connected : try : s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect((remotename,80)) print(s.getsockname()[0]) connected=True except socket.error,e : counter += 1 print counter finally: s.close() time.sleep(5) if counter >= 5: timedout=True print 'Failed to connect to ',remotename,' ',datetime.datetime.now().strftime("%y/%m/%d %H:%M") # Ideally, this gets called by cron once every quarter of an hour. #upload if not timedout: print 'ftp image starting ',datetime.datetime.now().strftime("%y/%m/%d %H:%M") try : ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(remotename, port=2222, username='username', password='password') sftp = ssh.open_sftp(); sftp.put(DIR+imagename, '/my/remote/path/'+imagename) sftp.close() print "closed SFTP" except paramiko.AuthenticationException,e : print e except socket.error,e : print e
This is then called by a cron job on the Raspberry Pi. You must to this with root privileges because you are accessing the hardware, so use
sudo crontab -e
and mine looks like
*/15 4-22 * * * /home/pi/takepic.py > /home/pi/log.txt
which means every 15 minutes between 4am and 10pm run takepic.py and save the error messages etc to log.txt. Before running this as a cron job you want to make sure that if you manually run
sudo /home/pi/takepic.py
you get a picture uploaded to where you want it 🙂
Flock of Jackdaws with young in trees by playing fields and trees by the River Test in Whitchurch. The calls of the young from all around come out in this binaural recording.
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.
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 –
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.
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 –
So the next stage down from a Pi is something like an Arduino
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.
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.
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.
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.
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.
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!
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.
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.
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.
Poundland in the UK sell batteries branded by Kodak, but the cheapest ones are zinc chloride. I thought ZnCl has gone out of use decades ago, but it is surprising how often people are penny-wise and pound foolish. Particularly in pound shops 😉
So I am looking to make something to track the discharge of a battery. This is also useful to qualify NiMH and NiCd batteries – these fade with time and it is good to know what sort of capacity is left.
Every minute it reports the voltage and current from the batteries running through a 2.5V torch bulb, the third bulb is maintained at 2.5V to provide a reference. It transmits the signal using radio to a datalogger. I got a camera to take a picture every 15 minutes, as a video the results are reasonably clear. A picture tells a thousand words – the Zinc Chloride batteries are crap
The left-hand bulb is powered by the ‘cheap’ battery that Poundland sell for 9p, the middle is powered by the ‘dearer’ alkalines they sell at about 17p.
I have a Ciseco OpenKontrol Gateway as a datalogger. It stores data to a SD card, but there is no law saying you couldn’t send it to some kind of IoT host like Xively. So all I need is the interface to the batteries to track the voltage and current; I used a 2.5V torch bulb for the load because it does not seem unreasonable to me to expect batteries to be used in a torch, I use two batteries in series, which seems to be the most common configuration in a torch. On the way to ground I use a 1 ohm resistor so I can measure between ground and the top of the bulb the battery voltage and between the resistor and ground the voltage corresponding to the current. Using 1 ohm makes the calculation easy, and also drops about 0.3V so the bulb is run at 2.7V at the start.
Now if you are looking to do this in a big way then these guys at Battery Showdown are doing this is a more rigorous way but their hardware is dearer. I’m also not absolutely sure that a constant current discharge is typical of many loads. something like a digital camera with a switch mode PSU actually increases its peak load with decreasing battery voltage because it is more a constant power device and needs to draw more current at a lower voltage to run the focusing bits. Something with a linear voltage regulator is a constant current to the dropout voltage of the regulator, but you don’t often see linear regulators in battery-powered kit.
The bulb isn’t ideal either, with a varying resistance with temperature, so I’d probably favour using resistive loads, and getting four/five battery channels instead of two. But the visuals were great for the video.
If you have a PC that can take RS232 then simply wire the output of the PIC to the PC serial port via a Max232 chip or single transistor inverter if you don’t need the radio connection. Since I have the datalogger logging other sensors it seems easy enough to use it as is.
I used a PIC16F870 that has five A/D channels – this gives me two battery channels. Each battery channel has one A/D port connected to A in the diagram, another one to B and 0V is connected to C. The voltage at B is the same as the current since R is 1Ω and the voltage at A is the battery voltage itself. The 10-bit A/D converter goes up to 1024, by setting the reference voltage to be the PIC power supply at the high end and PIC ground at the low end I made the maths easier by setting the PIC supply voltage to 5.12 V (this is within the PIC operational voltage spec of 4 to 5.5V) in which case a straight divide by two gives V in * 100, and matches the requirements acceptably.
Doing this for the Poundland batteries shows the difference between the alkaline and the ZnCl batteries
If we take the service life as down to 2V from 3V initially, then you get 1.7 hours from the cheap ones and 5.8 hours from the alkalines.Alkaline cost/hr is 17*2/5.8=5.9p/hr and the cheap batteries cost 9*2/1.7=10.6p/hr.
As a result you pay about twice as much to run something using the cheap Poundland batteries, and you get to replace the batteries three times as often. Saving money therefore costs you a fortune in aggravation and generates more waste. You also have this sort of problem if you don’t pay attention and leave the used batteries in too long.
The device offers an insight into the capacity of rechargeable batteries which is the more useful feature of it.
I am not really sure I understand the pathology behind the second wind the NiMH cells seem to have. I’d discard it as a fault in reading except that – the current shows the bulb did not blow or become loose, and the A/D and voltage reference is multiplexed, so the error should have shown elsewhere. will repeat this and see if it happens again – probably not as this battery has been totally flattened so it is not the same battery.
For rechargeables I will modify this rig to take four individual cells and discharge through four resistors. That way I don’t back-charge any weak cells, and I don’t need to measure the current as the terminal voltage and Ohms Law will tell me the current. If I run 2.7Ω I will run about 440mA.
JAL code
The JAL code for the PIC is 1311_datalogger_v06.jal
-- JAL 2.4i -- derived from univ-sensor_v06 -- Datalogger -- adjust power supply to 5.12V using the LM317 regulator. -- internal Vref = VCC = 5.12V -- Can just divide ADC by 2 and shift dec point by two places -- v06 12 Nov 2013 RM -- CC BY-SA 3.0 -- http://creativecommons.org/licenses/by-sa/3.0/ -- serial port designed for use with a Ciseco XBBO board and radio ( Google it) -- can also use w/o radio via a Max232 or a FTDI adapter instead -- radio is powered down while ADC measurement made to avoid loading regulator voltage include 16f870 pragma target clock 4_000_000 pragma target osc HS ; use a 4MHz crystal or resonator pragma target WDT ENABLED pragma target PWRTE ENABLED pragma target BROWNOUT ENABLED pragma target LVP DISABLED pragma target CP DISABLED pragma target CPD DISABLED -- HS, -BOD, ,-LVP, -WDT, -CP = 0x3F22 ;pragma target fuses 0x2007 include pic_general include print include format -- set all interrupt sources disabled ;INTCON = 0 -- ADC includes delays so don't include this myself -- V2 delay's -- include delay_any_mc -- more delay functions -- include extradelay -- the analogue pins pin_a0_direction = input pin_a1_direction = input pin_a2_direction = input pin_a3_direction = input -- there is no a4 analogue channel pin_a5_direction = input pin_c7_direction = input pin_c5_direction = output pin_c6_direction = output pin_A4_direction = output ; this is open drain so 3V3 pullup comes from XRF alias xrf_sleep is pin_A4 ; pull this low to start the XRF, let go and float up to enter sleep xrf_sleep=low ; must enable with ATSM2 -- now configure ADC (this is a 10-bit ADC) const bit ADC_HIGH_RESOLUTION = true const byte ADC_NCHANNEL = 1 const byte ADC_NVREF = ADC_NO_EXT_VREF include adc adc_init() -- ok, now setup serial, we'll use this -- to get ADC measures -- all this is because the 16f870.inc file is not right for serial hardware 8/5/13 alias RCIF IS PIR1_RCIF alias TXIF IS PIR1_TXIF alias BRGH IS TXSTA_BRGH alias RCIE IS PIE1_RCIE alias TXIE IS PIE1_TXIE alias TXEN IS TXSTA_TXEN alias TRMT IS TXSTA_TRMT alias SPEN IS RCSTA_SPEN alias OERR IS RCSTA_OERR alias CREN IS RCSTA_CREN -- end of -- all this is because the 16f870.inc file is not right for serial hardware alias PEIE IS INTCON_PEIE alias TMR1IE IS PIE1_TMR1IE alias CCP1IF IS PIR1_CCP1IF OPTION_REG = 0b00001111 ; PS asllocated to WDT and slowest rate selected (20ms*128) PEIE = high TMR1IE = high T1CON=0b00110001 ; set timer 1 running internal osc 8xprescaled CCP1CON=0b00001011 ; reset tmr1 on match, kicks off an A/D conversion ; these next values seem to call a period of 10s from previous project CCPR1H=244 ; decimal CCPR1L=36 ; decimal -- so count is 244*256+36 = 62500 At 4MHz each tick is 1uS, prescsaled by 8 to 8uS ticks. -- const byte cyclesmax=60*2 -- how many times to count 0.5s ticks var word mincounter = 0 ;var byte lastTMR0=0 ;TMR0=0 -- clear at start -- ok, now setup serial; const serial_hw_baudrate = 9600 const bit usart_hw_serial = TRUE const bit lowspeed=true include print include serial_hardware serial_hw_init() const byte booted[] = "aVVSTARTED--" const byte prefix[] = "aVV" const byte line1[] = "+++" const byte line2[] = "ATSM2r" const byte line3[] = "ATACr" const byte line4[] = "ATDNr" const byte line5[] = "ATID0AFFr" const byte vpfx[]= "VLT" procedure WaitOnOk() IS -- state machine - aim is to hang and -- if this doesn't get to 2 the WDT will start things over after 2 sec -- if it gets to 2 it clrwdt anbd returns var byte state=0 asm clrwdt while state !=2 loop if serial_hw_data_available then if state==0 & serial_hw_data == "O" then state=1 ; this is the only way to get to state 1 end if if (state == 1) & (serial_hw_data == "K") then state=2 else state=0 ; because O was followed by something that wasn't K end if end if asm clrwdt end loop end procedure procedure justify(word IN myval) IS -- value is going to be 0..1024 (in reality 0..512) -- hundreds are integers, ie 2 d.p. -- assumes radio is up and running format_word_dec(serial_hw_data,myval,3,2) -- 0 .23 serial_hw_data="-" end procedure function get_volts() return bit is var word reading1 var word reading2 var word reading3 var word reading4 var word reading5 asm clrwdt -- get ADC result, high resolution reading1 = adc_read_high_res(0)/2 asm clrwdt -- get ADC result, high resolution reading2 = adc_read_high_res(1)/2 asm clrwdt -- get ADC result, high resolution reading3 = adc_read_high_res(2)/2 asm clrwdt -- get ADC result, high resolution reading4 = adc_read_high_res(3)/2 asm clrwdt -- get ADC result, high resolution reading5 = adc_read_high_res(4)/2 asm clrwdt -- send it back through serial xrf_sleep=low -- start the radio a little before the data will be sent. -- may want to change the LLAP prefix and comma del if not using radio delay_100ms(2) asm clrwdt print_string(serial_hw_data,prefix) print_string(serial_hw_data,vpfx) serial_hw_data="A" justify(reading1) asm clrwdt delay_100ms(5) -- no need for this dela if going straight out on serial print_string(serial_hw_data,prefix) print_string(serial_hw_data,vpfx) serial_hw_data="B" justify(reading2) asm clrwdt delay_100ms(5) -- allows the LLAP data to be received properly asm clrwdt print_string(serial_hw_data,prefix) print_string(serial_hw_data,vpfx) serial_hw_data="C" justify(reading3) asm clrwdt print_string(serial_hw_data,prefix) print_string(serial_hw_data,vpfx) serial_hw_data="D" justify(reading4) asm clrwdt delay_100ms(5) asm clrwdt print_string(serial_hw_data,prefix) print_string(serial_hw_data,vpfx) serial_hw_data="E" justify(reading5) asm clrwdt delay_100ms(2) -- let the signal be transmitted and buffer empty xrf_sleep=high -- stop the radio ftre the original data sent return true end function -- MAIN PROGRAM START asm clrwdt asm sleep ; use the WDT to delay about 2s to ; boot the sensor and radio asm clrwdt -- now initialise the XRF to the system network ID and enable sleep mode -- clear out any pre-existing RX buffer var byte rxd while serial_hw_data_available loop -- check if data is ready for us rxd = serial_hw_data -- get the data end loop rxd=" " if true then ; loop is simply to enable/disable ; if you have no radio then use if false then asm clrwdt ; this setup routine for testing xrf_sleep=low ; setup the radio using AT commands print_string(serial_hw_data, line1) ; send +++ WaitOnOk print_string(serial_hw_data, line5) ; change network with ATID0AFF delay_100ms(1) print_string(serial_hw_data, line2) ; enable sleep mode with ATSM2 delay_100ms(1) print_string(serial_hw_data, line3) ; and use it - send commit delay_100ms(1) print_string(serial_hw_data, line4) ; ATDN we are done configuring delay_100ms(10) print_string(serial_hw_data,booted) delay_100ms(2) xrf_sleep=high -- power down the radio end if forever loop asm clrwdt if CCP1IF then CCP1IF=false; mincounter=mincounter+1 end if if mincounter >= cyclesmax-1 then mincounter=0 var bit b = get_volts() end if end loop
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.
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”
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
and the hex file
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.