PIC32 Push Buttons

Port Input - Push Putton

This small example goes through the basics of getting digital information into the microcontroller and looks at various ways of how to do this.

push button schematic

This is the basic circuit. Under normal circumstances port 'e' bit 4 is held high by R1 (say 10k). When the push button is pressed this shorts RE4 to ground. To detect this, that bit on the port will need setting to input. This is done by default at reset but it is good practice to do this again as the port may have been used as an out put in some other part of the program.

function pb_init
    portb "ets" 4 // port e bit 4 as i/p
endf

This code will set port 'e' pin 4 to be an input. To make the code easier to read, this following function returns 0 if the button is pressed and not 0 otherwise.

function pb_scan
dim pb
    portb "ei" pb
    result and(pb,0x10)
endf

  To test this the following code is used:

function pb_test
dim count=0
    pb_init
    while key?(2)=0
        if pb_scan = 0 then
            count=count+1
            print "button pressed",count
            while pb_scan=0:wend // wait
        endif
    wend
endf

The function starts by initialising the port bit for our use. Count is used simply for visual effect and detecting key?(2) means that we can get out of this endless loop without having to reset. The function works by waiting for the button to be pressed (pb_scan=0), if it is pressed then it waits for it to be released before continuing. Without this wait there would be a continuous stream of 'counts' until the button is released.

For this system this should actually work quite well as there is a certain amount of delay the switch bounce phenomena is not really present. When two electrical contacts come together they take a finite time to actually touch and stay connected. On the human scale of things this is completely undetectable but for a microcontroller this may represent several button presses rather than just one. To overcome this problem a delay is introduced in the millisecond region (between 2 and 50). Some systems make absolutely certain by taking two or more readings over a period of time.

The main reason why this works well without debounce is because of the print statement which because its printing to the console takes just over a millisecond to get the information out, by this time the switch has stopped bouncing and the 'while:wend' wait loop can do its job properly. In nearly all cases inserting a delay of a few ms after the switch has been pressed and before detecting its release works well.

Scheduling

This is a good opportunity to look at how scheduling may be used to look after port inputs whilst the main program gets on with other jobs. Just to make things more interesting connect an LED up to RE3 such that the Anode (ling lead) is to 3v3 and the shorter lead is to the port pin.

 Below is the whole of the modified code.

function pb_init
    if vexists("sw1")=0 then
        portb "ets" 4 // port e bit 4 as i/p
        portb "etc" 3 // port e bit 3 as o/p
        dim sw1=0
        process pb_scan every 35
        keep
    endif
endf

function pb_scan
dim pb
    if sw1 = 0 then
        portb "ei" pb
            if and(pb,0x10)=0 then
                sw1=1
            endif
    endif
endf

function pb_get
    if sw1=1 then
        portb "eoc" 3 // led on
        wait 200
        sw1=0
    endif
    portb "eos" 3 // led off
endf

function pb_test
    pb_init:keep
    process pb_get every 45
endf

pb_init: This has been extended to initialise RE3 for the LED indicator. It also places pb_scan into a schedule so it will be called every 35ms.

bp_scan: The variable sw1 keeps track of if the switch has been pressed, if it has then the scan is ignored until the variable is cleared. This is called in a schedule and so cannot contain any blocking code. (this is blocking code while 1=1:wend)

pb_get: This is also in a schedule and its job is to turn on the LED is sw1 is high. It also clears sw1 for next time. The wait 200 is necessary so that the LED can be seen to be lit. The wait keyword does not block the scheduling.

pb_test: this is called to initialsie the code. The switch can be pressed and the LED will light even though there appears to be no program running, i.e. the user is returned back to the ok prompt. An important point to note is that because there is no "switched pressed" text to print, debounce could become and issue. the debounce in this system is 10ms. How? It is the time lag between pressing the switch and getting the results -- the difference in schedule between 35ms and 45ms. Careful here because a process time on the pb_get of say 71 ms would not give a larger debounce but a smaller one of 2ms.