PIC Microcontroller Projects Handson
PIC Microcontroller Projects Handson
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
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
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.
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
Breadboard
1k resistor
PIC16F877A
DHT11 sensor
Jumper wires
Schematic
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.
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(){
__delay_ms(18);
__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;
while(!DHT11_Data_Pin);
__delay_us(30);
if(DHT11_Data_Pin == 0){
else{
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(0xDF);
lcd_puts("C ");
lcd_com (0xC0);
lcd_puts("Humidity: ");
//lcd_puts(" ");
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.
Bit 15 DACA 0
Bit 14 Unbuffered 0
Bit 13 1x(VOUT*D/4096) 1
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
MCP4921
PIC16F877A
20 MHz Crystal
2k resistor - 1 pc
4.7k resistor - 1 pc
A breadboard
Schematic
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.
// CONFIG
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"
/*
*/
while (!SSPSTATbits.BF);
*/
container = value;
LSB = container/256;
/*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*/
SPI_Write(LSB);
SPI_Write(MSB);
DAC_CS = 1;
void main() {
system_init();
introduction_screen();
int number=0;
int volt=0;
while (1) {
clear_screen();
lcd_com(FIRST_LINE);
lcd_print_number(number);
lcd_com(SECOND_LINE);
lcd_puts("Output:- ");
lcd_print_number(volt);
lcd_puts("V");
convert_DAC(number);
__delay_ms(300);
}
}
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.
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.
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.05 msec
So now we have set the clock to flood at each 0.05ms. The code to do the
equivalent is given beneath
/***********______***********/
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.
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.
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:");}
Lcd_Print_Char(d1+'0');Lcd_Print_Char(d2+'0');
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
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
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.
count=0;
else
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.
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.
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.
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.
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
}
while(1)
{
for (int pot_num=0; pot_num<=3; pot_num++)
{
int Pev_val = T_ON[pot_num];
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:");}
}
}
◆ ◆ ◆
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...
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.
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
PIC16F877A
4.7k resistor
1k resistor
10k pot
16x2 Display
Rotational Encoder
5V connector.
Bread Board
Hookup wires.
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);
lcd_com (0xC0);
lcd_puts(" ");
lcd_com (0xC0);
lcd_bcd(1,counter);
else{
// lcd_com (0x01);
lcd_com (0xC0);
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.
Other than this an alternative is given to advise about switch push on the
LCD.
if (Encoder_SW == 0){
if (Encoder_SW == 0){
//lcd_com(1);
//lcd_com(0xC0);
// 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(){
TRISDbits.TRISD2 = 1;
TRISDbits.TRISD3 = 1;
TRISCbits.TRISC4 = 1;
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.
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:
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.
Variable Refers to
Name
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.
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
#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.
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
/***********______***********/
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.
/***********______***********/
while(1)
__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
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
else
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
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
}
ADC_Initialize();
while(1)
{
POT_val = (ADC_Read(0)); //Read the value of POT using ADC
◆ ◆ ◆
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
Velcro tie
5V Power connector
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.
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:
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:
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:
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:
This count is giving the 2 milliseconds clock intrude. The figuring recipe is
void timer_isr() {
main_state = READ_ADC;
Signal = adc_value;
………….
………………………..
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.
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
Attach wires
PIC16F877A
680R resistor
Material switch
// CONFIG
#include <xc.h>
#include "supporting_cfile\eusart1.h"
/*
* System hardware related macros
*/
void system_init(void);
void main(void) {
system_init();
while(1){
notification_led = 1;
put_string("Hello! \n\r");//Print to Thermal printer
__delay_ms(50);
__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 ("\n\r");
put_string ("\n\r");
notification_led = 0;
}
}
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
10k pot
Jumper wires
Driven (discretionary)
5v Power gracefully
Circuit Diagram and Explanation
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 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.
Programming Explanation
uchar buf[20];
uchar buf1[20];
uint msCount=0;
uint g_timerflag=1;
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};
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};
RS=rw;
EN=1;
__delay_ms(5);
EN=0;
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);
TXSTAbits.TXEN = 1; //Enables
Transmission
PIR1bits.RCIF = 0;
Given capacities are utilized for moving orders to unique mark Module and
getting information from special finger print module.
serialprint(char *str)
{
while(*str)
serialwrite(*str++);
uchar ch=RCREG;
buf[index++]=ch;
if(index>0)
flag=1;
void serialFlush()
{
for(int i=0;i<sizeof(buf);i++)
buf[i]=0;
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[9] == 0)
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:
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);
__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;
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 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
Material Required
PIC16F877A
20Mhz Crystal
A breadboard
4.7k resistor
A 5V connector
RF Module EM-18
5V Buzzer
BC557 Transistor
Driven
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.
// CONFIG
#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.
/*
*/
void system_init(void){
void main(void) {
unsigned char count;
system_init();
lcd_com(0x80);
lcd_puts("Helloworld");
while (1){
RF_ID[count] = 0;
RF_ID[count]=EUSART1_Read();
lcd_puts("ID: ");
lcd_puts(RF_ID);
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.
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:
Parts Required:
PIC16F877A
20Mhz Crystal
4.7k resistor
8pcs LEDs
74HC595 ic
5V divider connector
Circuit Diagram:
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.
After that we pronounced the precious stone recurrence which is required for
the postponement and the pin-out affirmation for 74HC595.
#include <xc.h>
/*
*/
TRISB = 0x00;
We made the clock heartbeat and lock beat utilizing two distinct capacities
/*
*/
void clock(void){
CLK_595 = 1;
__delay_us(500);
CLK_595 = 0;
__delay_us(500);
what's more,
/*
*/
void strobe(void){
STROBE_595 = 1;
__delay_us(500);
STROBE_595 = 0;
clock();
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