OWL2 Stamp to rain gage or traffic counter
Tipping bucket rain gages signal each increment of rain (.01 inch or 0.2 mm) with a brief switch closure. A reed switch is activated by a magnet as the bucket tips from one side to the other. The tip frequency varies from zero in dry weather, to up to about one tip per second in torrential downpours. The pulse is brief, roughly 30 milliseconds in duration. Similar signals come from other kinds of event counters or traffic counters. Neither the PULSIN nor the COUNT commands in the BS2 work well with this type of signal, because of the wide range of times involved and the single-tasking manner of BS2 operation.
Here's one solution. The rain gage switch is set up to discharge a capacitor . The capacitor "stores" the "tip" event until the stamp gets around to looking at the input. (see diagram below) To begin, the stamp io pin is made a high output, which charges the capacitor +5 volts. Then the stamp io pin is made an input, so that the capacitor retains the charge, and the input can be sampled to sense the capacitor voltage. When the rain gage switch closes, the capacitor discharges thru the diode. When the switch opens, the diode prevents recharging. The 2k pullup resistor prevents leakage current across the rain gage switch (due to moisture, leaky cables etc.) from discharging the capacitor. In an environment where you can be assured that the switch will never have any leakage, you can dispense with both the diode and the 2k pullup resistor. The leakage is a practical consideration, very real out in field settings.
Here is a simplified version of the above circuit. It says "clean switch", because this circuit will not tolerate a "leaky" switch". Any conductiivity across the switch (as might come from condensation on a rain gage switch, or a nick in the cable), would discharge the capacitor. Some tolerance can be added by increasing the value of the capacitor.
Once the stamp input registers the discharged capacitor and increments the count, it recharges the capacitor to arm for the next tip. This takes advantage of the ease with which the stamp can switch any of its i/o pins between input and output modes. The capacitor can hold the charge for minutes at a time, due to the high input impdeance.
rout con 8 'assume p8 is used for the rain gage rin var in8 ' alias for the state of p8 rain var byte ' for count of tips--could be made a word variable loop: rain=rain+1-rin max 254 ' count advances when pin is low, up to 254 high rout ' recharge the capacitor, 200 microsecond pulse. input rout ' and await next tip ' other stuff debug dec rain,cr ' show it pause 1000 ' or do other stuff goto loop:
Usually there will be some point in time when the rain count will be logged into a file. The rain count can be rezeroed at that time. The routine recharges the capacitor each time through the loop, whether it needs it or not. Thisassures that the capacitor stays charged.
There is a probability for error. When the rain gage tips, the switch stays closed for 10 to 50 milliseconds, in any event, much longer than the 200 microseconds it takes for the Stamp to discharge the capacitor using the high and input instructions. It may happen that the discharge pulse comes along in the middle of the tip, so that the capacitor discharges right away and the event is erroneously counted counted twice. You might decrease that error by putting a delay between the high and input instructions, but that would lead to the opposite error, missing a pulse altogether. The following snippet makes sure that the capacitor is discharged for good before continuing:
surehigh: high rout ' recharge the capacitor, 200 microsecond pulse. input rout ' ready to test input state branch rin,[surehigh] ' if capacitor is not recharged, try again until it is ' ..continue...
The branch instruction sends the routine back to surehigh so long as the input pin remains low.
Here is another way to accomplish the same thing. The problem with the above fix is that the program will lock up if for some reason the rain gage is "stuck" closed, at the lo level. That might happen if the rain gage bucket is physically jammed at the middle position, or if the reed switch inside the rain gage becomes welded shut, or if the whole rain gage is flooded so the switch stays underwater or under a mud slide, or if an animal chews on the rain gage cable and shorts it out. That is the fun of real world electronics. Anyway, you do not want the data logging program to lock up just because the rain gage becomes shorted out. The following variation pauses the program until the rain gage input to go back high, OR until a time limit of about 70 milliseconds expires. The time limit is determined by the counter variable. The variable starts at zero and counts up. If it gets to 128, the seventh bit is set, and the routine exits no matter what. This technique is often useful to break out of wait loops.
x var byte x7 var x.bit7 ' alias for bit 7 of x x=0 surehigh: high rout ' recharge the capacitor, 200 microsecond pulse. input rout ' ready to test input state x=x+1 branch rin|x7,[surehigh] ' branch back until rin OR timer goes high ' ..continue...
The following are some advanced techniques. I quite often work with hydrologists, to whom monitoring of water becomes a fine art.
In some situations, more than one counter is needed. This might be multiple rain gages, or it might be traffic or animal activity counters, what have you. There is no need to repeat the above code in its entirety for each instance. The following implements four counters as an array. The inputs are OWL2c i/o pins 1 and 2 (stamp P8, P9, P10 and P11). Each input has its own storage capacitor. This routine makes use of BS2 implied indexing. See the BS2 v1.9 manual.
rains var byte(4) ' four counters rin var in8 ' alias for input state variable rout con 8 ' pin number of first rain channel rix var nib ' index for rain gage top: for rix=0 to 3 rain(rix) = rain(rix) + 1 - rin(rix) max 254 ' increment the rain count ' associated with this input high rout+rix ' refer to correct pin, charge capacitor input rout+rix ' armed for next event debug dec rain(rix),tab next debug cr goto top
The above makes use of implied indexing. "rin" is a symbol that refers to in8, the reading on stamp i/o P8. By implication rin(0) is the same as rin, and rin(1) refers to the next pin over, stamp i/o P9. And so on, up to P11.
Rain gages are active when the rain is falling, but do nothing in dry weather. The same is true of many kinds of traffic counting. When it is raining hard, the rain gage needs to be scanned every few seconds, or even once a second in a torrential downpour. However, there is no point in checking it so often in dry weather. In fact, a data logger may need to take a vacation and go to sleep for longer intervals for power conservation. It can sleep more in dry weather, but it needs a program mechanism to stay 'alert' during rainy periods. The following implementation uses a counter. If rain is detected, the counter is initialized to a high value. Every so often, the counter is decremented, and when it gets back to zero, the logger goes back into its 'sleepy' mode. So long as the counter is non-zero, the logger stays alert.
rout con 8 ' assume p8 is used for the rain gage rin var in8 ' alias for the state of p8 rain var byte rat var word ' iteration counter, if non-zero, then alert mode rib var bit ' = 1 in alert mode rains: rain=rain+1-rin max 254 ' count advances when pin is low rat = 1-rin * 3600 + rat max 3600 ' one hour time high rout ' discharge the capacitor 220 uS input rout ' await next tip ' other stuff rat = rat - rib ' decrement rat rib = rat max 1 ' counts down to zero and stops pause 1000 ' 1 second pause, or do other stuff if rib then rains ' scan intensively during rain event sleep 30 ' or just kick back during dry weather goto rains
The above routine goes into an intensive monitoring program if the rain gage bucket tips once.
In hydrological studies, logging needs to occur more often when rain is falling. For example, it is desireable to log data at 5 minute logging intervals during and for 3 hours after substantial rainfall, and hourly otherwise. That would capture the details of significant hydrological events, without eating up the logging memory with boring nothing. This can use the same logic as the above. So long as the timer is non-zero, the log interval is short. It is best to decrement the counter once per minute, so that the time intervals can be exact. The program needs a one minute task handler. Here is a snippet (details not shown)
' once per minute, do the following rat = rat - rib ' decrement the counter of wet minutes, not <0. rib = rat max 1 ' rib is 1 when rat is >0 logint = 60 - (55 * rib) ' 60 minutes in dry weather, 5 minutes in wet weather. ' this is the logging interval