PIC16F18855/75 with HC-SR501 PIR Motion Sensor


Motion detection for light control or alarm trigger.


Since we covered the basics in our previous posts adding another module is unspectacular from the circuit point of view. We will use our LCD circuit do demonstrate the output.

The Code

Even the code will now be very simple. The HC-SR501 already integrates a circuit sending logical “1” if there is a motion detected and a logical “0” if there is no motion detected. The sensitivity and delay time is also taken care of in the module. We just need to configure the choosen pin (RA6 in this example) as output and configure Interrupt-on-Change (IOC) for it. We do that by opening the MPLAB Code Configurator (MCC) and in the “Interrupt Module” tab we check the “Pin Module” to be enabled.

Please consult our previous post on setting up a project, basic configuration and I2C communication with the LCD.

Then in the “Pin Module” tab we “Analog” and “Output” checkboxes are unchecked and the “any” is selected in the “IOC“. This will trigger our interrupt on both, the raising and the falling edge.

We just set an flag in the interrupt handler itself and deal with the heavy lifting in our main loop:

 * File:   main.c
 * Author: Jan Kubovy <jan@kubovy.eu>
#define LCD_ADDRESS 0x27 // change this according to ur setup
#define LCD_COLS 20
#define LCD_ROWS 4

#include <stdio.h>
#include "mcc_generated_files/mcc.h"
#include "modules/i2c.h"
#include "modules/lcd.h"

bool doRA6Interrupt = false;

void pinRA6InterruptHandler(void) {
    doRA6Interrupt = true;

void main(void) {
    SYSTEM_Initialize(); // initialize the device

    // When using interrupts, you need to set the Global and Peripheral
    // Interrupt Enable bits Use the following macros to:
    INTERRUPT_GlobalInterruptEnable();      // Enable the Global Interrupts
    //INTERRUPT_GlobalInterruptDisable();   // Disable the Global Interrupts
    INTERRUPT_PeripheralInterruptEnable();// Enable the Peripheral Interrupts
    //INTERRUPT_PeripheralInterruptDisable(); // Disable the Peripheral Interrupts

    while (1) {

        if (doRA6Interrupt) {
            doRA6Interrupt = false;
            if (PORTAbits.RA6) {
                LCD_send_string("|c|Movement!", 2);
            } else {
                LCD_send_string("|c|Still", 2);


A very simple way how to add ready made sensors or react on changes on GPIO pins was shown here.

Leave a Reply

Your email address will not be published. Required fields are marked *