Skip to content

PICAXE clock exercise: backwards compatibility creates confusion for interrupts and touch

Exploring two advanced concepts, interrupts and touch input, highlighted errors and confusion in Revolution’s PICAXE documentation. In both cases, newer mcu’s have added features that provide interesting capability yet Revolution hasn’t done a very good job in updating PICAXE or its documentation. They don’t make it clear what commands are being superceded; they enhance commands with new commands rather than extending options; they confuse the pin nomenclature with different terms for different functions implying an inadequate programming model for the underlying hardware; the examples they provide are not qualified to distinguish new syntax or commands from older ones for various mcu’s.

Note here that I am using the term “PICAXE” to refer to the interpreter, the ‘computer language’ that Revolution installs in the mcu with the boot loader, rather than BASIC. That is because, while PICAXE is often BASIC like, it does very little that even a 4k BASIC on the early microcomputers could do. PICAXE is a simplified interface to the mcu capabilities that makes the use of the microcontroller much easier. It includes logic control structures and some expression translation but very little else that a proper BASIC language should include.

For interrupts, it is understandable that PICAXE would isolate the programmer from the hardware. That leads to a problem using pin state changes to wake the mcu from sleep states allowed in the advanced mcu’s. SLEEP is a way to reduce power consumption. A pulse output of the clock chip can toggle a pin every second to wake up the mcu so it can update the display as necessary then go back to a low power state. The chip is designed for this sort of thing to reduce battery load and low energy use is a design goal for mcu designers.

In PICAXE, you don’t have direct control over the mcu global interrupt enable flag. Instead, the ‘SETINT’ command is used to control the interrupt. This will cause a branch to a user interrupt routine when a supplied mask matches the state of an input port as checked between each PICAXE command. Newer mcu’s added more ports to this command. This means the mcu has to be in full operation before a user program can detect an interrupt in the usual PICAXE model.

For an interrupt on the X2 hardware interupt pins, the serial I/O system, or the timer, the ‘HINTSETUP’ command was added to define the parameters for the hardware interrupts and the ‘SETINTFLAGS’ was added to enable or disable interrupts on those particular events. Since the hardware interrupts for X2 parts can wake a processor from sleep, that command has been enhanced so that ‘SLEEP 0’ will put an X2 mcu into “permanent sleep” that requires a hardware interrupt or hard reset to change. The implication is that PICAXE has a low level interrupt handling routine behind the curtains to handle this situation but Revolution doesn’t tell you this. 

The interrupt routine you put in your program does not automatically re-enable interrupts like the chip level routine does. That means you need to re-issue a SETINT or SETINTFLAGS command to get PICAXE to start checking between commands for an interrupt condition. It also means that PICAXE likely checks for interrupt conditions even between commands in the interrupt routine.

Here’s the code to use the clock interupt:

; ============================
    hintsetup %00000001    ; interrupt 0 on falling edge

    setintflags %00000001,%00000001 ; interrupt on B.0 as per hintsetup above
    Disablebod  ; disable brownout detect to save power
    Sleep 0     ; wait for hardware interrupt

    gosub read_clock    ; update display with clock data

    Touch16 touch4, ij
    ; SerTxd ("touch input = ",#ij,cr,lf)

    If ij > 120 Then    ; magic value determined by experiment
        Gosub zero_seconds  ; adjust time if button pushed
Goto clock_loop

; interrupt handling
; just pull it out of sleep and let main routine do all processing
    ; could check flags here if multiple things are being watched
    ; in order to figure out what to do
; ================================

TOUCH, channel, port, pin

The TOUCH command uses a capacitance measurement technique to implement touch buttons. This can be handy for a number of things besides interactive input. The problem is that there is only one place in the three PICAXE manuals where the command’s “channel” is shown as apppropriate to the X2 chips. In the PICAXE product briefing there is a note about this but otherwise the command definition and examples all indicate that “channel” in the definition means a port bit label. That highlights sloppiness in definitions in the manual that can create significant programmer frustration.

It is bad enough that the documentation suffers but the tokenizer will also accept improper syntax for the X2 chips to create a program that produces all sorts of spurious output on the ADC channels. You do what the manual and examples tell you will work and find your program goes berserk.

To understand this, one needs to discriminate between the actual chip pins and the internal organization of these pins as bits on input and output ports. The next level discriminates between the input and output functions that are appropriate to the port model and other functions that do not use that port model. Those ‘other functions’ are often functions added or enhanced on the newer chips like the X2. PICAXE manual 2 has an entire section on pin naming conventions. Unfortunately, it does not cover advanced function pin labeling like for ADC channels. When using ADC related commands on most chips, the command definition reference to “channel” means a port bit label as shown in the examples. On the X2 parts, “channel” means the ADC channel number as shown in the ADCSETUP command tables that map setup mask pins designated by the port bit they’d use for normal I/O.


It seems to me that Revolution would better serve its educational goals to go back to the simple, early mcu model and leave the I/O port,  ADC flags and registers, and interupt descriptions for advanced usage. Create a command that defines how the mcu pin is being used in a project and have the tokenizer (what some call a compiler) take care of (a) making sure that function is available on that pin for the chip defined in a required directive (e.g. “#PICAXE 08m2”) and (b) setting the appropriate flags and registers as needed to implement that function on that pin. Then the programmer could just refer to a hardware pin any time it is needed to identify the target for an mcu function. Of course, good programming practice is that the pin should have a #SYMBOL directive to help document its use in the circuit and to allow for easier software porting between chips.

Post a Comment

You must be logged in to post a comment.