100% found this document useful (1 vote)
385 views

PIC Microcontroller Projects Handson

Uploaded by

Dung Huynh Xuan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
385 views

PIC Microcontroller Projects Handson

Uploaded by

Dung Huynh Xuan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 192

PIC

MICROCONTROLLER
PROJECTS HANDSON
Fingerprint Sensor, PIC16F877A for Temperature,
Mechanical Arm Control, Rotating Encoder, Heart
Beat Monitoring, Warm Printer, RFID, 74HC595
Serial Shift Register etc..,

Anbazhagan K
Copyright © 2020 Anbazhagan K

All rights reserved

The characters and events portrayed in this book are fictitious. Any similarity to real persons, living or
dead, is coincidental and not intended by the author.

No part of this book may be reproduced, or stored in a retrieval system, or transmitted in any form or
by any means, electronic, mechanical, photocopying, recording, or otherwise, without express written
permission of the publisher.
CONTENTS

Title Page
Copyright
Acknowledgments
Introduction
1. Interfacing DHT11 with PIC16F877A for Temperature along with
Humidity Measurement
2. DAC MCP4921 Interfacing with PIC Microcontroller PIC16F877A
3. Mechanical Arm Control utilizing PIC Microcontroller
4. Rotating Encoder Interfacing with PIC Microcontroller
5. Creating PWM flags on GPIO pins of PIC Microcontroller
6. Heart Beat Monitoring utilizing PIC Microcontroller and Pulse Sensor
7. Warm Printer interfacing with PIC16F877A
8. Interfacing Fingerprint Sensor with PIC Microcontroller
9. RFID Interfacing with PIC Microcontroller
10. Interfacing 74HC595 Serial Shift Register with PIC Microcontroller
thank you
ACKNOWLEDGMENTS

The writer might want to recognize the diligent work of the article group in
assembling this book. He might likewise want to recognize the diligent work
of the Raspberry Pi Foundation and the Arduino bunch for assembling items
and networks that help to make the Internet of Things increasingly open to
the overall population. Yahoo for the democratization of
innovation!
INTRODUCTION

The Internet of Things (IOT) is a perplexing idea comprised of numerous


PCs and numerous correspondence ways. Some IOT gadgets are associated
with the Internet and some are most certainly not. Some IOT gadgets
structure swarms that convey among themselves. Some are intended for a
solitary reason, while some are increasingly universally useful PCs. This
book is intended to demonstrate to you the IOT from the back to front. By
structure IOT gadgets, the per user will comprehend the essential ideas and
will almost certainly develop utilizing the rudiments to make his or her very
own IOT applications. These included ventures will tell the per user the best
way to assemble their very own IOT ventures and to develop the models
appeared. The significance of Computer Security in IOT gadgets is
additionally talked about and different systems for protecting the IOT from
unapproved clients or programmers. The most significant takeaway from this
book is in structure the tasks yourself.
1. INTERFACING DHT11
WITH PIC16F877A FOR
TEMPERATURE ALONG
WITH HUMIDITY
MEASUREMENT
Temperature along with Humidity estimation is frequently valuable in
numerous applications like Home Automation, Environment Monitoring,
Weather station, and so on. The most famously utilized Temperature sensor
close to LM35 is the DHT11, we have recently assembled numerous DHT11
Projects by interfacing it with Arduino, with Raspberry Pi along with
numerous other improvement sheets. Here, we will find how to interface this
DHT11 with PIC16F87A which is a 8-piece PIC Microcontroller. We will
utilize this microcontroller to peruse the estimations of Temperature along
with Humidity utilizing DHT11 and show it on a LCD show. In case you are
totally new with utilizing PIC microcontrollers you can utilize our PIC
instructional exercise arrangement to find out how to program and use PIC
microcontroller, that being stated, we should begin.

DHT11 – Specification and Working

The DHT11 sensor is accessible either in module structure or in sensor


structure. Here we are utilizing the sensor, the major difference between the
both is that in module structure the sensor has a separating capacitor along
with a draw up resistor joined to the yield pin of the sensor. So in case you
are utilizing the module you need not include them remotely. The DHT11 in
sensor structure is demonstrated as follows.
The DHT11 sensor accompanies a blue or white shading packaging. Inside
this packaging, we have two significant parts that help us to detect the
relative mugginess and temperature. The primary part is a couple of cathodes;
the electrical obstruction among these 2 anodes is chosen by a dampness
holding substrate. So the deliberate obstruction is contrarily corresponding to
the overall dampness of nature. Higher the relative moistness lower will be
the estimation of opposition and the other way around. Likewise, note that
Relative mugginess is not similar as real dampness. Relative stickiness
gauges the water amount observable all around comparative with the
temperature observable all around.
The other part is a surface mounted NTC Thermistor. The term NTC
represents the Negative temperature coefficient, for the expansion in
temperature the estimation of obstruction will diminish. The yield of the
sensor is plant adjusted and henceforth as a developer we need not stress over
aligning the sensor. The yield of the sensor given by 1-Wire correspondence,
we should see the pin and association graph of this sensor.
The item is in a 4pin single column bundle. first pin is associated over the
VDD and the fourth pin is associated over the GND. The second pin is the
information pin, utilized for correspondence purposes. This information pin
needs a draw up resistor of 5k. In any case, others pull up resistors, for
example, 4.7k to the 10k can likewise be utilized. The third pin isn't
combined with anything. So it is overlooked.
The datasheet gives specialized determinations just as interfacing data that
can be found in the underneath table-

The above table is indicating Temperature and Humidity estimation range


and exactness. It can quantify temperature from 0-50 degrees Celsius with a
precision of +/ - 2-degree Celsius and relative stickiness from 20-90%RH
with an exactness of +/ - 5%RH. The detail determination can be found in the
underneath table.

Speaking with DHT11 Sensor

As referenced before, so as to peruse the information from DHT11 with PIC


we need to utilize PIC one wire Communication convention. The subtleties
on the best way to play out this can be comprehended from the interfacing
outline of DHT 11 which can be found in its datasheet, the equivalent is
given underneath.
DHT11 needs a beginning sign from the MCU to begin the correspondence.
Thusly, every time the MCU requires to impart a beginning sign to the
DHT11 Sensor to demand it to send the estimations of temperature and
mugginess. In the wake of finishing the beginning sign, the DHT11 imparts a
reaction sign which incorporates the temperature and mugginess data. The
information correspondence is finished by the single transport information
correspondence convention. The full information length is 40bit and the
sensor sends higher information bit first.

Because of the draw up resistor, the information line consistently stays at the
VCC level during inert mode. The MCU requires to pull down this voltage
high to low for a base range of 18ms. During this time, the DHT11 sensor
recognizes the beginning sign and the microcontroller makes the information
line high for 20-40us. This 20-40us time is known as a holding up period
where the DHT11 starts to the reaction. After this holding up period, DHT11
sends the information to the microcontroller unit.

DHT11 Sensor DATA Format

The information comprises of decimal and fundamental parts joined together.


The sensor follows the underneath information group –

8bit integral RH data + 8bit decimal RH data + 8bit integral T data +


8bit decimal T data + 8bit checksum.

One can confirm the information by checking the checksum esteem with the
got information. This should be possible in light of the fact that, on the off
chance that everything is legitimate and in the event that the sensor has
transmitted appropriate information, at that point the checksum ought to be
the entirety of "8bit basic RH data+8bit decimal RHdata+8bit essential T
data+8bit decimal T information".

Required segments

For this venture, underneath things are required -


PIC microcontroller (8bit) programming arrangement.

Breadboard

5V 500mA force flexibly unit.

4.7k resistor 2pcs

1k resistor

PIC16F877A

20mHz precious stone


33pF capacitor 2 pcs

DHT11 sensor

16x2 character Liquid Crystal Display

Jumper wires

Schematic

The circuit outline for interfacing DHT11 with PIC16F877A is demonstrated


as follows.

We have utilized a 16x2 LCD to show the temperature along with mugginess
esteems that we measure from DHT11. The LCD is interfaced in 4-wire
mode and both the sensor and LCD are controlled by a 5V outer force
flexibly. I have utilized a breadboard to make all the necessary associations
and have utilized an outer 5V connector. You can likewise utilize this
breadboard power flexibly board to manage your board with 5V.
When the circuit is prepared, we should simply transfer the code given at the
base of this page and we can begin perusing the Temperature and Humidity
like demonstrated as follows. In case you require to know how the code was
composed and how it functions read further.

DHT11 with PIC MPLABX Code clarification


The code was composed utilizing MPLABX IDE and incorporated utilizing
the XC8 compiler the two of which gave by Microchip itself and is allowed
to install along with use. It would be ideal if you allude to the fundamental
instructional exercises to comprehend the nuts along with bolts of
programming, just the three significant capacities which are required for
speaking with the DHT11 sensor is talked about beneath. The capacities are -

void dht11_init();

void find_response();

char read_dht11();

The main capacity is utilized for the beginning sign with dht11. As examined
previously, every correspondence with DHT11 begins with a beginning sign,
here the pin course is changed from the start to arrange the information pin as
yield from the microcontroller. At that point the information line is pulled
low and continues sitting tight for the 18mS. After that again the line is made
high by the microcontroller and keeps sitting tight for up to 30us. After that
holding up time, the information pin set as contribution to the microcontroller
to get the information.

void dht11_init(){

DHT11_Data_Pin_Direction= 0; //Configure RD0 as output

DHT11_Data_Pin = 0; //RD0 sends 0 to the sensor

__delay_ms(18);

DHT11_Data_Pin = 1; //RD0 sends 1 to the sensor

__delay_us(30);
DHT11_Data_Pin_Direction = 1; //Configure RD0 as input

The following capacity is utilized for setting up a check bit relying upon the
information pin status. It is utilized to distinguish the reaction from DHT11
sensor.

void find_response(){

Check_bit = 0;

__delay_us(40);

if (DHT11_Data_Pin == 0){

__delay_us(80);

if (DHT11_Data_Pin == 1){

Check_bit = 1;

__delay_us(50);}

At last the dht11 read work; here the information is added something extra to
a 8-piece design where the information is returned utilizing bit move activity
relying upon the information pin status.

char read_dht11(){
char data, for_count;

for(for_count = 0; for_count < 8; for_count++){

while(!DHT11_Data_Pin);

__delay_us(30);

if(DHT11_Data_Pin == 0){

data&= ~(1<<(7 - for_count)); //Clear bit (7-b)

else{

data|= (1 << (7 - for_count)); //Set bit (7-b)

while(DHT11_Data_Pin);

return data;

From that point forward, everything is done into the principle work. To start
with, the framework introduction is done where the Liquid Crystal Display is
instated and the LCD pins port bearing is set to the yield. The application is
running inside the fundamental capacity

void main() {
system_init();

while(1){

__delay_ms(800);

dht11_init();

find_response();

if(Check_bit == 1){

RH_byte_1 = read_dht11();

RH_byte_2 = read_dht11();

Temp_byte_1 = read_dht11();

Temp_byte_2 = read_dht11();

Summation = read_dht11();

if(Summation ==
((RH_byte_1+RH_byte_2+Temp_byte_1+Temp_byte_2) & 0XFF)){

Humidity = Temp_byte_1;

RH = RH_byte_1;

lcd_com (0x80);

lcd_puts("Temp: ");

//lcd_puts(" ");
lcd_data(48 + ((Humidity / 10) % 10));

lcd_data(48 + (Humidity % 10));

lcd_data(0xDF);

lcd_puts("C ");

lcd_com (0xC0);

lcd_puts("Humidity: ");

//lcd_puts(" ");

lcd_data(48 + ((RH / 10) % 10));

lcd_data(48 + (RH % 10));

lcd_puts("% ");

else{

lcd_puts("Checksum error");

else {

clear_screen();

lcd_com (0x80);
lcd_puts("Error!!!");

lcd_com (0xC0);

lcd_puts("No Response.");

__delay_ms(1000);

The correspondence with the DHT11 sensor is done inside the while circle
where the beginning sign is submitted to the sensor. From that point onward,
the find_response work is activated. In case the Check_bit is 1, in this point
the further correspondence is conveyed in case the LCD will show mistake
exchange.
Contingent upon the 40bit information, the read_dht11 is called multiple
times (multiple times x 8bit) and put away the information according to the
information design gave in the datasheet. The checksum status is additionally
checked and if blunders are discovered, it will likewise inform in the LCD.
At last, the information is changed over and transmitted to the 16x2 character
Liquid Crystal Display.
Complete code for this PIC Temperature along with Humidity estimation can
be downloaded from here.
Expectation you comprehended the task and delighted in building something
valuable.

Code
#include <xc.h>
#include <stdint.h>
#include "supporing_cfile/lcd.h"
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT
disabled)
#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT
enabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR
enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit
Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be
used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection
bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable
bits (Write protection off; all program memory may be written to by EECON
control)
#pragma config CP = OFF // Flash Program Memory Code Protection
bit (Code protection off)
/*
Program Flow related definition
*/
#define DHT11_Data_Pin PORTDbits.RD5
#define DHT11_Data_Pin_Direction TRISDbits.TRISD5
#define FIRST_LINE 0x80
#define SECOND_LINE 0xC0
#define _XTAL_FREQ 20000000 //20 Mhz
unsigned char Check_bit, Temp_byte_1, Temp_byte_2, RH_byte_1,
RH_byte_2;
unsigned char Himudity, RH, Sumation ;
//Dht11 related definition
void dht11_init();
void find_response();
char read_dht11();
// System related definitions
void system_init(void);
void introduction_screen(void);
void clear_screen(void);
void main() {
system_init();

while(1){
__delay_ms(800);
dht11_init();
find_response();
if(Check_bit == 1){
RH_byte_1 = read_dht11();
RH_byte_2 = read_dht11();
Temp_byte_1 = read_dht11();
Temp_byte_2 = read_dht11();
Sumation = read_dht11();
if(Sumation ==
((RH_byte_1+RH_byte_2+Temp_byte_1+Temp_byte_2) & 0XFF)){
Himudity = Temp_byte_1;
RH = RH_byte_1;
lcd_com (0x80);
lcd_puts("Temp: ");
//lcd_puts(" ");
lcd_data(48 + ((Himudity / 10) % 10));
lcd_data(48 + (Himudity % 10));
lcd_data(0xDF);
lcd_puts("C ");
lcd_com (0xC0);
lcd_puts("Humidity: ");
//lcd_puts(" ");
lcd_data(48 + ((RH / 10) % 10));
lcd_data(48 + (RH % 10));
lcd_puts("% ");
}
else{
lcd_puts("Check sum error");
}
}
else {
clear_screen();
lcd_com (0x80);
lcd_puts("Error!!!");
lcd_com (0xC0);
lcd_puts("No Response.");
}
__delay_ms(1000);
}
}
/*
* This will initialize the dht22 sensor.
*/
void dht11_init(){
DHT11_Data_Pin_Direction= 0; //Configure RD0 as output
DHT11_Data_Pin = 0; //RD0 sends 0 to the sensor
__delay_ms(18);
DHT11_Data_Pin = 1; //RD0 sends 1 to the sensor
__delay_us(30);
DHT11_Data_Pin_Direction = 1; //Configure RD0 as input
}
/*
* This will find the dht22 sensor is working or not.
*/
void find_response(){
Check_bit = 0;
__delay_us(40);
if (DHT11_Data_Pin == 0){
__delay_us(80);
if (DHT11_Data_Pin == 1){
Check_bit = 1;
}
__delay_us(50);}
}

/*
This Function is for read dht22.
*/

char read_dht11(){
char data, for_count;
for(for_count = 0; for_count < 8; for_count++){
while(!DHT11_Data_Pin);
__delay_us(30);
if(DHT11_Data_Pin == 0){
data&= ~(1<<(7 - for_count)); //Clear bit (7-b)
}
else{
data|= (1 << (7 - for_count)); //Set bit (7-b)
while(DHT11_Data_Pin);
} //Wait until PORTD.F0 goes LOW
}
return data;
}

void system_init(){
TRISB = 0; // LCD pins set to out.
lcd_init();
introduction_screen();
//dht11_init();
}

/*
This Function is for Clear screen without command.
*/
void clear_screen(void){
lcd_com(FIRST_LINE);
lcd_puts(" ");
lcd_com(SECOND_LINE);
lcd_puts(" ");
}

/*
This Function is for playing introduction.
*/
void introduction_screen(void){
lcd_com(FIRST_LINE);
lcd_puts("Welcome to");
lcd_com(SECOND_LINE);
lcd_puts("Hello world");
__delay_ms(1000);
__delay_ms(1000);
clear_screen();
lcd_com(FIRST_LINE);
lcd_puts("DHT11 Sensor");
lcd_com(SECOND_LINE);
lcd_puts("with PIC16F877A");
__delay_ms(1000);
__delay_ms(1000);
}

◆ ◆ ◆
2. DAC MCP4921
INTERFACING WITH PIC
MICROCONTROLLER
PIC16F877A
Advanced along with Analog is a basic piece of Electronics. The majority of
the gadgets have both ADC just as DAC and they are utilized when there is a
need of changing over signs either from simple to advanced or computerized
to simple. Likewise this present reality signals like sound and light are simple
in the nature, so at whatever point these true signals must be utilized, the
computerized signals must be changed over to simple, for instance to deliver
sound utilizing Speakers or to control a light source.
Another sort of DAC is a Pulse Width Modulator. A PWM takes a
computerized word and creates an advanced heartbeat with variable heartbeat
width. At the point when this sign is gone through a channel, the outcome
will be simply simple. A simple sign can have numerous sorts of information
in a sign.
In this instructional exercise, we will interface DAC MCP4921 with
Microchip PIC16F877A for advanced to simple change.
Here in this instructional exercise we will change over the advanced sign into
a simple sign and show the information computerized worth and yield simple
incentive on 16x2 LCD. It will give 1V, 2V, 3V, 4V, and 5V as the last
simple yield .You can additionally find out about DAC in our valuable
instructional exercise of DAC interfacing with Raspberry Pi, Arduino and
STM32 sheets.
DAC can be utilized in numerous applications, for example, Motor control,
Control Brightness of the LED Lights, Audio Amplifier, Video Encoders,
Data Acquisition Systems along with etc. Before bouncing legitimately to the
interfacing part, it is critical to have a review about MCP4921.

MCP4921 DAC (Digital to Analog Converter)

MCP4921 is a 12 piece DAC, so MCP4921 will give 12 bits of yield goals.


DAC goals implies number of advanced bits that can be changed over into
simple sign. What number of qualities we can accomplish from this depends
on the recipe . For 12-piece, it is = 4096. This implies 12-piece goals DAC
could create 4096 unique yields.
By utilizing this worth, one can without much of a stretch compute the single
simple advance voltage. For ascertaining the means, the reference voltage is
required. As the rationale voltage for the gadget is 5V, the progression
voltage is 5/4095 (4096-1 on the grounds that the beginning stage for
computerized isn't 1, it is 0), which is 0.00122100122 millivolt. Along these
lines, a difference in 1 piece will change the simple yield with
0.00122100122.
Along these lines, that was the transformation part. The MCP4921 is a 8-pin
IC. The pin outline and the portrayal can be found underneath.
The MCP4921 IC speaks with the microcontroller by the SPI convention. For
SPI correspondence, a gadget must be ace, which submits information or
order to the outer gadget combined as a slave. In SPI correspondence
framework, numerous slave gadgets can be combined with the single Master
Device.
To present the information and the order, it is essential to comprehend the
order register.
In the beneath picture, the order register is appeared,
The order register is a 16-piece register. The bit-15 to bit-12 is utilized for the
design order. The information input and the design is obviously appeared in
the above picture. In this venture, the MCP4921 will be utilized as the
accompanying design

Bit Configuration Configuration


Number Value

Bit 15 DACA 0

Bit 14 Unbuffered 0
Bit 13 1x(VOUT*D/4096) 1

Output Power Down Control


Bit 12 1
Bit

So the Binary is 0011 alongside the information which is controlled by the


D11 to D0 bits of the register. The 16-piece information 0011 xxxx should be
submitted where the initial 4 piece of MSB is the design and the rest is the
LSB. It will be more clear by observing the compose order timing outline.

In accordance with the planning chart and the datasheet, the CS pin is low for
the whole order composing period to the MCP4921.
Presently it is the opportunity to interface the gadget with the equipment and
composing the codes.

Segments Required

For this venture, the accompanying parts are required-

MCP4921
PIC16F877A

20 MHz Crystal

A Display 16x2 character LCD.

2k resistor - 1 pc

33pF capacitors - 2 pcs

4.7k resistor - 1 pc

A multi-meter to quantify the yield voltage

A breadboard

5V power flexibly, A telephone charger can work.

Loads of hookup wires or berg wires.

Microchip programming condition with Programmer pack and


IDE with compiler

Schematic

Circuit Diagram for interfacing DAC4921 with PIC Microcontroller is given


beneath:
The circuit is developed in Breadboard-
Code Explanation

Complete code for changing over Digital signs into simple with PIC16F877A
is given toward the finish of article. As usual, we 1st required to set the
design bits in the PIC microcontroller.

// PIC16F877A Configuration Bit Settings

// 'C' source line config statements

// CONFIG

#pragma config FOSC = HS // Oscillator Selection bits (HS


oscillator)

#pragma config WDTE = OFF // Watchdog Timer Enable bit


(WDT disabled)

#pragma config PWRTE = OFF // Power-up Timer Enable bit


(PWRT disabled)

#pragma config BOREN = ON // Brown-out Reset Enable bit


(BOR enabled)

#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-


Circuit Serial Programming Enable bit (RB3/PGM pin has PGM
function; low-voltage programming enabled)

#pragma config CPD = OFF // Data EEPROM Memory Code


Protection bit (Data EEPROM code protection off)

#pragma config WRT = OFF // Flash Program Memory Write


Enable bits (Write protection off; all program memory may be
written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code
Protection bit (Code protection off)

The underneath code lines are utilized for coordinating LCD and SPI header
documents, additionally the XTAL Frequency and the DAC's CS pin
association is pronounced.
The PIC SPI instructional exercise and library can be found at the given
connection.

#include <xc.h>

#include <stdint.h>

#include "supporing_cfile\lcd.h"

#include "supporing_cfile\PIC16F877a_SPI.h"

/*

Hardware related definition

*/

#define _XTAL_FREQ 200000000 //Crystal Frequency, used in delay

#define DAC_CS PORTCbits.RC0 //Declaring DAC CS pin

Funciton the SPI_Initialize_Master() is marginally altered for an alternate


setup required for this undertaking. For this situation, the SSPSTAT register
is arranged such a way, that the information examined at end of information
yield time and the likewise the SPI clock designed as Transmit happens on
the change from dynamic to sit clock state mode. Other is the equivalent.
void SPI_Initialize_Master()

TRISC5 = 0; // Set as output

SSPSTAT = 0b11000000; //pg 74/234

SSPCON = 0b00100000; //pg 75/234

TRISC3 = 0; //Set as output for slave mode

Additionally, for the beneath work, the SPI_Write() is changed somewhat.


Information transmission will happen after the cradle is cleared for
guaranteeing impeccable information transmission over SPI.

void SPI_Write(char incoming)

SSPBUF = incoming; //Write the user given data into


buffer

while (!SSPSTATbits.BF);

The significant piece of the program is the MCP4921 driver. It is somewhat


dubious part as the order and computerized information is punched together
to give total 16-piece information over the SPI. Nonetheless, that rationale is
unmistakably appeared in the code remarks.
/*

This Function is for converting the digital value to the analog.

*/

void convert_DAC(unsigned int value)

/*Step Size = 2^n, Therefore 12bit 2^12 = 4096

For 5V reference, the step will be 5/4095 = 0.0012210012210012V


or 1mV (approx)*/

unsigned int container ;

unsigned int MSB;

unsigned int LSB;

/*Step: 1, stored the 12 bit data into the container

Suppose the data is 4095, in binary 1111 1111 1111*/

container = value;

/*Step: 2 Creating Dummy 8 bit. So, by dividing 256, upper 4 bits


are captured in LSB

LSB = 0000 1111*/

LSB = container/256;

/*Step: 3 Sending the configuration with punching the 4 bit data.


LSB = 0011 0000 OR 0000 1111. Result is 0011 1111 */

LSB = (0x30) | LSB;

/*Step:4 Container still has the 21bit value. Extracting the lower 8
bits.

1111 1111 AND 1111 1111 1111. Result is 1111 1111 which is
MSB*/

MSB = 0xFF & container;

/*Step:4 Sending the 16bits data by dividing into two bytes. */

DAC_CS = 0; // CS is low during data transmission. As per the


data-sheet it is required

SPI_Write(LSB);

SPI_Write(MSB);

DAC_CS = 1;

In the principle work, a 'for circle' is utilized where the computerized


information for making the yield of 1V, 2V, 3V, 4V, and 5V is made. The
advanced worth is determined against the Output
voltage/0.0012210012210012 millivolt.

void main() {

system_init();
introduction_screen();

int number=0;

int volt=0;

while (1) {

for (volt=1; volt<=MAX_VOLT; volt++){

number = volt / 0.0012210012210012;

clear_screen();

lcd_com(FIRST_LINE);

lcd_puts("DATA Sent:- ");

lcd_print_number(number);

lcd_com(SECOND_LINE);

lcd_puts("Output:- ");

lcd_print_number(volt);

lcd_puts("V");

convert_DAC(number);

__delay_ms(300);

}
}

Testing the Digital to Analog Conversion utilizing PIC

The fabricated circuit is tried utilizing Multi-meter. In beneath pictures, the


yield voltage and the advanced information is appeared on the Liquid Crystal
Display. The Multi-meter is indicating close reading.

Complete Code is joined beneath.


Code
/*
* File: main.c
* Project On: mcp4921 interfacing
*/
// PIC16F877A Configuration Bit Settings
// 'C' source line config statements
// CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT
disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT
disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR
enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit
Serial Programming Enable bit (RB3/PGM pin has PGM function; low-
voltage programming enabled)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection
bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable
bits (Write protection off; all program memory may be written to by EECON
control)
#pragma config CP = OFF // Flash Program Memory Code Protection
bit (Code protection off)
#include <xc.h>
#include <stdint.h>
#include "supporing_cfile\lcd.h"
#include "supporing_cfile\PIC16F877a_SPI.h"
/*
Hardware related definition
*/
#define _XTAL_FREQ 200000000 //Crystal Frequency, used in delay
#define DAC_CS PORTCbits.RC0 //Declaring DAC CS pin
/*
Program Flow related definition
*/
#define MAX_VOLT 5
#define FIRST_LINE 0x80
#define SECOND_LINE 0xC0
/*
Other Specific function definition
*/
void system_init(void);
void sw_delayms(unsigned int d);
void convert_DAC(unsigned int digital_value);
void clear_screen(void);
void introduction_screen(void);
void main() {
system_init();
introduction_screen();
int number=0;
int volt=0;
while (1) {
for (volt=1; volt<=MAX_VOLT; volt++){
number = volt / 0.0012210012210012;
clear_screen();
lcd_com(FIRST_LINE);
lcd_puts("DATA Sent:- ");
lcd_print_number(number);
lcd_com(SECOND_LINE);
lcd_puts("Output:- ");
lcd_print_number(volt);
lcd_puts("V");
convert_DAC(number);
__delay_ms(300);
}
}
}
/*
This Function is for software delay.
*/
void sw_delayms(unsigned int d){
int x, y;
for(x=0;x<d;x++)
for(y=0;y<=1275;y++);
}
/*
This Function is for system initializations.
*/
void system_init(void){
TRISB = 0x00; // LCD pin as output
TRISCbits.TRISC0=0; // CS pin declared as output
lcd_init(); // This will initialize the lcd
SPI_Initialize_Master();
}
/*
This Function is for Clear screen without command.
*/
void clear_screen(void){
lcd_com(FIRST_LINE);
lcd_puts(" ");
lcd_com(SECOND_LINE);
lcd_puts(" ");
}
/*
This Function is for playing introduction.
*/
void introduction_screen(void){
lcd_com(FIRST_LINE);
lcd_puts("Welcome to");
lcd_com(SECOND_LINE);
lcd_puts("Hello world");
__delay_ms(500);
clear_screen();
lcd_com(FIRST_LINE);
lcd_puts("mcp4921 with");
lcd_com(SECOND_LINE);
lcd_puts("PIC16F877A");
__delay_ms(350);
}
/*
This Function is for converting the digital value to the analog.
*/
void convert_DAC(unsigned int value)
{
/*Step Size = 2^n, Therefore 12bit 2^12 = 4096
For 5V reference, the step will be 5/4095 = 0.0012210012210012V or
1mV (approx)*/
unsigned int container ;
unsigned int MSB;
unsigned int LSB;
/*Step: 1, stored the 12 bit data into the container
Suppose the data is 4095, in binary 1111 1111 1111*/
container = value;
/*Step: 2 Creating Dummy 8 bit. So, by dividing 256, upper 4 bits are
captured in LSB
LSB = 0000 1111*/
LSB = container/256;
/*Step: 3 Sending the configuration with punching the 4 bit data.
LSB = 0011 0000 OR 0000 1111. Result is 0011 1111 */
LSB = (0x30) | LSB;
/*Step:4 Container still has the 21bit value. Extracting the lower 8 bits.
1111 1111 AND 1111 1111 1111. Result is 1111 1111 which is MSB*/
MSB = 0xFF & container;
/*Step:4 Sending the 16bits data by dividing into two bytes. */
DAC_CS = 0; // CS is low during data transmission. As per the data-
sheet it is required
SPI_Write(LSB);
SPI_Write(MSB);
DAC_CS = 1;
}
◆ ◆ ◆
3. MECHANICAL ARM
CONTROL UTILIZING PIC
MICROCONTROLLER
From the sequential construction system of vehicle producing enterprises to
the telesurgery robots in space, Robotic Arms are to be found all over the
place. The instruments of these robots are like a human which can be
customized for comparable capacity and expanded abilities. They can be used
to perform rehashed activities quicker and precise than people or can be used
in unforgiving situations without gambling human life. We have just
manufactured a Record and Play Robotic Arm utilizing Arduino which could
be prepared to do a specific errand and made to rehash until the end of time.
In this instructional exercise we will utilize the business standard
PIC16F877A 8-piece Microcontroller to control the equivalent automated
arm with potentiometers. The test with this undertaking is that PIC16F877A
has just two PWN able pins, however we have to control around 5 servo
engines for our robot which requires 5 individual PWM pins. So we require
to use the GPIO sticks and create PWM flags on PIC GPIO pins utilizing the
clock intrudes. Presently, obviously we could move up to a superior
microcontroller or utilize a de-multiplexer IC to make things significantly
simpler here. Yet at the mean time, it merits checking out this venture for the
learning experience.
The mechanical structure of the automated arm that I am utilizing in this task
was totally 3D printed for my past undertaking; you can locate the total plan
documents and gathering methodology here. Then again, in case you don't
have a 3D printer you can likewise assemble a straightforward Robotic Arm
utilizing cardboards as show in the connection. Expecting that you have by
one way or another got hold of your mechanical Arm lets continue into the
undertaking.

Schematic Diagram

The Complete circuit outline for this PIC Microcontroller based Robotic Arm
is demonstrated as follows. The schematics was drawn utilizing EasyEDA.
The circuit outline is entirely straightforward; the total task is controlled by
the 12V connector. This 12V is then changed over to +5V utilizing two 7805
Voltage controllers. One is named as +5V along with the other is named as
+5V(2). The purpose behind having two controllers is that when the servo
pivots it pulls in a ton of current which makes a voltage drop. This voltage
drop powers the PIC to restart itself, henceforth we can't work both the PIC
along with the servo engines on the equivalent +5V rail. So the one named as
+5V is utilized to control the PIC Microcontroller, LCD and Potentiometers
and a different controller yield which is marked as +5V(2) is utilized to
manage the servo engines.
The five yield pins of the potentiometers which give a variable voltage from
0V to 5V are associated with the simple pins An0 to AN4 of the PIC. Since
we are wanting to utilize clocks to create PWM the servo engines can be
associated with any General Purpose Input/Output pin. I have chosen pins
structure RD2 to RD6 for the servo engines, yet it tends to be any GPIO of
your decision.
Since the program includes a great deal of investigating, a 16x2 LCD show is
additionally interfaced to portB of the PIC. This will show the obligation
pattern of the servo engines that are being controlled. Aside from this I have
likewise expanded associations for all GPIO and simple pins, to be safe if any
sensors should be interfaced in future. At last I have additionally associated
the software engineer pin H1 to straightforwardly program the PIC with
pickit3 utilizing the ICSP programming alternative.

Producing PWM flags on GPIO pin for Servo Motor Control

When the circuit is prepared we require to do sense of how to produce PWN


flags on the GPIO pin of PIC to control the servo engine. We have just tired
something comparative utilizing the Timer intrude on strategy and were
effective. Here we are simply going to expand on it, so on the off chance that
you are new here, I would emphatically prescribe you to peruse this past
instructional exercise before continuing further.
All leisure activity servo engines work with a recurrence of 50Hz. Which
means one complete heartbeat cycle for a servo engine will be 1/50 (F=1/T)
which is 20ms. Of this total 20ms the manage signal is just from 0 to 2ms
while the remainder of the sign is constantly off. The underneath figure
shows how the ON time fluctuates just from 0 to 2ms to turn the engine from
0 degree to 180 level of the complete 20ms length.
Considering this we need to compose the program so that the PIC peruses in
0 to1204 from the potentiometer and maps it to 0 to 100 which will be the
obligation pattern of the servo engine. Utilizing this obligation cycle we can
compute the ON time of the servo engine. At that point we can instate the
clock hinder to flood at a customary interim with the end goal that it
demonstrations like the millis() work in Arduino. With that, we can flip the
status GPIO pin to be high for an ideal term and turn it off after 20ms (one
complete cycle) and afterward rehash a similar procedure. Presently, that we
have comprehended the rationale let us get into the program.

Programming PIC16F8771A for Robotic Arm

Like consistently the total program can be found toward the finish of this
page, code can likewise be downloaded from here with all the essential
records. In this area we will talk about the rationale behind the program. The
program utilizes the ADC module, Timer Module along with Liquid Crystal
Display Module to manage the Robotic Arm. In case you don't know about
how to utilize the ADC highlights or Timer highlights or to interface a LCD
with PIC, at that point you can fall back to the separate connects to learn
them. The underneath clarification is given accepting that the peruser knows
about these ideas.

Clock 0 Port Configuration

The most important segment in the code is setting the Timer 0 to over stream
for each particular deferral. The formulae to figure this postponement can be
given as

Delay = ((256-REG_val)*(Prescal*4))/Fosc

By utilizing the OPTION_REG and TMR0 register we have set the Timer 0
to work with a prescalar estimation of 32 and the REG val is set to 248. The
gem recurrence (Fosc) utilized in our equipment is 20Mhz. With these
qualities the postponement can be determined as
Delay = ((256-248)*(32*4)) / (20000000)

= 0.0000512 seconds (or)

= 0.05 msec

So now we have set the clock to flood at each 0.05ms. The code to do the
equivalent is given beneath

/*****Port Configuration for Timer ******/

OPTION_REG = 0b00000100; // Timer0 with external freq and 32


as prescalar // Also Enables PULL UPs

TMR0=248; // Load the time value for 0.0001s; delayValue can


be between 0-256 only

TMR0IE=1; //Enable timer interrupt bit in PIE1 register

GIE=1; //Enable Global Interrupt

PEIE=1; //Enable the Peripheral Interrupt

/***********______***********/

Of the absolute 0ms to 2ms control window of the servo engine we can
control it with a goals of 0.05msec, which permits us to have (2/0.05) 40
unique situations for the engine between 0 degree to 180 degree. You can
diminish this worth further if your MCU could bolster it to acquire more
positions and exact control.

Interfere with Service Routine (ISR)


Since we have the Timer 0 set to over stream for each 0.05ms, we will have
the TMR0IF intrude on banner set for 0.05ms. So inside the ISR work we can
reset that banner and augmentation a variable called check by one. So now
this variable will be augmentation by 1 for each 0.05ms.

void interrupt timer_isr()

if(TMR0IF==1) // Timer flag has been triggered due to timer


overflow -> set to overflow for every 0.05ms

TMR0 = 248; //Load the timer Value

TMR0IF=0; // Clear timer interrupt flag

count++; //Count increments by 1 for every 0.05ms

Figuring Duty Cycle and On Time

Next we require to figure the obligation cycle and on schedule for every five
servo engine. We have five servo engines is used to manage singular area of
arm. So we require to peruse the ADC estimation of every five and ascertain
the obligation cycle and on schedule for each.
The ADC worth will be in scope of 0 to 1024 which can be changed over to
0% to 100% obligation cycle by essentially duplicating 0.0976 (100/1024 =
0.0976) to the got esteem. This 0 to 100% obligation cycle must be then
changed over to ON schedule. We realize that at 100% obligation cycle the
ON time must be 2ms (for 180 degree) so increasing 0.02 (2/100 = 0.02) will
change over 0 to 100 obligation cycle to 0 to 2ms. Be that as it may, at that
point our clock variable check is set to increment once for each 0.05ms. This
implies estimation of check will be 20 (1/0.05 = 20) for each 1ms. So we
require to increase 20 with 0.02 to compute the specific on schedule for our
program which will give us the worth 0.4 (0.02*20 = 0.4). The code for the
equivalent is appear underneath, you can view it rehashed for multiple times
for every one of the 5 pot utilizing a for circle. The subsequent qualities are
put away in the T_ON exhibit.

for (int pot_num=0; pot_num<=3; pot_num++)

int Pev_val = T_ON[pot_num];

POT_val = (ADC_Read(pot_num)); //Read the value of POT


using ADC

Duty_cycle = (POT_val * 0.0976); //Map 0 to 1024 to 0 to 100

T_ON[pot_num] = Duty_cycle* 0.4;//20*0.02

Choosing which engine to pivot

We can't control each of the five engines together as it will make the ISR
code overwhelming hindering the whole microcontroller. So we require to
turn just a single servo engine at once. To choose which servo to pivot the
microcontroller screens the ON time of every one of the five servo engines
and contrasts it and it's past on schedule. In the event that there is an
adjustment in the ON schedule, at that point we can reason that the specific
servo must be moved. The code for the equivalent is demonstrated as follows.

if (T_ON[pot_num] != Pev_val)

Lcd_Clear();
servo = pot_num;

Lcd_Set_Cursor(2,11);
Lcd_Print_String("S:");Lcd_Print_Char(servo+'0');

if (pot_num==0)

{Lcd_Set_Cursor(1,1); Lcd_Print_String("A:");}

else if (pot_num==1)

{Lcd_Set_Cursor(1,6); Lcd_Print_String("B:");}

else if (pot_num==2)

{Lcd_Set_Cursor(1,11); Lcd_Print_String("C:");}

else if (pot_num==3)

{Lcd_Set_Cursor(2,1); Lcd_Print_String("D:");}

else if (pot_num==4)

{Lcd_Set_Cursor(2,6); Lcd_Print_String("E:");}

char d2 = (Duty_cycle) %10;

char d1 = (Duty_cycle/10) %10;

Lcd_Print_Char(d1+'0');Lcd_Print_Char(d2+'0');

We additionally print the servo obligation cycle on the Liquid Crystal


Display screen so the client could know about its present position. In light of
the change in ON time the variable servo is refreshed with numbers from 0 to
4 each speaking to singular engines.
Controlling the Servo Motor inside the ISR

Inside the ISR we have the variable tally getting augmented for each 0.05ms,
this implies for each 1ms the variable will be increased by 20. Utilizing this
we require to manage the pins to create PWM signal. In case the estimation
of check is not exactly the on schedule, in this way the GPIO of that engine is
turned on utilizing the underneath line

PORTD = PORTD | servo_code[servo];

Here the exhibit servo_code[] has the pin detail of every five servo engine
and dependent on the incentive in factor servo, the code for that specific
servo engine will be utilized. It is then legitimately OR (|) with existing
PORTD bits so we don't upset the estimations of other engine and update just
this specific engine. Also for killing the pin

PORTD = PORTD & ~(servo_code[servo]);

We have switched the bit esteem utilizing the rationale converse (~)
administrator and afterward have played out an (and) procedure on the
PORTD to kill just the ideal pin while leaving different pins in their past
state. The total code piece is demonstrated as follows.

void interrupt timer_isr()

if(TMR0IF==1) // Timer flag has been triggered due to timer


overflow -> set to overflow for every 0.05ms

TMR0 = 248; //Load the timer Value


TMR0IF=0; // Clear timer interrupt flag

count++; //Count increments by 1 for every 0.05ms -> count


will be 20 for every 1ms (0.05/1 = 20))

int servo_code[] = {0b01000000, 0b00100000, 0b00010000,


0b00001000, 0b00000100 };

if (count >= 20*20)

count=0;

if (count <= (T_ON[servo]) )

PORTD = PORTD | servo_code[servo];

else

PORTD = PORTD & ~(servo_code[servo]);

We realize that the all out cycle needs to keep going for 20ms before the
General Purpose Input/Output pin is turned on once more. So we check if the
tally has surpassed 20ms by contrasting the estimation of tally and 400 (same
computation as talked about above) and if yes we require to instate the tally
to be zero once more.

Recreation of PIC Robotic Arm Code

It is in every case better to recreate the code before taking it to the genuine
equipment. So I utilized Proteus to reenact my code and checked it to work
effectively. The circuit utilized for reproduction is demonstrated as follows,
We have utilized an oscilloscope to check if the PWM signals are being
produced as required. Likewise we can check if the LCD and Servo engines
are turning true to form.

As should be obvious the LCD shows the obligation pattern of engine D to be


07 dependent on the pot esteem which is the third engine. Comparable if
another pot is moved the obligation pattern of that pot and its engine number
will be shown on the LCD. The PWM signal appeared on the oscilloscope is
demonstrated as follows.
The all out cycle time frame is estimated to be 22.2ms utilizing the cursor
choice on the oscilloscope, which is extremely near the ideal 20ms. At last
we are certain that the code works, so to proceed with the circuit we can
either bind it on a perf board or utilize a PCB. It won't work effectively on
breadboard in light of the fact that the POT constantly will in general give a
few issues because of poor associations.

PCB Design utilizing EasyEDA

To plan this PIC Robotic Arm, we have picked the online EDA apparatus
called EasyEDA. I have been utilizing it for quite a while now along with
think that its helpful in light of its immense accessibility of impression and
simple to utilize nature. In the wake of structuring the PCB, we can arrange
the PCB tests by their minimal effort . They additionally offer part sourcing
administration where they have an enormous supply of electronic segments
and clients can arrange their necessary segments alongside the PCB request.
While structuring your circuits and PCBs, you can likewise make your circuit
and PCB plans open with the goal that different clients can duplicate or alter
them and can take profit by your work, we have additionally made our entire
Circuit and PCB designs open for this circuit:

Utilizing this connection you can legitimately arrange the equivalent PCB
that we are utilizing in this task and use it. When the structure is finished the
board can be seen as 3D model which will be particularly useful in imagining
how the board would show up after creation. The 3D model of the board that
we are utilizing is demonstrated as follows. Aside from this you can likewise
see the top and base layer of the board to check if the smooth screen is true to
form.

Figuring and Ordering Samples on the web

In the wake of finishing the structure of this PIC Robot PCB, you can arrange
the PCB through . To arrange the PCB from JLCPCB, you need Gerber File.
To install Gerber records of your PCB simply click the Generate Fabrication
File button on EasyEDA manager page, at that point install the Gerber
document from that point or you can tap on Order at JLCPCB as appeared in
underneath picture. This will divert you to JLCPCB.com, where you can
select the quantity of Printed Circuit Boards you require to arrange, what
number of copper layers you need, the PCB thickness, copper weight, and
even the PCB shading, similar to the depiction demonstrated as follows:

After you have chosen the entirety of the choices, click "Spare to Cart" and
afterward you will be taken to the page where you can transfer your Gerber
File which we have installed from EasyEDA. Transfer your Gerber document
and snap "Spare to Cart". Lastly click on Checkout Securely to end your
request, at that point you will get your PCBs a 2 days after the fact. They are
creating the PCB at exceptionally low rate which is $2. Their fabricate time is
likewise extremely less which is 48 hours with DHL conveyance of 3-5 days,
essentially you will get your PCBs inside seven days of requesting.
In case of requesting the Printed Circuit Board, you can check the Production
Progress of your Printed Circuit Board with date along with time. You check
it by going on Account page and snap on "Creation Progress" .

Following scarcely any long periods of requesting PCB's I got the PCB tests
in pleasant bundling as appeared in underneath pictures.

Also, in the wake of getting these pieces I have fastened all the necessary
parts over the Printed Circuit Board. I additionally legitimately fastened the
POT straightforwardly as opposed to utilizing interfacing wires on the
grounds that the female to female wires that I at first utilized where giving
odd simple yield voltages most likely as a result of free contacts. When all
the segments were amassed my PCB looked something like this.

You may have seen that there is just a single 7805 on this board. That is on
the grounds that at first I figured I could pull off only controller for fueling
both PIC and servo engine and later I understood I need two. So I have
utilized an outside circuit to manage the servo engines across the green wires
you view here.
Considering all you don't need to stress a lot over it since; I have rolled out
the improvements to the PCB now. You can utilize the altered PCB and weld
both the controllers on board itself.

Working of PIC Robotic Arm


After all the tiring work it is the ideal opportunity for pay off. Bind all the
parts on the board and transfer the program to the PIC controller. Complete
Code is given beneath or can be downloaded from here. The programming
connector gave on the board should assist you with transferring the program
straightforwardly utilizing Pickit 3 absent a lot of issue. When the program is
transferred you should view the LCD showing the servo that is presently
being controlled. To become well- known with programming the PIC
Microcontroller, simply follow the past instructional exercise.

z
From that point you can essentially turn the pot and check how the servo
engines react every potentiometer. When you comprehend the configuration
you can control the automated arm to play out whatever activity you need it
to perform and have a fabulous time.
That is it folks trust you comprehended the undertaking and gained some new
useful knowledge from it.

Code
/*
* Program to Control Robotic Arm through POT
* 5 Servo controlled with Timer Register PWM
*/
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT
disabled)
#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT
enabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR
enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit
Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be
used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection
bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable
bits (Write protection off; all program memory may be written to by EECON
control)
#pragma config CP = OFF // Flash Program Memory Code Protection
bit (Code protection off)
#define _XTAL_FREQ 20000000 //Crystak Freq is 20MHz
#define PWM_Frequency 0.05 // in KHz (50Hz)
//Define LCD pins
#define RS RB1
#define EN RB2
#define D4 RB3
#define D5 RB4
#define D6 RB5
#define D7 RB6
#include <xc.h>
#include "lcd.h" //Header for using LCD module
int POT_val; //variable to store value from ADC
int count; //timer variable
//int T_TOTAL = (1/PWM_Frequency); //calculate Total Time from
frequency (in milli sec)) //20msec
int Duty_cycle; //Duty cycle value
int T_ON[4];
char servo;
void ADC_Initialize() //Prepare the ADC module
{
ADCON0 = 0b01000001; //ADC ON and Fosc/16 is selected
ADCON1 = 0b11000000; // Internal reference voltage is selected
}
unsigned int ADC_Read(unsigned char channel) //Read from ADC
{
ADCON0 &= 0x11000101; //Clearing the Channel Selection Bits
ADCON0 |= channel<<3; //Setting the required Bits
__delay_ms(2); //Acquisition time to charge hold capacitor
GO_nDONE = 1; //Initializes A/D Conversion
while(GO_nDONE); //Wait for A/D Conversion to complete
return ((ADRESH<<8)+ADRESL); //Returns Result
}
void interrupt timer_isr()
{
if(TMR0IF==1) // Timer flag has been triggered due to timer overflow ->
set to overflow for every 0.05ms
{
TMR0 = 248; //Load the timer Value
TMR0IF=0; // Clear timer interrupt flag
count++; //Count increments by 1 for every 0.05ms
}

int servo_code[] = {0b01000000, 0b00100000, 0b00010000,


0b00001000, 0b00000100 };

if (count >= 20*20)


count=0;

if (count <= (T_ON[servo]) )


PORTD = PORTD | servo_code[servo];
else
PORTD = PORTD & ~(servo_code[servo]);
}
void main()
{
/*****Port Configuration for Timer ******/
OPTION_REG = 0b00000100; // Timer0 with external freq and 32 as
prescalar // Also Enables PULL UPs
TMR0=248; // Load the time value for 0.0001s; delayValue can be
between 0-256 only
TMR0IE=1; //Enable timer interrupt bit in PIE1 register
GIE=1; //Enable Global Interrupt
PEIE=1; //Enable the Peripheral Interrupt
/***********______***********/

/*****Port Configuration for I/O ******/


TRISB = 0x00; //PORT B is output since LCd is connected
PORTB=0x00; //Initialize all pins to 0
TRISD = 0x00; //PORT D is output since servo is connected
PORTD=0x00; //Initialize all pins to 0
/***********______***********/

Lcd_Start(); //Initialize LCD module


ADC_Initialize(); //Initialize ADC module
// Lcd_Clear();
// Lcd_Set_Cursor(1,1);
//Lcd_Print_String("Helloworld");
//Lcd_Set_Cursor(2,1);
//Lcd_Print_String("WORKING!!");
//__delay_ms(500);

while(1)
{
for (int pot_num=0; pot_num<=3; pot_num++)
{
int Pev_val = T_ON[pot_num];

POT_val = (ADC_Read(pot_num)); //Read the value of POT using


ADC
Duty_cycle = (POT_val * 0.0976); //Map 0 to 1024 to 0 to 100
T_ON[pot_num] = Duty_cycle* 0.4;//((Duty_cycle * T_TOTAL) /
1000)*10; //Calculate On Time from 0ms to 2ms for 0-100 Duty Cycle //*10
is multiplication factor

if (T_ON[pot_num] != Pev_val)
{
Lcd_Clear();
servo = pot_num;
Lcd_Set_Cursor(2,11);
Lcd_Print_String("S:");Lcd_Print_Char(servo+'0');

if (pot_num==0)
{Lcd_Set_Cursor(1,1); Lcd_Print_String("A:");}
else if (pot_num==1)
{Lcd_Set_Cursor(1,6); Lcd_Print_String("B:");}
else if (pot_num==2)
{Lcd_Set_Cursor(1,11); Lcd_Print_String("C:");}
else if (pot_num==3)
{Lcd_Set_Cursor(2,1); Lcd_Print_String("D:");}
else if (pot_num==4)
{Lcd_Set_Cursor(2,6); Lcd_Print_String("E:");}

char d2 = (Duty_cycle) %10;


char d1 = (Duty_cycle/10) %10;
Lcd_Print_Char(d1+'0');Lcd_Print_Char(d2+'0');

}
}

◆ ◆ ◆
4. ROTATING ENCODER
INTERFACING WITH PIC
MICROCONTROLLER
A Rotary encoder is an information gadget which encourages the client to
collaborate with a framework. It looks progressively like a Radio
potentiometer however it yields a train of heartbeats which makes its
application one of a kind. At the point when the handle of the Encoder is
pivoted it turns in type of little advances which encourages it to be utilized
for stepper/Servo engine controlling, exploring through a grouping of the
menu and Increasing/diminishing the estimation of a number and
considerably more.
Here, we will find out about the various kinds of Rotary Encoders along with
how it functions. We will likewise interface it with PIC Microcontroller
PIC16F877A and control the estimation of a whole number by turning the
Encoder and show its incentive on a 16*2 LCD screen. Toward the finish of
this instructional exercise, you will be alright with utilizing a Rotary Encoder
for your tasks. So how about we begin...

Rotating Encoder and its Types

Rotating encoder frequently called a pole encoder. It is an electromechanical


transducer, which means it changes over mechanical developments into
electronic heartbeats or as it were it changes over precise position or
movement or shaft position to a computerized or simple sign. It comprises of
a handle which when pivots will move bit by bit and produce a grouping of
heartbeat trains with pre-characterized width for each progression.
There are numerous kinds of revolving encoder in the market the planner can
pick one as indicated by his application. The most well-known sorts are
recorded beneath

Gradual Encoder

Total Encoder

Attractive Encoder

Optical Encoder

Laser Encoder

These encoders are arranged dependent on the Output sign and detecting
innovation, the Incremental Encoder and Absolute Encoders are ordered
dependent on Output signal and the Magnetic, Optical and Laser Encoder are
characterized dependent on Sensing Technology. The Encoder utilized here is
an Incremental sort Encoder.
Total encoder stores the position data considerably after the force is
evacuated, and the position data will be accessible when we again apply
capacity to it.
The other fundamental sort, Incremental encoder gives information when the
encoder change its the position. It couldn't store the position data.

KY-040 Rotary Encoder Pinout and portrayal

The pinouts of the KY-040 Incremental sort turning encoder is demonstrated


as follows. In this task, we will interface this Rotary Encoder with the
mainstream microcontroller PIC16F877A from microchip.
The initial two pins (Ground and Vcc) is utilized to control the Encoder,
normally +5V flexibly is utilized. Aside from turning the handle in clock
savvy and against clockwise course, the encoder likewise has a switch
(Active low) which can be squeezed by squeezing the handle inside. The sign
from this switch is gotten through the pin 3 (SW). At long last it has the two
yield pins (DT and CLK) which produce the waveforms as of now talked
about underneath. We have interfaced this Rotary Encoder already with
Arduino.

How Rotary Encoder Works

The yield completely relies upon the inside copper cushions which furnish
the association with GND and VCC with the pole.
There are 2 pieces of the Rotary Encoder. Shaft Wheel which is associated
with the pole and pivots clockwise or hostile to clockwise contingent upon
the turn of the pole, and the base where the electrical association is finished.
The base has ports or focuses which is associated with DT or CLK so that
when the pole wheel pivots, it will interface the base focuses and give square
wave on both DT and CLK port.
The yield will resemble when the pole pivots

Two ports give the square wave yet there is slight contrast in the planning.
Because of this, in the event that we acknowledge the yield as 1 and 0, there
can be just four state, 0, 1 0, 1, 0 1. The arrangement of the parallel yield
decides the clockwise turn or against clockwise turn. Like, for instance, if the
Rotary Encoder gives 1 0 out of gear condition and give 1 from that point
forward, that implies the encoder change it's position a solitary advance to the
clockwise heading, however in the event that it is giving 0 after the inactive 1
0, implies the pole is changin its situations in against clockwise course with
one stage.

Segments Required

It is an ideal opportunity to recognize what we have to interface Rotary


Encoder with PIC Microcontroller,

PIC16F877A

4.7k resistor

1k resistor

10k pot

33pF artistic circle capacitor – 2pcs

20Mhz precious stone

16x2 Display

Rotational Encoder

5V connector.

Bread Board

Hookup wires.

PIC16F877A Rotary Encoder Interfacing Circuit Diagram


The following is the image of conclusive arrangement subsequent to
associating the parts as per Circuit Diagram:
We have utilized a solitary 1K resistor for the differentiation of the LCD as
opposed to utilizing a potentiometer.
Code Explanation

we are clarifying a couple of significant pieces of the code. On the off chance
that you are new with PIC Microcontroller, at that point follow our PIC
instructional exercises from the earliest starting point.
As we talked about previously, we have to check the yield and separate the
double yield for both DT and CLK, so we made an if-else part for the
activity.

if (Encoder_CLK != position){

if (Encoder_DT != position){
// lcd_com (0x01);

counter++; // Increase the counter which will be printed


on the lcd

lcd_com (0xC0);

lcd_puts(" ");

lcd_com (0xC0);

lcd_bcd(1,counter);

else{

// lcd_com (0x01);

lcd_com (0xC0);

counter--; // decrease the counter

lcd_puts(" ");

lcd_com (0xC0);

lcd_bcd(1,counter);

//lcd_puts("Left");

}
We additionally need to store the situation on each progression. To do this,
we utilized a variable "position" which stores the present position.

position = Encoder_CLK; // It is to store the encoder clock position on


the variable. Can be 0 or 1.

Other than this an alternative is given to advise about switch push on the
LCD.

if (Encoder_SW == 0){

sw_delayms(20); //debounce delay

if (Encoder_SW == 0){

//lcd_com(1);

//lcd_com(0xC0);

lcd_puts ("switch pressed");

// itoa(counter, value, 10);

// lcd_puts(value);

The system_init work is utilized to introduce the pin I/O activity, LCD and to
store the Rotary Encoder position.

void system_init(){

TRISB = 0x00; // PORT B as output, This port is used for LCD

TRISDbits.TRISD2 = 1;
TRISDbits.TRISD3 = 1;

TRISCbits.TRISC4 = 1;

lcd_init(); // This will Initialize the LCD

position = Encoder_CLK;// Sotred the CLK position on system


init, before the while loop start.

The LCD work is composed on the lcd.c and lcd.h library where the
lcd_puts(), lcd_cmd() are pronounced.
For the variable affirmation, arrangement bits and other code pieces, kindly
locate the full code underneath.

Code
/*
* File: main.c
*/
/*
* Configuration Related settings. Specific for microcontroller unit.
*/
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT
disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT
disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR
enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit
Serial Programming Enable bit (RB3/PGM pin has PGM function; low-
voltage programming enabled)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection
bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable
bits (Write protection off; all program memory may be written to by EECON
control)
#pragma config CP = OFF // Flash Program Memory Code Protection
bit (Code protection off)
#define _XTAL_FREQ 20000000
/*
* System Header files inclusions
*/
#include <xc.h>
//#include <string.h>
#include <stdlib.h>
#include "supporting c files/lcd.h"
#define Encoder_SW PORTDbits.RD2
#define Encoder_DT PORTDbits.RD3
#define Encoder_CLK PORTCbits.RC4
/*
* Program flow related functions
*/
int counter; // It will hold the count of rotary encoder.
int position; // It will store the rotary encoder position.
void sw_delayms(unsigned int d);
int value[7];
/*
* System Init Function
*/
void system_init ();
/* Main function single Thread*/
void main(void) {
system_init();
lcd_puts ("Helloworld");
lcd_com(0xC0);
counter = 0;
while(1){
lcd_com(0xC0);
if (Encoder_SW == 0){
sw_delayms(20);
if (Encoder_SW == 0){
//lcd_com(1);
//lcd_com(0xC0);
lcd_puts ("switch pressed");
// itoa(counter, value, 10);
// lcd_puts(value);
}
}
if (Encoder_CLK != position){
if (Encoder_DT != position){
// lcd_com (0x01);
counter++;
lcd_com (0xC0);
lcd_puts(" ");
lcd_com (0xC0);
lcd_bcd(1,counter);
}
else{
// lcd_com (0x01);
lcd_com (0xC0);
counter--;
lcd_puts(" ");
lcd_com (0xC0);
lcd_bcd(1,counter);
//lcd_puts("Left");
}
}
position = Encoder_CLK;
}
return;
}
void sw_delayms(unsigned int d){
int x, y;
for(x=0;x<d;x++)
for(y=0;y<=1275;y++);
}
void system_init(){
TRISB = 0x00; // PORT B as output, This port is used for LCD
TRISDbits.TRISD2 = 1;
TRISDbits.TRISD3 = 1;
TRISCbits.TRISC4 = 1;
lcd_init(); // This will Initialize the LCD
position = Encoder_CLK;// Sotred the CLK position on system init, before
the while loop start.
}

◆ ◆ ◆
5. CREATING PWM FLAGS
ON GPIO PINS OF PIC
MICROCONTROLLER
PWM signal age is an indispensable device in each inserted engineers
munititions stockpile, they come in helpful for part of utilizations like
controlling the situation of servo engine, exchanging scarcely any force
electronic ICs in converters/invertors and in any event, for a basic LED
brilliance control. In PIC microcontrollers PWM signs can be created
utilizing the Compare, Capture and PWM (CCP) modules by setting the
necessary Registers, we have as of now figured out how to do that in the PIC
PWM instructional exercise. In case, there is one significant downside with
that strategy.
The PIC16F877A can create PWM flags just on pins RC1 and RC2, in the
event that we utilize the CCP modules. In case, we may experience
circumstances, where we need more pins to have PWM usefulness. For
example for my situation, I need to control 6 RC servo engines for my
automated arm venture for which the CCP module is miserable. In these
situations we can program the GPIO pins to deliver PWM signals utilizing
clock modules. In this way we can create the same number of Pulse Width
Modulation signals with any necessary pin. There are additionally other
equipment hacks like utilizing a multiplexer IC, yet why contribute on
equipment when the equivalent can be accomplished however programming.
So in this instructional exercise we will figure out how to change over a PIC
GPIO pin into a PWM pin and to test it we will reproduce it on proteus with
advanced oscilloscope and furthermore control the situation of Servo engine
utilizing the PWM flag and differ its obligation cycle by shifting a
potentiometer.

What is a PWM Signal?

Before we dive into the subtleties, let us look over a piece on what PWM
Signals are. Heartbeat Width Modulation (PWM) is a computerized signal
which is most normally utilized in charge hardware. This sign is set high (5v)
along with low (0v) in a predefined time along with speed. The time during
which the sign remains high is known as the "on schedule" and the time
during which the sign remains low is known as the "off time". There are two
significant parameters for a Pulse Width Modulation as talked about
underneath:

Obligation pattern of the Pulse Width Modulation

The level of time wherein the Pulse Width Modulation signal stays HIGH (on
schedule) is called as obligation cycle. In the event that the sign is
consistently ON it is in 100% obligation cycle and on the off chance that it is
constantly off it is 0% obligation cycle.

Duty Cycle =Turn ON time/ (Turn ON time + Turn OFF time)


Recurrence of a PWM

The recurrence of a PWM signal decides how quick a Pulse Width


Modulation finishes one period. One Period is finished ON and OFF of a
PWM signal as appeared in the above figure. In our instructional exercise we
will set a recurrence of 5KHz.

Figuring Duty Cycle for PWM

To create PWM signal on a General Purpose Input/Output pin we require to


just turn it on and off for a pre-characterized time. Yet, it isn't as basic as it
sounds. This on schedule and off time ought to be exact for each cycle so we
essentially can't utilize defer capacities, thus we utilize a clock module and
utilize the clock intrudes. Additionally we require to consider the obligation
cycle and the recurrence of the PWM signal that we create. The
accompanying variable names are utilized in program to characterize the
parameters.

Variable Refers to
Name

PWM_Frequency Frequency of the PWM Signal

Total time taken for one complete cycle of


T_TOTAL PWM
T_ON On time of the PWM signal

T_OFF Off time of the PWM signal

Duty_cycle Duty cycle of the PWM signal

So now, how about we crunch the numbers.


This is the standard formulae where recurrence is basically the
complementary of time. The estimation of recurrence must be chosen and set
by the client dependent on his/her application prerequisite.

T_TOTAL = (1/PWM_Frequency)

At the point when the client changes the Duty cycle esteem, our program
ought to naturally alter the T_ON time and T_OFF time as indicated by that.
So the above formulae can be utilized to ascertain T_ON dependent on the
estimation of Duty_Cycle and T_TOTAL.

T_ON = (Duty_Cycle*T_TOTAL)/100

Since the Total time of the PWM signal for one full cycle will be the total of
on schedule and off time. We can ascertain the off time T_OFF as appeared
previously.

T_OFF = T_TOTAL – T_ON

In light of these formulae we can start programming the PIC microcontroller.


The program includes the PIC Timer Module along with PIC Analog to
Digital Converter Module to make a Pulse Width Modulation signal based
with a differing Duty cycle as per the ADC esteem structure the POT. In case
you are new to utilizing these modules, in this point it is unequivocally
prescribed to peruse the suitable instructional exercise by tapping on the
hyperlinks.

Programming PIC to create PWM on GPIO Pins

The total program for this instructional exercise can be found at the base of
the site like consistently. In this segment we should see how the program is
really composed. Like all projects, we start by setting the designs bits. I have
utilized the memory sees choice to set it for me.

// CONFIG

#pragma config FOSC = HS // Oscillator Selection bits (HS


oscillator)

#pragma config WDTE = OFF // Watchdog Timer Enable bit


(WDT disabled)

#pragma config PWRTE = OFF // Power-up Timer Enable bit


(PWRT disabled)

#pragma config BOREN = ON // Brown-out Reset Enable bit


(BOR enabled)

#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-


Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on
MCLR must be used for programming)

#pragma config CPD = OFF // Data EEPROM Memory Code


Protection bit (Data EEPROM code protection off)

#pragma config WRT = OFF // Flash Program Memory Write


Enable bits (Write protection off; all program memory may be
written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code
Protection bit (Code protection off)

// #pragma config statements should precede project file includes.

// Use project enums instead of #define for ON and OFF.

#include <xc.h>

In this point we notice the check recurrence utilized in the equipment, here
my equipment utilizes 20MHz precious stone, you can enter the worth
situated in your equipment. Followed by that is the recurrence estimation of
the Pulse Width Modulation signal. Since my point here it to control a
diversion RC servo engine which requires a PWM recurrence of 50Hz I have
set 0.05KHz as the Frequency esteem you can similarly change this situated
in your application prerequisites.

#define _XTAL_FREQ 20000000

#define PWM_Frequency 0.05 // in KHz (50Hz)

Presently, that we have the evaluation of Frequency we can ascertain the


T_TOTAL utilizing the above examined equations. The outcome is plunged
by 10 to get the estimation of time in milli seconds. For my situation the
estimation of T_TOTAL will be 2 milli seconds.

int T_TOTAL = (1/PWM_Frequency)/10; //calculate Total Time from


frequency (in milli sec)) //2msec

Followed by that, we instate the ADC modules for perusing the situation of
the Potentiometer as talked about in our ADC PIC instructional exercise.
Next we have the Interrupt administration routine which will be called
without fail, the clock floods we will return to this later, for the time being
how about we check the fundamental capacity.
Inside the fundamental capacity we design the clock module. Here I have
arranged the Timer module to flood for each 0.1ms. The incentive for the
time can be determined by utilizing the formulae beneath

RegValue = 256-((Delay * Fosc)/(Prescalar*4)) delay in sec and Fosc


in hz

For my situation for a deferral of 0.0001 seconds (0.1ms) with prescalar of 64


and Fosc of 20MHz the estimation of my register (TMR0) ought to be 248.
So the setup resembles this

/*****Port Configuration for Timer ******/

OPTION_REG = 0b00000101; // Timer0 with external freq and 64


as prescalar // Also Enables PULL UPs

TMR0=248; // Load the time value for 0.0001s; delayValue can


be between 0-256 only

TMR0IE=1; //Enable timer interrupt bit in PIE1 register

GIE=1; //Enable Global Interrupt

PEIE=1; //Enable the Peripheral Interrupt

/***********______***********/

At that point we need to set the Input along with Output arrangement. Here
we are utilizing the AN0 pin for perusing the ADC worth and PORTD pins to
yield the PWM signals. So start them as yield pins and make them low by
utilizing the beneath lines of code.

/*****Port Configuration for I/O ******/


TRISD = 0x00; //Instruct the MCU that all pins on PORT D are
output

PORTD=0x00; //Initialize all pins to 0

/***********______***********/

Inside the limitless while circle, we require to figure the estimation of on


schedule (T_ON) from the obligation cycle. The on schedule and obligation
cycle fluctuates dependent on the situation of the POT so we do it over and
again inside the while circle as demonstrated as follows. 0.0976 is the worth
that must be duplicated with 1024 to get 100 and to compute T_ON we have
increased it with 10 to get an incentive in milli seconds.

while(1)

POT_val = (ADC_Read(0)); //Read the value of POT using ADC

Duty_cycle = (POT_val * 0.0976); //Map 0 to 1024 to 0 to 100

T_ON = ((Duty_cycle * T_TOTAL)*10 / 100); //Calculate On


Time using formulae unit in milli seconds

__delay_ms(100);

Since the clock is set to over stream for each 0.1ms, the clock intrude on
administration routine ISR will be required each 0.1ms. Inside the
administration routine we utilize a variable called check and augmentation it
for each 0.1ms. Along these lines we can keep track f time. To become
familiar with Interrupts in PIC microcontroller, follow the connections
if(TMR0IF==1) // Timer flag has been triggered due to timer
overflow -> set to overflow for every 0.1ms

TMR0 = 248; //Load the timer Value

TMR0IF=0; // Clear timer interrupt flag

count++; //Count increments for every 0.1ms -> count/10 will


give value of count in ms

At long last the time has come to flip the GPIO nail based to the estimation of
T_ON along with T_OFF. We have the tally variable that monitors time in
milli seconds. So we utilize that variable to check in case time is not exactly
on schedule, on the off chance that truly, at that point we keep the GPIO nail
went to else we turn it off and keep it killed until the new cycle begins. This
should be possible by contrasting it with the all out time of one PWM cycle.
The code to do the equivalent is demonstrated as follows

if (count <= (T_ON) ) //If time less than on time

RD1=1; //Turn on GPIO

else

RD1=0; //Else turn off GPIO

if (count >= (T_TOTAL*10) ) //Keep it turned off until a new cycle


starts

count=0;
Circuit Diagram

The circuit graph for creating PWM with GPIO pin of PIC microcontroller is
extremely straightforward, simply power the PIC with oscillator and associate
the potentiometer to stick AN0 and Servo Motor to stick RD1, we can utilize
GPIO pin to get the PWM signal, I have chosen RD1 simply out of irregular.
Both the Potentiometer and the Servo engine is controlled by 5V which is
directed from the 7805 as appeared beneath in the circuit graph.

Reenactment

To reenact the venture I utilized my proteus programming. Construct the


circuit appeared underneath and connect the code to your reproduction and
run it. You must get a Pulse Width Modulation signal on the RD1 GPIO pin
according to our program and the obligation pattern of the PWM must get
controlled dependent on the situation of the potentiometer. The underneath
GIF shows how the PWM sign and servo engine react when the ADC esteem
is changed across the potentiometer.

Equipment Setup for controlling Servo Motor utilizing PIC


Microcontroller

My total equipment set-up is demonstrated as follows, for individuals who


are following my instructional exercises this board should look recognizable,
it is a similar board which I have utilized in the entirety of my instructional
exercises up until this point. You can refer the Blinking Light Emitting Diode
instructional exercise in case you are keen on knowing how I assemble it. In
any case simply follow the circuit outline above and all should work fine.
Transfer the program and differ the potentiometer and you should see the
servo changing the position dependent on the situation of the potentiometer.
Expectation you comprehended the venture and appreciated structure.
I am intending to take this venture forward by adding alternatives to control
numerous servo engines and consequently fabricating a mechanical arm out
of it, like the Arduino Robotic Arm that we previously constructed. So up to
that point see ya!!

Code
/*
* File: PIC_GPIO_PWM.c
*/
// CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT
disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT
disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR
enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit
Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be
used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection
bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable
bits (Write protection off; all program memory may be written to by EECON
control)
#pragma config CP = OFF // Flash Program Memory Code Protection
bit (Code protection off)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#define _XTAL_FREQ 20000000
#define PWM_Frequency 0.05 // in KHz (50Hz)
//TIMER0 8-bit with 64-bit Prescalar
//$$RegValue = 256-((Delay * Fosc)/(Prescalar*4)) delay in sec and Fosc in
hz ->Substitute value of Delay for calculating RegValue
int POT_val; //variable to store value from ADC
int count; //timer variable
int T_TOTAL = (1/PWM_Frequency)/10; //calculate Total Time from
frequency (in milli sec)) //2msec
int T_ON=0; //value of on time
int Duty_cycle; //Duty cycle value
void ADC_Initialize() //Prepare the ADC module
{
ADCON0 = 0b01000001; //ADC ON and Fosc/16 is selected
ADCON1 = 0b11000000; // Internal reference voltage is selected
}
unsigned int ADC_Read(unsigned char channel) //Read from ADC
{
ADCON0 &= 0x11000101; //Clearing the Channel Selection Bits
ADCON0 |= channel<<3; //Setting the required Bits
__delay_ms(2); //Acquisition time to charge hold capacitor
GO_nDONE = 1; //Initializes A/D Conversion
while(GO_nDONE); //Wait for A/D Conversion to complete
return ((ADRESH<<8)+ADRESL); //Returns Result
}
void interrupt timer_isr()
{
if(TMR0IF==1) // Timer flag has been triggered due to timer overflow ->
set to overflow for every 0.1ms
{
TMR0 = 248; //Load the timer Value
TMR0IF=0; // Clear timer interrupt flag
count++; //Count increments for every 0.1ms -> count/10 will give value
of count in ms
}

if (count <= (T_ON) )


RD1=1;
else
RD1=0;

if (count >= (T_TOTAL*10) )


count=0;
}
void main()
{
/*****Port Configuration for Timer ******/
OPTION_REG = 0b00000101; // Timer0 with external freq and 64 as
prescalar // Also Enables PULL UPs
TMR0=248; // Load the time value for 0.0001s; delayValue can be
between 0-256 only
TMR0IE=1; //Enable timer interrupt bit in PIE1 register
GIE=1; //Enable Global Interrupt
PEIE=1; //Enable the Peripheral Interrupt
/***********______***********/

/*****Port Configuration for I/O ******/


TRISD = 0x00; //Instruct the MCU that all pins on PORT D are output
PORTD=0x00; //Initialize all pins to 0
/***********______***********/

ADC_Initialize();
while(1)
{
POT_val = (ADC_Read(0)); //Read the value of POT using ADC

Duty_cycle = (POT_val * 0.0976); //Map 0 to 1024 to 0 to 100

T_ON = ((Duty_cycle * T_TOTAL)*10 / 100); //Calculate On Time


using formulae unit in milli seconds
__delay_ms(100);

◆ ◆ ◆
6. HEART BEAT
MONITORING UTILIZING
PIC MICROCONTROLLER
AND PULSE SENSOR
Heart Beat rate is most significant parameter in observing any individual's
wellbeing. In the advanced time of wearable gadgets, there are parcel of
gadgets which can gauge heartbeat, circulatory strain, strides, calories
consumed and part of different things. These gadgets has heartbeat sensor
inside them to detect the beat rate. Today, we will likewise utilize a heartbeat
sensor with PIC Microcontroller to check heart beat every moment along
with the Inter-Beat Interval, these qualities will be additionally shown on
16x2 character Liquid Crystal Display. We will utilize PIC16F877A PIC
microcontroller in this venture. We as of now interfaced beat sensor with
Arduino for Patient Monitoring System.

Required Components

PIC16F877A microcontroller

20 Mhz Crystal

33pF capacitor 2 pcs

4.7k resistor 1 pcs


16x2 Character LCD

10K pot for differentiate control of the LCD

SEN-11574 Pulse sensor

Velcro tie

5V Power connector

Breadboard and hookup wires

Heartbeat Sensor SEN-11574

To quantify the heartbeat we require a heartbeat sensor. Here we have chosen


SEN-11574 heartbeat sensor which is effectively accessible on the web or
disconnected stores. We utilized this sensor as there are test codes gave from
the maker, however that is an Arduino code. We changed over that code for
our PIC microcontroller.
The sensor is tiny and ideal for perusing heartbeat across ear cartilage or on
the fingertip. It is 0.625" in width and 0.125" thick from the round PCB side.
This sensor gives a simple sign and the sensor can be driven with 3V
otherwise 5V, the present utilization of the sensor is 4 mA, which is
incredible for versatile applications. The sensor accompanies 3 wire with 24"
long hookup link along with berg male header toward the end. Likewise, the
sensor accompanies Velcro Finger Strap to wear it across fingertip.
Heartbeat Sensor schematic is additionally given by the maker and
furthermore accessible on sparkfun.com.

The sensor schematic comprises optical pulse sensor, clamor wiping out RC
hardware or channels, which can be found in the schematic graph. R2, C2,
C1, C3 and an operational enhancer MCP6001 are utilized for dependable
intensified simple yield.
There are barely any different sensors for Heart Beat Monitoring however
SEN-11574 heartbeat sensor is generally utilized in Electronics ventures.

Circuit Diagram for Pulse Sensor interfacing with PIC Microcontroller


Here we have associated the beat sensor over a second pin of the
microcontroller unit. As the sensor gives simple information, we have to
change over the simple information into computerized signal by doing
essential estimations.
The Crystal oscillator of 20Mhz is associated across 2 OSC pins of the
microcontroller unit with 2 clay 33pF capacitors. The LCD is associated over
the RB port of the microcontroller.
Code Explanation

The code is somewhat mind boggling for apprentices. The producer gave test
codes to the SEN-11574 sensor, however it was composed for the Arduino
stage. We have to change over the figuring for our microchip, PIC16F877A.
What's more, the supporting C records can be downloaded from here.
Our code stream is moderately straightforward and we made the means
utilizing a switch case. In accordance with the producer, we have to get the
information from the sensor in each 2 milliseconds. In this way, we utilized a
clock interfere with administration routine which will fire a capacity in each 2
milliseconds.
Our code stream in switch proclamation will go this way:

Case 1: Read the ADC


Case 2: Calculate the Heart Beat and IBI
Case 3: Show the heartbeat and IBI on LCD
Case 4: IDLE (Do nothing)

Inside the clock intrude on work, we modify the condition of the program to
Case 1: Read the Analog to Digital Converter on each 2 milliseconds.
In this way, in the fundamental capacity, we characterized the program state
and all the switch cases.

void main() {

system_init();

main_state = READ_ADC;

while (1) {

switch (main_state) {

case READ_ADC:

adc_value = ADC_Read(0); // 0 is the channel number

main_state = CALCULATE_HEART_BEAT;

break;

case CALCULATE_HEART_BEAT:

calculate_heart_beat(adc_value);
main_state = SHOW_HEART_BEAT;

break;

case SHOW_HEART_BEAT:

if (QS == true) { // A Heartbeat Was Found

// BPM and IBI have been Determined

// Quantified Self "QS" true when Arduino finds a


heartbeat

QS = false; // reset the Quantified Self flag for next


time

// 0.9 used for getting better data. actually should not


be used

BPM = BPM * 0.9;

IBI = IBI / 0.9;

lcd_com(0x80);

lcd_puts("BPM:- ");

lcd_print_number(BPM);

lcd_com(0xC0);
lcd_puts("I.B.I:- ");

lcd_print_number(IBI);

main_state = IDLE;

break;

case IDLE:

break;

default:

We are utilizing two equipment peripherals of the PIC16F877A: Timer0 and


ADC.
Inside the timer0.c record,
TMR0 = (uint8_t)(tmr0_mask & (256-(((2
*_XTAL_FREQ)/(256*4))/1000)));

This count is giving the 2 milliseconds clock intrude. The figuring recipe is

// TimerCountMax - (((delay(ms) * Focs(hz)) / (PreScale_Val * 4)) /


1000)

On the off chance that we see the timer_isr work, it is-

void timer_isr() {

main_state = READ_ADC;

In this capacity the program state is changed to READ_ADC in each 2ms.


At that point the CALCULATE_HEART_BEAT work is taken from the
Arduino model code.

void calculate_heart_beat(int adc_value) {

Signal = adc_value;

sampleCounter += 2; // keep track of the time in mS with this


variable

int N = sampleCounter - lastBeatTime; // monitor the time since


the last beat to avoid noise

// find the peak and trough of the pulse wave


if (Signal < thresh && N > (IBI / 5)*3) { // avoid dichrotic noise by
waiting 3/5 of last IBI

if (Signal < T) { // T is the trough

T = Signal; // keep track of lowest point in pulse wave

………….

………………………..

Further, the total code is given underneath and all around clarified by the
remarks. This heart beat sensor information can be additionally transferred to
the cloud and observed over the web from anyplace, which along these lines
makes it IoT based Heart Beat Monitoring framework, follow the connection
to find out additional.
Download Supporting C records for this PIC Pulse Sensor Project from here.

Code
/*
* File: main.c
*/
// PIC16F877A Configuration Bit Settings
// 'C' source line config statements
// CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT
disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT
disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR
enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit
Serial Programming Enable bit (RB3/PGM pin has PGM function; low-
voltage programming enabled)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection
bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable
bits (Write protection off; all program memory may be written to by EECON
control)
#pragma config CP = OFF // Flash Program Memory Code Protection
bit (Code protection off)
#include <xc.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include "supporing_cfile\lcd.h"
#include "supporing_cfile\eusart1.h"
#include "supporing_cfile\adc.h"
#include "supporing_cfile\tmr0.h"
/*
Hardware related definition
*/
#define _XTAL_FREQ 200000000 //Crystal Frequency, used in delay
/*
Program Flow related definition
*/
#define READ_ADC 1
#define CALCULATE_HEART_BEAT 2
#define SHOW_HEART_BEAT 3
#define IDLE 0
#define DEFAULT -1
volatile int rate[10]; // array to hold last ten IBI values
volatile unsigned long sampleCounter = 0; // used to determine pulse timing
volatile unsigned long lastBeatTime = 0; // used to find IBI
volatile int P = 512; // used to find peak in pulse wave, seeded
volatile int T = 512; // used to find trough in pulse wave, seeded
volatile int thresh = 530; // used to find instant moment of heart beat, seeded
volatile int amp = 0; // used to hold amplitude of pulse waveform, seeded
volatile bool firstBeat = true; // used to seed rate array so we startup with
reasonable BPM
volatile bool secondBeat = false; // used to seed rate array so we startup with
reasonable BPM
volatile int BPM; // int that holds raw Analog in 0. updated every 2mS
volatile int Signal; // holds the incoming raw data
volatile int IBI = 600; // int that holds the time interval between beats! Must
be seeded!
volatile bool Pulse = false; // "True" when User's live heartbeat is detected.
"False" when not a "live beat".
volatile bool QS = false; // becomes true when finds a beat.
int main_state = -1;
int adc_value = 0;
int tune = 0;
/*
Other Specific definition
*/
void system_init(void);
void calculate_heart_beat(int adc_value) {
Signal = adc_value;
sampleCounter += 2; // keep track of the time in mS with this variable
int N = sampleCounter - lastBeatTime; // monitor the time since the last
beat to avoid noise
// find the peak and trough of the pulse wave
if (Signal < thresh && N > (IBI / 5)*3) { // avoid dichrotic noise by
waiting 3/5 of last IBI
if (Signal < T) { // T is the trough
T = Signal; // keep track of lowest point in pulse wave
}
}
if (Signal > thresh && Signal > P) { // thresh condition helps avoid noise
P = Signal; // P is the peak
} // keep track of highest point in pulse wave
// NOW IT'S TIME TO LOOK FOR THE HEART BEAT
// signal surges up in value every time there is a pulse
if (N > 250) { // avoid high frequency noise
if ((Signal > thresh) && (Pulse == false) && (N > (IBI / 5)*3)) {
Pulse = true; // set the Pulse flag when we think there is a pulse
IBI = sampleCounter - lastBeatTime; // measure time between beats
in mS
lastBeatTime = sampleCounter; // keep track of time for next pulse
if (secondBeat) { // if this is the second beat, if secondBeat == TRUE
secondBeat = false; // clear secondBeat flag
int i;
for (i = 0; i <= 9; i++) { // seed the running total to get a realisitic
BPM at startup
rate[i] = IBI;
}
}
if (firstBeat) { // if it's the first time we found a beat, if firstBeat ==
TRUE
firstBeat = false; // clear firstBeat flag
secondBeat = true; // set the second beat flag
//pulse_tmr_handle =
bsp_harmony_start_tmr_cb_periodic(PULSE_CHECK_TIME_INTERVAL,
0, pulse_read_cb); // enable interrupts again
return; // IBI value is unreliable so discard it
}
// keep a running total of the last 10 IBI values
uint16_t runningTotal = 0; // clear the runningTotal variable
int i;
for (i = 0; i <= 8; i++) { // shift data in the rate array
rate[i] = rate[i + 1]; // and drop the oldest IBI value
runningTotal += rate[i]; // add up the 9 oldest IBI values
}
rate[9] = IBI; // add the latest IBI to the rate array
runningTotal += rate[9]; // add the latest IBI to runningTotal
runningTotal /= 10; // average the last 10 IBI values
BPM = 60000 / runningTotal; // how many beats can fit into a
minute? that's BPM!
QS = true; // set Quantified Self flag
// QS FLAG IS NOT CLEARED INSIDE THIS ISR
}
}
if (Signal < thresh && Pulse == true) { // when the values are going down,
the beat is over
Pulse = false; // reset the Pulse flag so we can do it again
amp = P - T; // get amplitude of the pulse wave
thresh = amp / 2 + T; // set thresh at 50% of the amplitude
P = thresh; // reset these for next time
T = thresh;
}
if (N > 2500) { // if 2.5 seconds go by without a beat
thresh = 530; // set thresh default
P = 512; // set P default
T = 512; // set T default
lastBeatTime = sampleCounter; // bring the lastBeatTime up to date
firstBeat = true; // set these to avoid noise
secondBeat = false; // when we get the heartbeat back
}
}
void main() {
system_init();
main_state = READ_ADC;
while (1) {
switch (main_state) {
case READ_ADC:
{
adc_value = ADC_Read(0);
main_state = CALCULATE_HEART_BEAT;
break;
}
case CALCULATE_HEART_BEAT:
{
calculate_heart_beat(adc_value);
main_state = SHOW_HEART_BEAT;
break;
}
case SHOW_HEART_BEAT:
{
if (QS == true) { // A Heartbeat Was Found
// BPM and IBI have been Determined
// Quantified Self "QS" true when arduino finds a
heartbeat
QS = false; // reset the Quantified Self flag for next time
// 0.9 used for getting better data. actually should not be used
//BPM = BPM * 0.9;
// IBI = IBI / 0.9;
//IBI = IBI * 2;
// tune = BPM / 2;
//lcd_com(0x01);
lcd_com(0x80);
lcd_puts("BPM:- ");
lcd_print_number(BPM);
lcd_puts (" ");
lcd_com(0xC0);
lcd_puts("I.B.I:- ");
lcd_print_number(IBI);
lcd_puts (" ");

}
}
main_state = IDLE;
break;

case IDLE:
{
break;
}
default:
{
}
}
}
}
/*
This Function is for system initializations.
*/
void system_init(void){
TRISB = 0x00;
lcd_init(); // This will initialize the lcd
TMR0_Initialize();
TMR0_StartTimer();
INTERRUPT_GlobalInterruptEnable();
INTERRUPT_PeripheralInterruptEnable();
ADC_Init();
}
/*
* Custom timer callback function
*/
void timer_isr() {
main_state = READ_ADC;
}
void interrupt INTERRUPT_InterruptManager (void)
{
// interrupt handler
if(INTCONbits.TMR0IE == 1 && INTCONbits.TMR0IF == 1)
{
TMR0_ISR();
}
}

◆ ◆ ◆
7. WARM PRINTER
INTERFACING WITH
PIC16F877A
Warm printer is regularly alluded as receipt printer. It is generally utilized in
cafés, ATM, shops and numerous different spots where receipts or bill is
required. It is a practical arrangement and exceptionally helpful to use from
the client's side just as from the designer's side. A warm printer uses a unique
printing process which uses thermochromic paper or warm paper for printing.
The printer head is warmed at a specific temperature that when the warm
paper goes from the print head, the paper covering turns dark in the regions
where the printer head is warmed.
In this instructional exercise, we will interface a warm printer CSN A1 with
broadly utilized PIC microcontroller PIC16F877A. Here in this undertaking,
a warm printer is associated across PIC16F877A and a material switch is
utilized to begin the printing. A warning LED is likewise used to inform the
printing status. It will shine just when the printing action is going on.

Printer Specification and Connections


We are utilizing CSN A1 Thermal Printer from Cashino, which is accessible
effectively and the cost isn't excessively high.

On the off chance that we see the determination on its official site, we will
see a table which gives the definite particulars
On the posterior of the printer, we will see the accompanying association
The TTL connector gives the Rx Tx association with speak with the
microcontroller unit. We can likewise utilize the RS232 convention to speak
with the printer. The force connector is for controlling the printer and the
catch is utilized for printer testing reason. At the point when the printer is
being fueled, on the off chance that we press the individual test button the
printer, will print a sheet where details and test lines will be printed. Here is
the individual test sheet-
As should be obvious the printer utilize 9600 baud rate to speak with the
microcontroller unit. The printer can print ASCII characters. The
correspondence is extremely simple, we can print anything by just utilizing
UART, transmitting string otherwise character.
The printer needs a 5V 2A power flexibly for warming the printer head. This
is the downside of the warm printer as it takes immense burden current
during the printing procedure.

Requirements

To make the accompanying task, we need the accompanying things:-


Breadboard

Attach wires

PIC16F877A

2pcs 33pF fired circle capacitor

680R resistor

Any shading drove

Material switch

2pcs 4.7k resistors

Warm Printer CSN A1 with paper roll

5V 2A evaluated power flexibly unit.

Schematic Diagram along with Interpretation

Schematic for controlling printer with PIC Microcontroller is given


underneath:
Here we are utilizing PIC16F877A as microcontroller unit. A 4.7k resistor is
utilized to associate MCLR pin to the 5V power flexibly. We have
additionally associated an outer oscillator of 20 MHz with 33pF capacitors
for the clock signal. A warning LED is associated across RB2 port with 680R
drove current constraining resistor. The Tactile switch is associated across
RB0 pin when the catch is squeezed it will give Logic High in any case the
pin will get Logic low by the 4.7k resistor.
The printer CSN A1 is associated utilizing the cross arrangement,
Microcontroller Transmit pin is associated with the printer's Receive pin. The
printer likewise associated with the 5V and GND flexibly.
We developed the circuit in a breadboard and tried it.
Code Explanation

The code is entirely easy to comprehend. Complete code for interfacing


Thermal Printer with PIC16F877A is given toward the finish of article. As
usual, we first need to set the design bits in the PIC microcontroller.

// PIC16F877A Configuration Bit Settings

// 'C' source line config statements

// CONFIG

#pragma config FOSC = HS // Oscillator Selection bits (HS


oscillator)

#pragma config WDTE = OFF // Watchdog Timer Enable bit


(WDT disabled)

#pragma config PWRTE = OFF // Power-up Timer Enable bit


(PWRT disabled)

#pragma config BOREN = ON // Brown-out Reset Enable bit


(BOR enabled)

#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-


Circuit Serial Programming Enable bit (RB3/PGM pin has PGM
function; low-voltage programming enabled)

#pragma config CPD = OFF // Data EEPROM Memory Code


Protection bit (Data EEPROM code protection off)

#pragma config WRT = OFF // Flash Program Memory Write


Enable bits (Write protection off; all program memory may be
written to by EECON control)

#pragma config CP = OFF // Flash Program Memory Code


Protection bit (Code protection off)

From that point forward, we characterized framework equipment related


macros and utilized eusart1.h header record for eusart related equipment
control. The UART is arranged at 9600 Baud rate inside the header
document.

#include <xc.h>

#include "supporting_cfile\eusart1.h"

/*
* System hardware related macros

*/

#define _XTAL_FREQ 200000000 //Crystal Frequency, used in delay


routine

#define printer_sw PORTBbits.RB0 //this macro is for defining the


printing switch

#define notification_led PORTBbits.RB2

void system_init(void);

In the fundamental capacity, we initially checked the 'button press' and


furthermore utilized switch debounce strategies to take out the switch
glitches. We have made an if proclamation for 'button squeezed' condition.
First the drove will shine and the UART will print the strings. Custom lines
can be created inside the if proclamation and can be printed as a string.

void main(void) {

system_init();

while(1){

if(printer_sw == 1){ //switch is pressed

__delay_ms(50); // debounce delay

if (printer_sw == 1){ // switch is still pressed

notification_led = 1;
put_string("Hello! \n\r");//Print to Thermal printer

__delay_ms(50);

put_string("Thermal Printer Tutorial.\n\r");

__delay_ms(50);

put_string("Helloworld. \n\r");

__delay_ms(50);

put_string ("\n\r");

put_string ("\n\r");

put_string ("\n\r");

put_string ("---------------------------- \n \r");

put_string ("Thank You");

put_string ("\n\r");

put_string ("\n\r");

put_string ("\n\r");

notification_led = 0;

}
}

Complete Code is given beneath.

Code
/*
* File: main.c
* Project: Thermal Printer CSN-A1 Interfacing with pic16F877A
*/
// PIC16F877A Configuration Bit Settings
// 'C' source line config statements
// CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT
disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT
disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR
enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit
Serial Programming Enable bit (RB3/PGM pin has PGM function; low-
voltage programming enabled)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection
bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable
bits (Write protection off; all program memory may be written to by EECON
control)
#pragma config CP = OFF // Flash Program Memory Code Protection
bit (Code protection off)
#include <xc.h>
#include "supporting_cfile\eusart1.h"
/*
* System hardware related macros
*/
#define _XTAL_FREQ 200000000 //Crystal Frequency, used in delay
routine
#define printer_sw PORTBbits.RB0 //this macro is for defining the printing
switch
#define notification_led PORTBbits.RB2
void system_init(void);
void main(void) {
system_init();
while(1){
if(printer_sw == 1){ //switch is pressed
__delay_ms(50); // debounce delay
if (printer_sw == 1){ // switch is still pressed
notification_led = 1;
put_string("Hello! \n\r");//Print to Thermal printer
__delay_ms(50);
put_string("Thermal Printer Tutorial.\n\r");
__delay_ms(50);
put_string("Hello world. \n\r");
__delay_ms(50);
put_string ("\n\r");
put_string ("\n\r");
put_string ("\n\r");
put_string ("---------------------------- \n \r");
put_string ("Thank You");
put_string ("\n\r");
put_string ("\n\r");
put_string ("\n\r");
notification_led = 0;
}
}
}
}
void system_init(void){
TRISBbits.TRISB0 = 1; // Setting Printing Switch as input
TRISBbits.TRISB2 = 0;
notification_led = 0;
EUSART1_Initialize(); // This will initialise the Eusart
}

◆ ◆ ◆
8. INTERFACING
FINGERPRINT SENSOR
WITH PIC
MICROCONTROLLER
Unique mark Sensor, which we used to view in Sci-Fi motion pictures a
couple of years back, is currently gotten extremely basic to check the
character of an individual for different purposes. Currently we can view
special mark based frameworks wherever in our every day life like for
involvement in workplaces, representative confirm in banks, for money
withdrawal otherwise stores in ATMs, for character check in government
workplaces along with etc. We have as of now interfaced it with Arduino
along with with Raspberry Pi, we are gonna to interface Finger Print Sensor
with PIC microcontroller. Utilizing this PIC microcontroller PIC16f877A
Finger Print System, we can choose new fingerprints in the framework and
can erase the as of now took care of fingerprints.

Required Components

PIC16f877A Microcontroller

Special finger impression Module

Press catches or keypad


16x2 LCD

10k pot

18.432000 MHz Crystal Oscillator

Bread Board or PCB (requested from JLCPCB)

Jumper wires

Driven (discretionary)

Resistor 150 ohm - 1 k ohm (discretionary)

5v Power gracefully
Circuit Diagram and Explanation

In this PIC Microcontroller Finger Print sensor interfacing venture, we have


utilized 4 press fastens: these catches are utilized for multifunctioning. Key 1
is utilized for coordinating the special finger impression and augmentation
unique mark ID while putting away or erasing the finger impression in the
framework. Key 2 is utilized for enlisting the new special mark and for
decrement finger print ID while putting away or erasing special finger print in
the framework. Key 3 is utilized for erase put away finger from the
framework and key 4 is utilized for OK. A LED is utilized for a sign that
unique mark is distinguished or coordinated. Here we have utilized a unique
mark module which chips away at UART. So here we have interfaced this
unique mark module with PIC microcontroller at its default baud rate which
is 57600.

In this way, as a matter of first importance, we have to make the all the
necessary association as appeared in Circuit Diagram beneath. Associations
are straightforward, we have quite recently associated unique mark module to
PIC microcontroller's UART. A 16x2 LCD is utilized for showing all
messages. A 10k pot is additionally utilized with LCD for controlling the
differentiation of the equivalent. 16x2 LCD information pins are associated
PORTA pins. LCD's d4, d5, d6, and d7 pins are associated with Pin RA0,
RA1, RA2, and RA3 of PIC microcontroller individually. Four press catches
(or keypad) is associated with PORTD's Pin RD0, RD1, RD2, and RD.
Driven is likewise associated at port PORTC's pin RC3. Here we have
utilized a 18.432000 MHz outside valuable stone oscillator to clock the
microcontroller.

Activity of Fingerprint Sensor with PIC Microcontroller

Activity of this task is basic, simply transfer hex record, produced from
source code, into the PIC microcontroller with the assistance of PIC
developer or burner (PIckit2 or Pickit3 or others)and then you will see some
introduction messages over LCD and afterward the client will be approached
to enter a decision for activities. To coordinate unique mark client need to
squeeze key 1 then LCD will request Place Finger on Finger Print Sensor.
Presently by putting a finger over special finger print module, we can check
if our fingerprints are as of now put away otherwise not. On the off chance
that your special finger print is put away, at that point LCD will show the
message with the putting away ID of unique mark like 'ID:2' else it will show
'Not Found'.
Presently to enlist a special mark, the client needs to press enlist catch or key
2 and adhere to the directions messages on the LCD screen.
In case the client requires to erase any of fingerprints, in this point the client
requires to press the erase catch or key 3. After which, LCD will request the
ID of the unique mark which is to be erased. Currently by utilizing
augmentation press catch or key 1(match press catch or key 1) and decrement
press catch or key 2 (enlist press catch or key 2) for addition and decrement,
the client can choose the ID of spared Finger Print and press OK catch to
erase that unique finger print.

Unique finger print interfacing Note: Program of this venture is somewhat


perplexing for a tenderfoot. However, its straightforward interfacing code
made by utilizing perusing r305 unique mark module datasheet. All the
guidance of working of this unique finger print module is given in the
datasheet.
Here we have utilized an edge configuration to converse with special finger
print module. At whatever point we send an order or information demand
edge to unique finger impression module it reacts us with a similar casing
position containing information or data identified with applied order. The
entirety of the information and order outline position has given in the client
manual or in the datasheet of R305 unique mark module.

Programming Explanation

In programming, we have utilized the underneath outline design.


We start the program by setting the design bits and characterizing macros and
pins for LCD, Buttons and LED, which you can check in the total code given
toward the finish of this venture. In case you are new to PIC Microcontroller,
at that point start with Getting initiated with PIC Microcontroller Project.
At that point we pronounced and instated some factor and exhibit, and made
a casing that we have to use in this task to interface unique mark module with
PIC microcontroller.

uchar buf[20];

uchar buf1[20];

volatile uint index=0;

volatile int flag=0;

uint msCount=0;

uint g_timerflag=1;

volatile uint count=0;

uchar data[10];

uint id=1;

enum

CMD,

DATA,

SBIT_CREN=4,
SBIT_TXEN,

SBIT_SPEN,

};

const char passPack[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0,
0x7, 0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1B};

const char f_detect[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0,
0x3, 0x1, 0x0, 0x5};

const char f_imz2ch1[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1,


0x0, 0x4, 0x2, 0x1, 0x0, 0x8};

const char f_imz2ch2[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1,


0x0, 0x4, 0x2, 0x2, 0x0, 0x9};

const char f_createModel[]=


{0xEF,0x1,0xFF,0xFF,0xFF,0xFF,0x1,0x0,0x3,0x5,0x0,0x9};

char f_storeModel[]=
{0xEF,0x1,0xFF,0xFF,0xFF,0xFF,0x1,0x0,0x6,0x6,0x1,0x0,0x1,0x0,0xE};

const char f_search[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0,
0x8, 0x1B, 0x1, 0x0, 0x0, 0x0, 0xA3, 0x0, 0xC8};

char f_delete[]=
{0xEF,0x1,0xFF,0xFF,0xFF,0xFF,0x1,0x0,0x7,0xC,0x0,0x0,0x0,0x1,0x0,0x15};

After it, we have made LCD capacity to drive LCD.

void lcdwrite(uchar ch,uchar rw)


{

LCDPORT= ch>>4 & 0x0F;

RS=rw;

EN=1;

__delay_ms(5);

EN=0;

LCDPORT= ch & 0x0F;

EN=1;

__delay_ms(5);

EN=0;

lcdprint(char *str)

while(*str)

lcdwrite(*str++,DATA);

//__delay_ms(20);

}
}

lcdbegin()

uchar lcdcmd[5]={0x02,0x28,0x0E,0x06,0x01};

uint i=0;

for(i=0;i<5;i++)

lcdwrite(lcdcmd[i], CMD);

Given capacity is utilized for instating UART

void serialbegin(uint baudrate)

SPBRG = (18432000UL/(long)(64UL*baudrate))-1; // baud rate


@18.432000Mhz Clock

TXSTAbits.SYNC = 0; //Setting Asynchronous


Mode, ie UART

RCSTAbits.SPEN = 1; //Enables Serial Port

TRISC7 = 1; //As Prescribed in Datasheet

TRISC6 = 0; //As Prescribed in Datasheet

RCSTAbits.CREN = 1; //Enables Continuous


Reception

TXSTAbits.TXEN = 1; //Enables
Transmission

GIE = 1; // ENABLE interrupts

INTCONbits.PEIE = 1; // ENable peripheral interrupts.

PIE1bits.RCIE = 1; // ENABLE USART receive interrupt

PIE1bits.TXIE = 0; // disable USART TX interrupt

PIR1bits.RCIF = 0;

Given capacities are utilized for moving orders to unique mark Module and
getting information from special finger print module.

void serialwrite(char ch)

while(TXIF==0); // Wait till the transmitter register becomes


empty

TXIF=0; // Clear transmitter flag

TXREG=ch; // load the char to be transmitted into transmit


reg

serialprint(char *str)
{

while(*str)

serialwrite(*str++);

void interrupt SerialRxPinInterrupt(void)

if((PIR1bits.RCIF == 1) && (PIE1bits.RCIE == 1))

uchar ch=RCREG;

buf[index++]=ch;

if(index>0)

flag=1;

RCIF = 0; // clear rx flag

void serialFlush()
{

for(int i=0;i<sizeof(buf);i++)

buf[i]=0;

After it we have to do a capacity which plans information that will be


transmitted to unique mark and disentangle the information originating from
finger impression module.

int sendcmd2fp(char *pack, int len)

uint res=ERROR;

serialFlush();

index=0;

__delay_ms(100);

for(int i=0;i<len;i++)

serialwrite(*(pack+i));
}

__delay_ms(1000);

if(flag == 1)

if(buf[0] == 0xEF && buf[1] == 0x01)

if(buf[6] == 0x07) // ack

if(buf[9] == 0)

uint data_len= buf[7];

data_len<<=8;

data_len|=buf[8];

for(int i=0;i<data_len;i++)

data[i]=0;

for(int i=0;i<data_len-2;i++)

data[i]=buf[10+i];
}

res=PASS;

else

res=ERROR;

Presently, there are 4 capacity accessible in the code for four distinctive
assignment:

Capacity for input the unique mark ID – unit getId()

Capacity for coordinating finger – void matchFinger()

Capacity for selecting new finger – void enrolFinger()

Capacity for erasing a finger – void deleteFinger()

The total code with all the four capacity is given toward the end.
Presently in the principle work, we instate GPIOs, LCD, UART and check
whether the unique finger impression module is associated with a
microcontroller or not. At that point it gives some introduction messages over
LCD. At long last in while circle we read all keys or press catches to work
the task.
int main()

void (*FP)();

ADCON1=0b00000110;

LEDdir= 0;

SWPORTdir=0xF0;

SWPORT=0x0F;

serialbegin(57600);

LCDPORTDIR=0x00;

TRISE=0;

lcdbegin();

lcdprint("Fingerprint");

lcdwrite(192,CMD);

lcdprint("Interfacing");

__delay_ms(2000);

lcdwrite(1,CMD);

lcdprint("Using PIC16F877A");

lcdwrite(192,CMD);
lcdprint("Helloworld");

__delay_ms(2000);

index=0;

while(sendcmd2fp(&passPack[0],sizeof(passPack)))

lcdwrite(1,CMD);

lcdprint("FP Not Found");

__delay_ms(2000);

index=0;

lcdwrite(1,CMD);

lcdprint("FP Found");

__delay_ms(1000);

lcdinst();

while(1)

FP=match<enrol?matchFinger:enrol<delet?
enrolFinger:delet<enrol?deleteFinger:lcdinst;
FP();

return 0;

Complete PIC Code is given underneath. Likewise check our different


undertakings utilizing Finger Print Sensor Module:

Unique finger impression Based Biometric Voting Machine using


Arduino

Biometric Security System using Arduino along with Fingerprint


Sensor

Unique finger impression Based Biometric Attendance System


utilizing Arduino

?Fingerprint Sensor Interfacing with Raspberry Pi

Code
#define _XTAL_FREQ 18432000
#include <xc.h>
#include<pic.h>
#include <stdio.h>
#include <stdlib.h>
// BEGIN CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT
disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial
Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for
programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit
(Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits
(Write protection off; all program memory may be written to by EECON
control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit
(Code protection off)
//END CONFIG
#define uchar unsigned char
#define uint unsigned int
#define LCDPORTDIR TRISA
#define LCDPORT PORTA
#define RS RE1
#define EN RE0
#define SWPORTdir TRISD
#define SWPORT PORTD
#define enrol RD4
#define match RD5
#define delet RD7
#define ok RD6
#define up RD5
#define down RD4
#define LEDdir TRISC3
#define LED RC3
#define HIGH 1
#define LOW 0
#define PASS 0
#define ERROR 1
#define checkKey(id) id=up<down?++id:down<up?--id:id;
uchar buf[20];
uchar buf1[20];
volatile uint index=0;
volatile int flag=0;
uint msCount=0;
uint g_timerflag=1;
volatile uint count=0;
uchar data[10];
uint id=1;
enum
{
CMD,
DATA,
SBIT_CREN=4,
SBIT_TXEN,
SBIT_SPEN,
};
const char passPack[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0x7,
0x13, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1B};
const char f_detect[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0x3,
0x1, 0x0, 0x5};
const char f_imz2ch1[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0x4,
0x2, 0x1, 0x0, 0x8};
const char f_imz2ch2[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0x4,
0x2, 0x2, 0x0, 0x9};
const char f_createModel[]=
{0xEF,0x1,0xFF,0xFF,0xFF,0xFF,0x1,0x0,0x3,0x5,0x0,0x9};
char f_storeModel[]=
{0xEF,0x1,0xFF,0xFF,0xFF,0xFF,0x1,0x0,0x6,0x6,0x1,0x0,0x1,0x0,0xE};
const char f_search[]={0xEF, 0x1, 0xFF, 0xFF, 0xFF, 0xFF, 0x1, 0x0, 0x8,
0x1B, 0x1, 0x0, 0x0, 0x0, 0xA3, 0x0, 0xC8};
char f_delete[]=
{0xEF,0x1,0xFF,0xFF,0xFF,0xFF,0x1,0x0,0x7,0xC,0x0,0x0,0x0,0x1,0x0,0x15};
void lcdwrite(uchar ch,uchar rw)
{
LCDPORT= ch>>4 & 0x0F;
RS=rw;
EN=1;
__delay_ms(5);
EN=0;
LCDPORT= ch & 0x0F;
EN=1;
__delay_ms(5);
EN=0;
}
lcdprint(char *str)
{
while(*str)
{
lcdwrite(*str++,DATA);
//__delay_ms(20);
}
}
lcdbegin()
{
uchar lcdcmd[5]={0x02,0x28,0x0E,0x06,0x01};
uint i=0;
for(i=0;i<5;i++)
lcdwrite(lcdcmd[i], CMD);
}
void lcdinst()
{
lcdwrite(0x80, CMD);
lcdprint("1-Match 2-Enroll");
lcdwrite(0xc0, CMD);
lcdprint("3-delete Finger");
__delay_ms(10);
}
void serialbegin(uint baudrate)
{
SPBRG = (18432000UL/(long)(64UL*baudrate))-1; // baud rate
@18.432000Mhz Clock
TXSTAbits.SYNC = 0; //Setting Asynchronous Mode, ie
UART
RCSTAbits.SPEN = 1; //Enables Serial Port
TRISC7 = 1; //As Prescribed in Datasheet
TRISC6 = 0; //As Prescribed in Datasheet
RCSTAbits.CREN = 1; //Enables Continuous
Reception
TXSTAbits.TXEN = 1; //Enables Transmission
GIE = 1; // ENABLE interrupts
INTCONbits.PEIE = 1; // ENable peripheral interrupts.
PIE1bits.RCIE = 1; // ENABLE USART receive interrupt
PIE1bits.TXIE = 0; // disable USART TX interrupt
PIR1bits.RCIF = 0;

}
void serialwrite(char ch)
{
while(TXIF==0); // Wait till the transmitter register becomes empty
TXIF=0; // Clear transmitter flag
TXREG=ch; // load the char to be transmitted into transmit reg
}
serialprint(char *str)
{
while(*str)
{
serialwrite(*str++);
}
}
void interrupt SerialRxPinInterrupt(void)
{
if((PIR1bits.RCIF == 1) && (PIE1bits.RCIE == 1))
{
uchar ch=RCREG;
buf[index++]=ch;
if(index>0)
flag=1;
RCIF = 0; // clear rx flag
}
}
void serialFlush()
{
for(int i=0;i<sizeof(buf);i++)
{
buf[i]=0;
}
}
int sendcmd2fp(char *pack, int len)
{
uint res=ERROR;
serialFlush();
index=0;
__delay_ms(100);
for(int i=0;i<len;i++)
{
serialwrite(*(pack+i));
}
__delay_ms(1000);
if(flag == 1)
{
if(buf[0] == 0xEF && buf[1] == 0x01)
{
if(buf[6] == 0x07) // ack
{
if(buf[9] == 0)
{
uint data_len= buf[7];
data_len<<=8;
data_len|=buf[8];
for(int i=0;i<data_len;i++)
data[i]=0;
for(int i=0;i<data_len-2;i++)
{
data[i]=buf[10+i];
}
res=PASS;
}
else
{
res=ERROR;
}
}
}
index=0;
flag=0;
return res;
}
}
uint getId()
{
uint id=0;
lcdwrite(1, CMD);
while(1)
{
lcdwrite(0x80, CMD);
checkKey(id);
sprintf(buf1,"Enter Id:%d ",id);
lcdprint(buf1);
__delay_ms(200);
if(ok == LOW)
return id;
}
}
void matchFinger()
{
lcdwrite(1,CMD);
lcdprint("Place Finger");
lcdwrite(192,CMD);
__delay_ms(2000);
if(!sendcmd2fp(&f_detect[0],sizeof(f_detect)))
{
if(!sendcmd2fp(&f_imz2ch1[0],sizeof(f_imz2ch1)))
{
if(!sendcmd2fp(&f_search[0],sizeof(f_search)))
{
lcdwrite(1,CMD);
lcdprint("Finger Found");
uint id= data[0];
id<<=8;
id+=data[1];
uint score=data[2];
score<<=8;
score+=data[3];
sprintf(buf1,"Id:%d Score:%d",id,score);
lcdwrite(192,CMD);
lcdprint(buf1);
LED=1;
__delay_ms(1000);
LED=0;
}

else
{
lcdwrite(1,CMD);
lcdprint("Not Found");
}
}
}

else
{
lcdprint("No Finger");
}
__delay_ms(2000);
}
void enrolFinger()
{
lcdwrite(1,CMD);
lcdprint("Enroll Finger");
__delay_ms(2000);
lcdwrite(1,CMD);
lcdprint("Place Finger");
lcdwrite(192,CMD);
__delay_ms(1000);
if(!sendcmd2fp(&f_detect[0],sizeof(f_detect)))
{
if(!sendcmd2fp(&f_imz2ch1[0],sizeof(f_imz2ch1)))
{
lcdprint("Finger Detected");
__delay_ms(1000);
lcdwrite(1,CMD);
lcdprint("Place Finger");
lcdwrite(192,CMD);
lcdprint(" Again ");
__delay_ms(2000);
if(!sendcmd2fp(&f_detect[0],sizeof(f_detect)))
{
if(!sendcmd2fp(&f_imz2ch2[0],sizeof(f_imz2ch2)))
{
lcdwrite(1,CMD);
lcdprint("Finger Detected");
__delay_ms(1000);
if(!sendcmd2fp(&f_createModel[0],sizeof(f_createModel)))
{
id=getId();
f_storeModel[11]= (id>>8) & 0xff;
f_storeModel[12]= id & 0xff;
f_storeModel[14]= 14+id;
if(!sendcmd2fp(&f_storeModel[0],sizeof(f_storeModel)))
{
lcdwrite(1,CMD);
lcdprint("Finger Stored");
sprintf(buf1,"Id:%d",id);
lcdwrite(192,CMD);
lcdprint(buf1);
__delay_ms(1000);
}

else
{
lcdwrite(1,CMD);
lcdprint("Finger Not Stored");
}
}
else
lcdprint("Error");
}
else
lcdprint("Error");
}
else
lcdprint("No Finger");
}
}
else
{
lcdprint("No Finger");
}
__delay_ms(2000);
}
void deleteFinger()
{
id=getId();
f_delete[10]=id>>8 & 0xff;
f_delete[11]=id & 0xff;
f_delete[14]=(21+id)>>8 & 0xff;
f_delete[15]=(21+id) & 0xff;
if(!sendcmd2fp(&f_delete[0],sizeof(f_delete)))
{
lcdwrite(1,CMD);
sprintf(buf1,"Finger ID %d ",id);
lcdprint(buf1);
lcdwrite(192, CMD);
lcdprint("Deleted Success");

}
else
{
lcdwrite(1,CMD);
lcdprint("Error");
}
__delay_ms(2000);
}

int main()
{
void (*FP)();
ADCON1=0b00000110;
LEDdir= 0;
SWPORTdir=0xF0;
SWPORT=0x0F;
serialbegin(57600);
LCDPORTDIR=0x00;
TRISE=0;
lcdbegin();
lcdprint("Fingerprint");
lcdwrite(192,CMD);
lcdprint("Interfacing");
__delay_ms(2000);
lcdwrite(1,CMD);
lcdprint("Using PIC16F877A");
lcdwrite(192,CMD);
lcdprint("Helloworld");
__delay_ms(2000);
index=0;
while(sendcmd2fp(&passPack[0],sizeof(passPack)))
{
lcdwrite(1,CMD);
lcdprint("FP Not Found");
__delay_ms(2000);
index=0;
}
lcdwrite(1,CMD);
lcdprint("FP Found");
__delay_ms(1000);
lcdinst();
while(1)
{
FP=match<enrol?matchFinger:enrol<delet?enrolFinger:delet<enrol?
deleteFinger:lcdinst;
FP();
}
return 0;
}

◆ ◆ ◆
9. RFID INTERFACING
WITH PIC
MICROCONTROLLER
RFID represents Radio Frequency Identification. RFID module can peruse or
compose limited quantity of information into a Passive RFID tag, which can
be utilized in recognizable proof procedure in different frameworks like
Attendance framework, security framework, casting a ballot framework and
so forth. RFID is exceptionally helpful and simple innovation.
To peruse the Passive RFID cards and tag, we need a microcontroller with
UART equipment. In the event that we select a microcontroller without
UART, we have to actualize programming UART. Here we are utilizing PIC
Microcontroller PIC16F877A for interfacing RFID. We will just peruse the
extraordinary distinguishing proof no. of RFID labels and show it on 16x2
Liquid Crystal Display.

RFID module and its Working

In this undertaking, we picked EM-18 RFID module, which is little


estimated, ease, and force proficient module. EM-18 RFID module utilize
125 KHz RF recurrence to peruse detached 125 KHz RFID labels. EM-18
module use Oscillator, demodulator and information decoder to peruse
information from a uninvolved card.

RFID Tag

There are three sorts of RFID labels accessible, Passive, Active otherwise
Battery-helped inactive. Distinctive sort of RFID labels with an alternate sort
of shapes along with sizes are accessible in the market. Not many utilize
distinctive recurrence for correspondence reason. We will utilize 125Khz
Passive RFID cards which holds the one of a kind ID information. Here are
the RFID card and labels we are utilizing for this task.

Working of RFID

On the off chance that we see the datasheet


(http://www.alselectro.com/documents/rfid-ttl-em18.pdf) of EM-18 Module
we could view the rear of the module and the application circuit:
The module utilizes UART correspondence convention in 9600 Baud rate. At
the point when a Valid recurrence tag is brought into the attractive field of the
EM-18 peruser, the BC557 transistor jumps on and the bell will begin
blaring, it likewise shines the LED. We are utilizing a module which is
effectively accessible in the market and has total hardware with a signal,
drove, and an extra RS232 port.
Here is the RFID board module we are utilizing with pin names. This module
likewise has extra force choice.
One thing should be remembered that the yield of EM-18 peruser utilizes 5V
rationale level. We could utilize another microcontroller which utilizes a
lower rationale level, however in such cases, the extra rationale level
converter is required. In hardly any cases, the UART pin of the 3.3V
microcontroller is regularly 5V open minded.
The UART yield gives 12-piece ASCII information. Initial 10 bits are RFID
label number, which is a kind ID and last two digits are utilized for mistake
testing. Those last two digits are the XOR of the label number. EM-18
module will peruse the information from 125 KHz Passive RFID labels or
cards.
Those labels or IDs have a manufacturing plant modified memory exhibit
which stores the extraordinary ID number. As those are inactive, so no
battery is available in the card otherwise labels, they get empowered by the
attractive field of the RF Transceiver module. These RFID labels are made
utilizing the EM4102 CMOS IC which is timed by the attractive field as well.

Material Required

To make this undertaking we need following things

PIC16F877A

20Mhz Crystal

2pcs 33pF artistic plate capacitor

16x2 Character LCD

A breadboard

10k preset pot

4.7k resistor

Single strand wires to associate

A 5V connector

RF Module EM-18

5V Buzzer

100uF and .1uF 12V capacitor

BC557 Transistor

Driven

2.2k and 470R resistor.

We are utilizing the EM-18 module board with bell and drove preconfigured.
In this way, the segments recorded from 11 to 15 are not required.
Circuit Diagram

The schematic is basic; we associated LCD across port RB and associated the
EM-18 module over the UART Rx pin.
We have made the association on breadboard as indicated by schematic.
Code Explanation

As usual, first we have to set the arrangement bits in the pic microcontroller,
characterize a few macros, including libraries and gem recurrence. You can
check code for every one of those in the total code given toward the end.

// PIC16F877A Configuration Bit Settings

// 'C' source line config statements

// CONFIG

#pragma config FOSC = HS // Oscillator Selection bits (HS


oscillator)

#pragma config WDTE = OFF // Watchdog Timer Enable bit


(WDT disabled)

#pragma config PWRTE = OFF // Power-up Timer Enable bit


(PWRT disabled)

#pragma config BOREN = ON // Brown-out Reset Enable bit


(BOR enabled)

#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-


Circuit Serial Programming Enable bit (RB3/PGM pin has PGM
function; low-voltage programming enabled)

#pragma config CPD = OFF // Data EEPROM Memory Code


Protection bit (Data EEPRO

M code protection off)

#pragma config WRT = OFF // Flash Program Memory Write


Enable bits (Write protection off; all program memory may be
written to by EECON control)

#pragma config CP = OFF // Flash Program Memory Code


Protection bit (Code protection off)

#include "supporing_cfile\lcd.h"

#include "supporing_cfile\eusart1.h"

In the event that we see the principle work we called a capacity to instate the
framework. We introduce LCD and UART in this capacity.

/*

This Function is for system initializations.

*/

void system_init(void){

TRISB = 0x00; //PORT B set as output pin

lcd_init(); // This will initialize the lcd

EUSART1_Initialize(); // This will initialize the Eusart

Presently, in the primary capacity, we utilized a 13 piece exhibit which is


RFID Number. We get each piece of the RFID no. utilizing
EUSART1_Read(); work, which is proclaimed within the UART library. In
the wake of getting 12bits, we print the Array as string in the LCD.

void main(void) {
unsigned char count;

unsigned char RF_ID[13];

system_init();

lcd_com(0x80);

lcd_puts("Helloworld");

while (1){

for (count=0; count<12; count++){

RF_ID[count] = 0;

RF_ID[count]=EUSART1_Read();

lcd_com(0xC0); // Set the cursor for second line beginning

lcd_puts("ID: ");

lcd_puts(RF_ID);

Complete code is given beneath.


Likewise check interfacing RFID with other Microcontroller:

RFID Interfacing with MSP430 Launchpad


RFID Interfacing with 8051 Microcontroller

RFID Interfacing with Arduino

Code
/*
* File: main.c
*/
// PIC16F877A Configuration Bit Settings
// 'C' source line config statements
// CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT
disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT
disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR
enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit
Serial Programming Enable bit (RB3/PGM pin has PGM function; low-
voltage programming enabled)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection
bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable
bits (Write protection off; all program memory may be written to by EECON
control)
#pragma config CP = OFF // Flash Program Memory Code Protection
bit (Code protection off)
#include <xc.h>
#include <stdio.h>
#include <string.h>
#include "supporing_cfile\lcd.h"
#include "supporing_cfile\eusart1.h"
/*
Hardware related definition
*/
#define _XTAL_FREQ 200000000 //Crystal Frequency, used in delay
/*
Other Specific definition
*/
void system_init(void); // This will initialize the system.
void main(void) {
unsigned char count;
unsigned char RF_ID[13];
system_init();
lcd_com(0x80);
lcd_puts("Hello world");
while (1){
for (count=0; count<12; count++){
RF_ID[count] = 0;
RF_ID[count]=EUSART1_Read();
}
lcd_com(0xC0); // Set the cursor for second line begining
lcd_puts("ID: ");
lcd_puts(RF_ID);
}
}
/*
This Function is for system initializations.
*/
void system_init(void){
TRISB = 0x00; //PORT B set as output pin
lcd_init(); // This will initialize the lcd
EUSART1_Initialize(); // This will initialize the Eusart
}

◆ ◆ ◆
10. INTERFACING 74HC595
SERIAL SHIFT REGISTER
WITH PIC
MICROCONTROLLER
There are conceivable outcomes in inserted plan where you need more I/O
pins accessible in your microcontroller. That can be because of any
explanation, might be your application needs numerous LEDs or you require
to utilize different 7-portion shows, yet you don't have required I/O sticks in
your microcontroller. Here comes an ideal segment, move register. Move
register acknowledges sequential information and give equal yield. It's
requires just 3 pins to associate with your microcontroller and you will get in
excess of 8 Output pins from it. One of the famous move register is
74HC595. It has 8 piece stockpiling register and 8 piece move register. Get
familiar with move enlists here.
You will give sequential information to the move register and it will be
locked on the capacity register and afterward the capacity register will control
the 8 yields. In case you need more yield simply include another move
register. By falling two move registers, you will get extra 8 yields, all out
16bit yield.

Move Register 74HC595:

Here is the pin out chart of the 74HC595 according to the datasheet-
HC595 has 16pins; in the event that we see the datasheet we will comprehend
the pin capacities

The QA to QH, from pin numbers 1 to 7 and 15 utilized as 8 piece yield from
the move register, where as the pin 14 is utilized for accepting the sequential
information. There is likewise truth table about how to utilize different pins
and benefit different elements of the move register.
At the point when we compose the code for interfacing the 74HC595, we will
apply this fact table for getting the ideal yields.
Presently, we will interface 74HC595 with PIC16F877A along with manage
eight Light Emitting Diodes. We have interfaced 74HC595 move register
with different microcontrollers:

Interfacing 74HC595 Serial Shift Register with Raspberry Pi

How to Use Shift Register 74HC595 with Arduino Uno?

Interfacing LCD with NodeMCU utilizing shift Register

Parts Required:

PIC16F877A

2pcs 33pF earthenware circle capacitors

20Mhz Crystal

4.7k resistor
8pcs LEDs

1k resistor - 1 pc (8 pcs 1k resistors required if separate resistors


on every drove required)

74HC595 ic

5V divider connector

PIC programming condition

Breadboard and wires

Circuit Diagram:

In circuit outline, we have associated the sequential information pin; clock


and strobe (lock) nail to microcontroller's RB0, RB1 along with RB2 pin
separately. Here we have utilized one resistor for eight Light Emitting
Diodes. According to reality table, we empowered yield by associating the
pin 13 of 74HC595 to ground. The QH pin is left open as we won't course
another 74HC595 with it. We handicapped the reasonable information banner
by interfacing pin 10 of the move register with VCC.
The Crystal oscillator is combined on the OSC pins of the microcontroller.
PIC16F877A don't have any inward oscillator. In this venture we will
illuminate the drove individually from Q0 to Q7 utilizing shift regitster.

We have built the circuit in a breadboard-

Code Explanation:
Complete code for controlling LEDs with move register is given toward the
finish of article. As usual, we have to set the arrangement bits in the PIC
microcontroller.

#pragma config FOSC = HS // Oscillator Selection bits (HS


oscillator)

#pragma config WDTE = OFF // Watchdog Timer Enable bit


(WDT disabled)

#pragma config PWRTE = OFF // Power-up Timer Enable bit


(PWRT disabled)

#pragma config BOREN = ON // Brown-out Reset Enable bit


(BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-
Circuit Serial Programming Enable bit (RB3/PGM pin has PGM
function; low-voltage programming enabled)

#pragma config CPD = OFF // Data EEPROM Memory Code


Protection bit (Data EEPROM code protection off)

#pragma config WRT = OFF // Flash Program Memory Write


Enable bits (Write protection off; all program memory may be
written to by EECON control)

#pragma config CP = OFF // Flash Program Memory Code


Protection bit (Code protection off)

After that we pronounced the precious stone recurrence which is required for
the postponement and the pin-out affirmation for 74HC595.

#include <xc.h>

/*

Hardware related definition

*/

#define _XTAL_FREQ 20000000 //Crystal Frequency, used in delay

#define DATA_595 PORTBbits.RB0

#define STROBE_595 PORTBbits.RB1

#define CLK_595 PORTBbits.RB2

Next we proclaimed system_init() capacity to introduce the pin course.


void system_init(void){

TRISB = 0x00;

We made the clock heartbeat and lock beat utilizing two distinct capacities

/*

*This function will enable the Clock.

*/

void clock(void){

CLK_595 = 1;

__delay_us(500);

CLK_595 = 0;

__delay_us(500);

what's more,

/*

*This function will strobe and enable the output trigger.

*/
void strobe(void){

STROBE_595 = 1;

__delay_us(500);

STROBE_595 = 0;

After this two capacities we announced the data_submit(unsigned int


information) capacity to submit sequential information to the 74HC595.

void data_submit(unsigned int data){

for (int i=0 ; i<8 ; i++){

DATA_595 = (data >> i) & 0x01;

clock();

strobe(); // Data finally submitted

In this capacity we acknowledge 8bit information and send each piece


utilizing two bitwise administrators left move AND administrator. We first
move the information individually and discover the specific piece whether it
is 0 or 1 utilizing AND administrator with 0x01. Every datum is put away by
the clock heartbeat and last information yield done utilizing the hook or
strobe beat. In this procedure the information yield will be (Most Significant
Bit) first.
In the fundamental capacity we presented the double and made the yield
sticks high individually.

system_init(); // System getting ready

while(1){

data_submit(0b00000000);

__delay_ms(200);

data_submit(0b10000000);

__delay_ms(200);

data_submit(0b01000000);

__delay_ms(200);

data_submit(0b00100000);

__delay_ms(200);

data_submit(0b00010000);

__delay_ms(200);

data_submit(0b00001000);

__delay_ms(200);

data_submit(0b00000100);

__delay_ms(200);
data_submit(0b00000010);

__delay_ms(200);

data_submit(0b00000001);

__delay_ms(200);

data_submit(0xFF);

__delay_ms(200);

return;

That is the means by which a move register can be utilized to get all the more
free I/O sticks in any microcontroller for interfacing more sensors.

Code
/*
* File: main.c
*/
// PIC16F877A Configuration Bit Settings
// 'C' source line config statements
// CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT
disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT
disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR
enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit
Serial Programming Enable bit (RB3/PGM pin has PGM function; low-
voltage programming enabled)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection
bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable
bits (Write protection off; all program memory may be written to by EECON
control)
#pragma config CP = OFF // Flash Program Memory Code Protection
bit (Code protection off)
#include <xc.h>
/*
Hardware related definition
*/
#define _XTAL_FREQ 20000000 //Crystal Frequency, used in delay
#define DATA_595 PORTBbits.RB0
#define STROBE_595 PORTBbits.RB1
#define CLK_595 PORTBbits.RB2
#define LED PORTBbits.RB3
/*
Other Specific definition
*/
void system_init(void);
/*
*This function will enable the Clock.
*/
void clock(void){
CLK_595 = 1;
__delay_us(500);
CLK_595 = 0;
__delay_us(500);
}
/*
*This function will strobe and enable the output trigger.
*/
void strobe(void){
STROBE_595 = 1;
__delay_us(500);
STROBE_595 = 0;
}
/*
* This function will send the data to shift register
*/
void data_submit(unsigned int data){
for (int i=0 ; i<8 ; i++){
DATA_595 = (data >> i) & 0x01;
clock();
}
strobe(); // Data finally submitted
}
void main(void) {
system_init(); // System getting ready
while(1){
data_submit(0b00000000);
__delay_ms(200);
data_submit(0b10000000);
__delay_ms(200);
data_submit(0b01000000);
__delay_ms(200);
data_submit(0b00100000);
__delay_ms(200);
data_submit(0b00010000);
__delay_ms(200);
data_submit(0b00001000);
__delay_ms(200);
data_submit(0b00000100);
__delay_ms(200);
data_submit(0b00000010);
__delay_ms(200);
data_submit(0b00000001);
__delay_ms(200);
data_submit(0xFF);
__delay_ms(200);
}
return;
}

/*
This Function is for system initialisations.
*/
void system_init(void){
TRISB = 0x00;
}
THANK YOU

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy