PICAXE Interrupts & Rain Gauge

August 29, 2013

The PICAXE can be configured to look for an interrupt. This will cause it to stop whatever it is processing, jump away using GOSUB, and then RETURN back to what it was doing before.

This is done using the setint command. This takes two binary numbers, the first is what to listen for and the second is the mask. We'll make these both the same, because we're only listening on one input.

At its simplest, this can be shown with the following example:

    setint %00001000,%00001000,C

main:
    low C.1
    pause 2000
    goto main

interrupt:
    high C.1
    if pinC.3 = 1 then interrupt
    pause 2000
    setint %00001000,%00001000,C
    return

Here we have a push button on C.3, and an LED on C.1. The LED is normally off, when the button is pushed this causes the interrupt to fire which lights up the LED. Once the button push has gone away, we return to normal and the LED is switched off again.

The setint command is passed 00001000. Counting from the right, these digits are the inputs on the PICAXE, so if we used 00000001 this would refer to C.0. 00000010 would be C.1 and so on, so in this case we're using C.3.

Raingauge

My immediate goal for the PICAXE is to retrofit an existing raingauge with a PICAXE circuit such that it can record temperature and raingauge tips, and transmit them via ERF/URF to a computer.

To this end, we can take the existing temperature sensing circuit and add the interrupt code to it so that it transmits a RAINTIP:1_ every time the button is pushed. In real life, this will be a magnet passing a reed switch when the raingauge bucket tips.

Here's the completed code:

    setint %00001000,%00001000,C
main:
    symbol TemperatureSign = bit0      ' This holds whether the temperature is positive or negative
    symbol Whole = b1                  ' This will hold the whole number of degrees
    symbol Fraction = b2               ' This holds the fractional part of the temperature, to two decimal places
    symbol TemperatureTimes100 = w3    ' This holds the temperature count in tenths of a degree
    symbol Temperature12 = w4          ' This holds the value read from the temperature sensor
    setfreq m8                         ' Set the frequency to 8Mhz for the ERF module
    high C.1                           ' Turn LED on C.1 on
    readtemp12 C.2, Temperature12      ' Read temperature into Temperature12 variable
    low C.1                            ' Turn LED on C.1 off
    TemperatureSign = Temperature12 / 256 / 128    ' Take the most significant bit from the 16 bit word - this is the sign +/-
    if TemperatureSign = 1 then 
        Temperature12 =  Temperature12 ^ $ffff + 1 ' Temperature is negative, convert number using two's complement
    endif
    TemperatureTimes100 = Temperature12 * 6      ' Temperature12 is the number of 0.0625 increments, so we can get the
                                                 ' temperature * 100 by multiplying by 6.25.  
                                                 'This bit multiplies by 6 and...
    Temperature12 = Temperature12 * 25 / 100     ' ...this bit multiplies by 0.25
    TemperatureTimes100 = TemperatureTimes100 + Temperature12    'add these two values together to get Temperature * 100
    Whole = TemperatureTimes100 / 100             ' Whole number of degrees is this value divided by 100
    Fraction = TemperatureTimes100 % 100          ' Fractional number of degrees is this value mod 100
    if TemperatureSign = 0 then
       if Fraction > 9 then
         serout C.4, N9600_8, ("TEMP:",#Whole,".",#Fraction,"_")    ' Output positive value to network
       else
         serout C.4, N9600_8, ("TEMP:",#Whole,".0",#Fraction,"_")   ' Output positive value with decimal place prefixed by 0
      endif
    else
       if Fraction > 9 then
         serout C.4, N9600_8, ("TEMP:-",#Whole,".",#Fraction,"_")    ' Output negative value to network
       else
         serout C.4, N9600_8, ("TEMP:-",#Whole,".0",#Fraction,"_")   ' Output negative value with decimal place prefixed by 0
       endif
    endif
    pause 1000
    goto main

interrupt:
    serout C.4, N9600_8, ("RAINTIP:1_") 
    high C.1
    pause 1000
    setint %00001000,%00001000,C
    return

References