My family lives in Fresno, which is a fantastic place to live, except that our air quality is quite poor.  I’m sure you can look up how poor and why it is on your own.  I recently discovered that California’s Central Valley has one of the best air quality monitoring networks in the country!  Various agencies collect air quality monitoring data at stations throughout the Valley, including 7 stations in Fresno County and 3 in the City alone!  The stations provide data which is used to predict air quality for the following day at schools, and to support a Real-Time Air Advisory Network (RAAN), which posts hourly ozone and PM2.5 data to a webpage.  Every morning, schools raise a flag indicating the air quality for the day.  The predicted air quality index determines the color of the flag.

It seems odd to me that the school warning system is based on a prediction and does not change with the air quality through the day.  The diurnal cycle of smog production results in huge fluctuations in ozone, which can creep up to very dangerous levels, even on a green flag day.  The static flag system at schools does not inform teachers and parents of these trends.  I don’t think very many people are even aware that State and local agencies (public servants) are producing all this air quality data, and I doubt that most people have the means to look it up.

As a Arduino-equipped disciple of Christ, I can’t help but consider how all the wonderful data being gathered might be better utilized to serve our community, my low-tech neighbors in particular.  A couple of web queries later, I’m well on my way to building a Real-Time Air Advisory Network People-Alerting Machine (RAANPAM)!  I figure I’ll use python script on a computer to look up the data online and tell an Arduino UNO how to display the current air quality data on some sort of big display (like a big color wheel) and sound a horn.

So far, I’ve learned enough python (VERY little required, cuz python is AWESOME!) to grab data from the California Air Resources Board (CARB) website.  CARB actually has more data, like hourly NOx, than the local Air District.  Here’s what I did in python to download the current ozone data (screws up if no data has been posted yet for the day):

This is my first time using python, so let me know if you have any pointers for me.  The idea is simply to download the HTML files from the CARB website that have the air quality data we’re looking for, parse it out with basic string functions like find(), and then somehow deliver that data to the next step for further processing/decision-making.  I imagine there’s a better way to access CARB’s data (SQL database) that wouldn’t depend on CARB maintaining the exact HTML format they use today, but this seems to work right now.  Probably to minimize redundant data pulls, the air quality query results page includes all the data for each pollutant, day, and monitoring station as a comma-separated list in a link to graph the data – a really convenient single string to grab all the data I’m looking for.

# library with now() function for getting date and time import datetime

# library with urlopen() function for loading a web page
import urllib

# Get the current time as a string
now = str(

# Convert current time to three ints (month, year, day)
year = int(now[0:4])
month = int(now[5:7])
day = int(now[8:10])

# Create the URL that will load today’s CARB ozone monitoring data at the Fresno-First monitoring station
ozoneurl = “” + str(year) + “&mon=” + str(month) + “&day=” + str(day) + “&hours=all&county_name=10-Fresno&basin=–AIR+BASIN–&latitude=–PART+OF+STATE–&report=HVAL&”

# Get a file-like object for the ARB web page with today’s ozone data.
f = urllib.urlopen(ozoneurl)
# Read from the object, storing the page’s contents in ‘ozonehtml’.
ozonehtml =

# GOAL OF NEXT FEW STEPS: Find and store the latest ozone data for processing

# Find the comma-separated ozone data (starting/ending place in the HTML)
# (the file has it embedded in a link to plot the data – pretty convenient!)
ozonedatafinish = ozonehtml.find(“Fresno-1st Street,3009″)
ozonedatastart = ozonehtml.find(“value=’”, ozonedatafinish – 500, ozonedatafinish) + 7

# Store the comma-separated ozone data
ozonedata = ozonehtml[ozonedatastart:ozonedatafinish]

# Show the data!

The other day I posted about progress on an aerial photography project.  At the end of the day, my auto-picture-snapping circuit didn’t work.  It’s my first project using a 555 timer (NE555P).  I finally measured the capacitance of the timing capacitor and found it was WAY smaller than I’d thought.  The circuit output seemed to be always high because the frequency was really high.  This also explains the low voltage (averaged over duty cycle)!  I swapped the capacitor with one closer to my design and it flashed LEDs just right!  When I connect the camera up to the MOSFET (2N7000) that is controlled by the output of the 555, I got pictures!  Woohoo!  You should have seen my excitement when it finally worked…actually you can!

it works!

Since our church is not too strong in the revenue department, we try to get creative with fund raisers in order to bring as many people as we can to camp.  This year, we collected stuff for a yard sale and did pretty well.  Our enchilada sale was a success, too.  But we’re still coming up pretty short.  I got the idea to sell personalized aerial photographs that we could take using a tethered balloon.  I’m still not finished with the setup and camp is this weekend, but I think it could be a pretty good little racket.

The plan is to get a cheapo camera that I can wreck without too much heartache (craigslist camera – CHECK!) and send it up with a helium balloon and a picture-taking circuit.  I estimated (assuming ideal gas law and spherical balloon) that a 36-inch balloon could lift about a pound.  I found a website with 36-inch balloons six for $10.  This seems so easy and simple!

I spent a few hours in the middle of last night working on the picture-taking circuit part.  I made progress, but in the end I was pretty disappointed.  I was able to crack open the camera after an hour of ridiculously excessive straining with the wrong-sized screwdriver.  I poked around with some wire to figure out which metal pieces need to connect to trigger the shutter.  Then I soldered wires onto each side of the connection that worked.  After running the wires out of the camera and closing the camera back up, I tested it out by touching the loose ends of wire together and BAM!  There you go – it worked!  This is great, because now it should be really easy to trigger photos with an easy-to-generate signal from a simple circuit or a microcontroller like the Arduino!

I recently bought a hundred 2N7000 MOSFETs from Jameco.  It seems to me that one of these is perfect as a switch to short my two shutter-control wires together.  I also bought a hundred 555 timer chips…because I’m crazy.  But one of these should come in handy to send a shutter-control signal to the MOSFET switch every few seconds when the camera is in the air.  I referenced a handy LM555 calculator website to build this circuit (powered by an ATX power supply for testing):

555 timer circuit for camera shutter control

I tried to size the resistors and capacitors for the 555 timer to generate a periodic square wave signal with about 0.15 seconds of “on” followed by 15 seconds of “off”.  It didn’t work!  When I tried it with 5V supply, my multimeter shows what seems to be a constant 1.9V output from the 555 (Vgs on the 2N7000), which results in a partially on MOSFET with channel resistance around a k-ohm instead of just a couple of ohms.  With 12V supply, I get Vgs of 6V but it seems to have 100% duty cycle (the “pulse” to signal the camera is always on).  I might as well not have a 555 chip in there – no good.  This is the point in the story when I realized the sun had come up and it was time to go to work.  Will need to face this later, as well as the issue of supplying power at 5V or higher when the camera has a 3V supply.