Sensor Workshop
Sketch 1 - Sensors and Time

Build a simple microcontroller/sensor system that outputs the sensor's changes over time, in order to visualize or sonify the sensor's reaction curve. This piece of code, written in Processing, is a good place to start. The output of your system should be very simple, and give a clear picture of the changes in the sensor over time.

Introduction:
I decided to build a simple system to monitor the level of light falling on a CdS photocell like the ones sold by RadioShack as part number 276-1657. This type of sensor has a resistance that varies inverse to the amount of light striking it and so, by reading the voltage across the sensor, the relative light level of an area can be determined.
Use Scenarios:
There are a number of places and ways this system could be used:
1. To measure the ambient light level in a room over time
2. Mounted in a refrigerator, it could be used to determine how often the refrigerator door was opened and for how long - the sensor would respond to the light inside the refrigerator going on and off as the door was opened and closed.
3. If the sensor were taped to the power LED on a television or a corner of the television screen, this system could record TV-watching patterns
4. If the sensor were taped to the hard drive LED on a computer or any of the LEDs on a router, this system could record the use of these resources
Design Details:

Early on I decided to construct the system so that it would read its attached photocell once a second. This doesn't provide a very fast response to changing light conditions but since I originally intended the system to measure the light level in my apartment throughout the day, I made this tradeoff in responsiveness to cut down on the amount of data that would be generated.

I selected a PIC18F252 microcontroller for the heart of the sensor system for its small size, reasonably accurate analog-to-digital converters, and the fact that I had plenty on hand. Since this PIC does not have enough memory to store an entire day's worth of readings I needed to attach it to a host PC that could save the readings as they were made. Since it would be inconvenient to have the sensor circuit tethered to the computer by a serial cable I wanted to try using a Bluetooth modem for wireless serial communication (the BlueSMiRF Basic from Sparkfun) that I had purchased last semester. Remembering the problems I had with this device last semester though, I designed the circuit to be able to communicate over either a wired or wireless link.

I began by constructing the circuit shown in figure 1 on a breadboard. The circuit is powered by a 9-volt battery regulated to 5 volts by a linear voltage regulator. I did this so that the circuit would not need to be tethered to a wall outlet for power. With battery power and a wireless link to the host computer, I was hoping to be able to put the sensor circuit anywhere in my apartment.

In operation, the code running on the PIC waits for a '?' character to come in over the serial connection. This is a request from the PC for a new reading. The PIC reads the voltage on analog pin 0, encodes it as an 8-bit value and sends it out over the serial connection then goes back to waiting for a request for another value.

Program Operation:
Three programs on the host PC work together to produce a visualization of the data captured over time. The first handles communication with the sensor circuit over the serial port. Once every second it sends a request for a new reading and stores the value it receives in memory. Once it has received 60 seconds worth of readings it writes the values with a time stamp for each to a text file and then goes back to receiving readings. The second program is very simple - it concatenates the contents of all of these files into one large file. The third program works from this file that contains a second-by-second reading of the light levels throughout the day and uses them to simulate the light level at any given time.
Processing Code:

Datalogger Processing code
Concatenating Processing code

Display demonstration
sample readings
Schematic:
PIC Code:
'****************************************************************
'*  Name    : sensor_workshop_sensors_and_time_rev0.BAS         *
'*  Author  : Zachary Eveland                                   *
'*  Notice  : Copyright (c) 2006 [select VIEW...EDITOR OPTIONS] *
'*          : All Rights Reserved                               *
'*  Date    : 1/26/2006                                         *
'*  Version : 0.0                                               *
'*  Notes   : reads a photoresistor and outputs the		* 
'*          : A/D result serially in response to a query from 	*
'*	    : the host PC.  tested on a PIC18F252     		*
'*          :                                                   *
'****************************************************************

DEFINE OSC 4

DEFINE ADC_BITS 10      'ADC resolution in bits
DEFINE ADC_CLOCK 3      'ADC clock source (3 = RC)
DEFINE ADC_SAMPLEUS 10  'ADC sample time in uS

TRISA = %11111111       'make all pins on PORT A inputs
TRISB = %00111111	'make all but the the LED pins on PORT B inputs
TRISC = %10111111	'make all but the TX pin on PORT C inputs
ADCON1 = %10000010      'pins 0-4 of PORT A are analog inputs,
                        'ADC results are right-justified, Vref+
                        'is Vdd and Vref- is Vss

start:
'we define two different baud modes to accomodate both wired (through
'a standard serial cable) and wireless (through a BlueRadios Bluetooth
'serial cable replacement)
wirelessBaudMode CON 84     	'9600,8,N,1,true TTL logic levels
wiredBaudMode CON 16468     	'9600,8,N,1,inverted (pseudo-RS232)

powerLEDpin VAR PORTB.7
statusLEDpin VAR PORTB.6
photocellPin VAR PORTA.0
serialRXpin VAR PORTC.7
serialTXpin VAR PORTC.6
baudModePin VAR PORTC.3		'used to select the baud mode to use:
				'a pullup resistor keeps this pin high and indicates
				'serial cable operation, if pulled low it indicates
				'wireless operation

baudMode VAR WORD		'stores the current baudmode to use (as
				'selected with the baudmode pin)
photoVoltage VAR WORD		'stores the ADC value for the photoresistor
inByte VAR BYTE			'stores the last byte received from the PC
outByte VAR BYTE		'stores the byte to send to the PC
i VAR BYTE			'counter 

photoVoltage = 0
inByte = 0
outByte = 0
i = 0

HIGH statusLEDpin
'a little POST routine
FOR i = 0 TO 3
	PAUSE 80
	LOW powerLEDpin
	PAUSE 80
	HIGH powerLEDpin
NEXT i

main:
IF (baudModePin == 1) THEN 
	baudMode = wiredBaudMode
ENDIF
IF (baudModePin == 0) THEN 
	baudMode = wirelessBaudMode
ENDIF
SERIN2 serialRXpin, baudMode, 1000, timedOut, [inByte]
IF (inByte == 63) THEN 		'63 == '?' - the PC is requesting a value
	ADCIN photocellPin, photoVoltage
	outByte = photoVoltage/4
	SEROUT2	serialTXpin, baudMode, [DEC outByte]
	inByte = 0
	FOR i = 0 TO 3
		PAUSE 80			
		LOW statusLEDpin
		PAUSE 80
		HIGH statusLEDpin
	NEXT i
ELSE 				'something other than '?' was received, report
				'the error by blinking the status LED
	LOW statusLEDpin
	PAUSE 500
	HIGH statusLEDpin
ENDIF
GOTO main

timedOut:
inByte = 0
LOW statusLEDpin
PAUSE 80
HIGH statusLEDpin
GOTO main