Saturday, March 31, 2018

Interfacing PIC16F877A with DHT22(Temperature and Humidity Sensor )

Description:

These sensors are very popular for electronics hobbyists because there are very cheap but still providing great performance.The DHT22 is the more expensive version which obviously has better specifications. Its temperature measuring range is from -40 to +125 degrees Celsius with +-0.5 degrees accuracy,DHT22 sensor has better humidity measuring range, from 0 to 100% with 2-5% accuracy




















Specification:

Model-: AM2303 
Power supply-: 3.3-6V DC 
Output signal-: digital signal via single-bus 
Sensing element-: Polymer humidity capacitor & DS18B20 for detecting temperature 
Measuring range-: humidity 0-100%RH; temperature -40~125Celsius
Accuracy humidity-: +-2%RH(Max +-5%RH); temperature +-0.2Celsius 
Resolution or sensitivity-: humidity 0.1%RH; temperature 0.1Celsius 
Repeatability-: humidity +-1%RH; temperature +-0.2Celsius 
Humidity hysteresis--: +-0.3%RH 
Long-term Stability--: +-0.5%RH/year 
Sensing period-: Average: 2s 
Interchangeability-: fully interchangeable


Circuit Diagram:



















MikroC Code:

//Interfacing PIC16F877A with DHT22
//Crystal used @ 12MHz
 sbit LCD_RS at RB0_bit;
 sbit LCD_EN at RB1_bit;
 sbit LCD_D4 at RB2_bit;
 sbit LCD_D5 at RB3_bit;
 sbit LCD_D6 at RB4_bit;
 sbit LCD_D7 at RB5_bit;
 sbit LCD_RS_Direction at TRISB0_bit;
 sbit LCD_EN_Direction at TRISB1_bit;
 sbit LCD_D4_Direction at TRISB2_bit;
 sbit LCD_D5_Direction at TRISB3_bit;
 sbit LCD_D6_Direction at TRISB4_bit;
 sbit LCD_D7_Direction at TRISB5_bit;
 // End LCD module connections

 unsigned char  Check, T_byte1, T_byte2, RH_byte1, RH_byte2, Ch ;
 unsigned Temp, RH, Sum ;
 unsigned be, me,ne, Sum2,h1,h2 ;

//////////////////////////////
 void StartSignal(){
 TRISD.F0 = 0;    //Configure RD0 as output
 PORTD.F0 = 0;    //RD0 sends 0 to the sensor
 delay_ms(18);
 PORTD.F0 = 1;    //RD0 sends 1 to the sensor
 delay_us(30);
 TRISD.F0 = 1;    //Configure RD0 as input
  }
 //////////////////////////////
 void CheckResponse(){
 Check = 0;
 delay_us(40);
 if (PORTD.F0 == 0){
 delay_us(80);
 if (PORTD.F0 == 1)   Check = 1;   delay_us(40);}
 }
 //////////////////////////////
 char ReadData(){
 char i, j;
 for(j = 0; j < 8; j++){
 while(!PORTD.F0); //Wait until PORTD.F0 goes HIGH
 delay_us(30);
 if(PORTD.F0 == 0)
       i&= ~(1<<(7 - j));  //Clear bit (7-b)
 else {i|= (1 << (7 - j));  //Set bit (7-b)
 while(PORTD.F0);}  //Wait until PORTD.F0 goes LOW
 }
 return i;
 }
 //////////////////////////////

 void main() {
 TRISC = 0;    //Configure RC0 as output
 Lcd_Init();
 Lcd_Cmd(_LCD_CURSOR_OFF);        // cursor off
 Lcd_Cmd(_LCD_CLEAR);             // clear LCD
 while(1){
  StartSignal();
  CheckResponse();
  if(Check == 1){
  RH_byte1 = ReadData();
  RH_byte2 = ReadData();
  T_byte1 = ReadData();
  T_byte2 = ReadData();
  Sum = ReadData();
  if(Sum == ((RH_byte1+RH_byte2+T_byte1+T_byte2) & 0XFF)){
  Temp = T_byte1;
  Temp = (Temp << 8) | T_byte2;
  RH = RH_byte1;
  Lcd_Cmd(_LCD_CLEAR);             // clear LCD
  RH = (RH << 8) | RH_byte2;
  Lcd_Out(1, 6, "Temp:   . C");
  Lcd_Out(2, 2, "Humidity:   . %");
  if (Temp > 0X8000){
  Lcd_Out(1, 11, "-");
  Temp = Temp & 0X7FFF; }
  be=(48 + ((Temp / 100) % 10));//work for frist later of temperature like 2 than 22,,23,
  LCD_Chr(1, 12, be);
  me= (48 + ((Temp / 10) % 10));
  LCD_Chr(1, 13, me);
  ne=48 + (Temp % 10);
  LCD_Chr(1, 15, ne); //after (.) number 
 
 //for humidity
  h1=  48 + ((RH / 100) % 10);
  LCD_Chr(2, 12, h1);
  h2= 48 + ((RH / 10) % 10);
  LCD_Chr(2, 13, h2);
  LCD_Chr(2, 15, 48 + (RH % 10));
  /////////////////////////////////////////////////

    if(be==51 & me==55 & ne>53){ // more then 26*C   relay 
    DELAY_MS(500);
     portc.f0=0;

      }
    if(be<52 & me<56 & ne<52 ){  // less then 26*C
     portc.f0=1;

    }
    if (h1>53 & h2>52)  // for humidity control relay 
    {
    portc.f1 =0;
    }
    if(h1<54 & h2<49)
    {
    portc.f1=1;
    }

   }
  else {
  Lcd_Cmd(_LCD_CURSOR_OFF);        // cursor off
  Lcd_Cmd(_LCD_CLEAR);             // clear LCD
  Lcd_Out(1, 1, "Check sum error");}
  }
  else {
  Lcd_Out(1, 3, "No response");
  Lcd_Out(2, 1, "from the sensor");
  }
  delay_ms(1000);
  }
  }

Tuesday, March 13, 2018

Analog to Digital Converter with PIC Microcontroller (PIC16F877A)

Why need ADC? !!!!













ADC pins of PIC16F877A














Features of PIC16F877A ADC:

  • 10-bit 8 channels analogue input ADC
  • ±2 LSB absolute accuracy
  • Up to 15 KSPS at Maximum Resolution
  • 0-Vcc ADC input votage range 
  • Reference Voltage can be configured as Avcc, AREF or 2.56 Volts
  • Sleep Mode Noise Canceller. 

What is Resolution?

  • The smallest change that can be detected in the measuring voltage.
  • 10 Bit resolution provide 210 =1024 steps.
  • Vcc = 5Volt
  • Step Size(mV) = 5/1024 = 4.88

Conversion Time:

  • Conversion time is defined as the time an ADC takes to convert the analogue input into the digital (binary) output.
  • The conversion time depends on -MCU clock source.

ADC Timings:


  • Startup time: should be considered when the ADC has been enabled either for the first time or after a wake up from some of the sleep modes.
  • Sample and hold time: This time must be considered carefully especially when multiple channels are used during conversion.

The A/D converter module has the following features:

      The converter generates a 10-bit binary result using the method of successive approximation and stores the conversion results into the ADC registers (ADRESL and ADRESH). There are 14 separate analog inputs; The A/D converter converts an analog input signal into a 10- bit  binary number. The minimum resolution or quality of conversion may be adjusted to various needs by selecting voltage referances Vref- and Vref+.












ADC programming in PIC16F877A:

          The A/D module has four registers. These registers are:
  • A/D Result High Register (ADRESH)
  • A/D Result Low Register (ADRESL)
  • A/D Control Register 0 (ADCON0)
  • A/D Control Register 1 (ADCON1)













ADRESH and ADRESL Registers:


The result obtained after converting an analog value into digital is a10-bit number that is to be stored in the ADRESH and ADRESL registers. There are two ways of handling it – left and right justification which simplifies its use to a great extent. The format of conversion result depends on the ADFM bit of the ADCON1 register. In the event that the A/D converter is not used, these registers may be used as general-purpose registers.













ADCON0 Register:







ADCS1, ADCS0 – A/D Conversion Clock Select bits select clock frequency used for internal synchronization of A/D converter. It also affects duration of conversion.
CHS3-CHS0 – Analog Channel Select bits select a pin or an analog channel for A/D conversion, i.e. voltage measurement:
GO/DONE – A/D Conversion Status bit determines current status of conversion:
1 – A/D conversion is in progress.
0 – A/D conversion is complete. This bit is automatically cleared by hardware when the A/D conversion is complete.

ADON – A/D On bit enables A/D converter.
1 – A/D converter is enabled.

0 – A/D converter is disabled.

ADCON1 Register:

















To do an A/D Conversion, follow these steps:

Step 1 --Configure the A/D module:

  • Configure analog pins/voltage reference and digital I/O(ADCON1)
  • Select A/D input channel (ADCON0)
  • Select A/D Conversion clock (ADCON0)
  • Turn on A/D module (ADCON0)
  • Select one of input channels CH0-CH13 of the ADCON0 register
  • Select data format using the ADFM bit of the ADCON1 register.
  •  Enable A/D converter by setting the ADON bit of the ADCON0 register.
Step 2 – ADC interrupt configuration (optionally):
                Clear the ADIF bit.
                Set the ADIE, PEIE and GIE bits.
Step 3 – Wait for the required acquisition time to pass (approximately 20uS).
Step 4 – Start conversion by setting the GO/DONE bit of the ADCON0 register.
Step 5 – Wait for ADC conversion to complete.
                It is necessary to check in the program loop whether the GO/DONE pin is cleared or wait                      for an A/D interrupt (must be previously enabled).
Step 6 – Read ADC results:
                Read the ADRESH and ADRESL registers.



Circuit Diagram:







REMEMBER !!!!

  • The AVCC and VREF should be constant. If they vary, the accuracy of ADC conversion will be affected.
  • Input must not exceed VCC
  • Signal components higher than the Nyquist frequency (fADC/2) should not be present for either kind of channels, to avoid distortion from unpredictable signal convolution.

Basic code:

Define CONF_WORD = 0x3f72
Define CLOCK_FREQUENCY = 12
AllDigital
ADCON1 = 0x0e
Define LCD_BITS = 8
Define LCD_DREG = PORTD
Define LCD_DBIT = 0
Define LCD_RSREG = PORTE
Define LCD_RSBIT = 0
Define LCD_RWREG = PORTE
Define LCD_RWBIT = 1
Define LCD_EREG = PORTE
Define LCD_EBIT = 2
Define LCD_READ_BUSY_FLAG = 1
Lcdinit
Dim an0 As Word
loop:
  Adcin 0, an0
  Lcdcmdout LcdClear
  Lcdout "Analog input AN0"
  Lcdcmdout LcdLine2Home
  Lcdout "Value: ", #an0
  WaitMs 250
Goto loop

C Code


// LCD module connections
 sbit LCD_RS at RD0_bit;
 sbit LCD_EN at RD1_bit;
 sbit LCD_D4 at RD4_bit;
 sbit LCD_D5 at RD5_bit;
 sbit LCD_D6 at RD6_bit;
 sbit LCD_D7 at RD7_bit;
sbit LCD_RS_Direction at TRISD0_bit;
sbit LCD_EN_Direction at TRISD1_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
 // End LCD module connections

int adc;
char adc_con[7];

void main()
{
ADCON0 = 0x41; //ADC Module Turned ON and Clock is selected
ADCON1 = 0xC0; //All pins as Analog Input
TRISA.RA0=1;      // Configure RA0 pin as input
ADC_Init();         // Initialize ADC
Lcd_Init();          // Initialize LCD
Lcd_Cmd(_LCD_CLEAR);    // Clear display
lcd_cmd(_LCD_CURSOR_OFF);
lcd_out(1,1,"ADC Reading");
delay_ms(1000);             // 1 Second delay
Lcd_Cmd(_LCD_CLEAR);  // Clear display

while(1)
{
adc = ADC_Read(0);          // Get 10-bit results of AD conversion
IntToStr(adc, adc_con);               // Convert temperature to string
lcd_out(1,1,"ADC Valu=");
Lcd_Out(1, 10, adc_con);                   // Display Temperature
 Delay_ms(500);                     // 1 Second delay
}
}

Circuit Diagram:



Sunday, March 4, 2018

How to Interface 16x2 LCD with PIC Microcontroller (PIC16F877A)

Liquid Crystal Display











This component is specifically manufactured to be used with microcontrollers, which means that it cannot be activated by standard IC circuits. It is used for displaying different messages on a miniature liquid crystal display. The model described here is for its low price and great capabilities most frequently used in practice. It is based on the HD44780 microcontroller (Hitachi) and can display messages in two lines with 16 characters each. It displays all the letters of alphabet, Greek letters, punctuation marks, mathematical symbols etc. In addition, it is possible to display symbols made up by the user. Other useful features include automatic message shift (left and right), cursor

Inside the Display Controller
CG ROM stores segment patterns of 192 char
CG RAM stores segment patterns for 16-user designed characters.
An 8-bit instruction register
An 8-bit data register
DD RAM stores 80 numbers of 8-bit character codes 
11 instructions
To clear display
To write a character
To select a position
--To read information from the display, etc.

LCD Memory

LCD display contains three memory blocks:
DRAM – Display Data RAM;
CGRAM – Character Generator RAM; and
CGROM – Character Generator ROM.

DDRAM Memory








DDRAM memory is used for storing characters that should be displayed.
 The size of this memory is sufficient for storing 80 characters.
Some memory locations are directly connected to the characters on display.
It works quite simply: it is enough to configure the display to increment addresses
 automatically (shift right) and set the starting address for the message that should be
displayed (for example 00 hex).
After that, all characters sent through lines D0-D7 will be displayed as a message format
 we are used to- from left to right. In this very case, displaying starts from the first field
of the first line because the address is 00 hex. If more than 16 characters are sent then all
of them will be memorized, but only the first sixteen characters will be visible. In order to
 display the rest of them, a shift command should be used. Virtually, everything looks as if
 the LCD display is a window which shifts left-right over memory locations containing
 different characters. In reality, this is how the effect of message shifting on the screen
 has been created.

CGROM Memory

CGROM memory contains the default character map with all characters that can be displayed on the screen. Each character is assigned to one memory location:


What is Busy flag ?

Compared to the microcontroller, the LCD is an extremely slow component. Because of this, it was necessary to provide a signal which would, upon command execution, indicate that the display is ready for the next piece of data. That signal, called the busy flag, can be read from the line D7. When the voltage on this line is 0V (BF=0), the display is ready to receive new data.

         Pinout:












Commands:













Initializing the LCD for 8-bit operation:

To initialize for 2 lines, 5X7 matrix and 8bit operation the sequence of commandas
0x38,0x0E, and 0x01 should be executed.

If initialization is the first command in your code wait 15msec just after power up, if not
it is not necessary.

Sending Commands to the LCD

To send any of the commands, make pin RS and R/W both ‘0’ and  the command code in pin D0-D7
Then send a high-to-low pulse at pin E to enable the internal latch of the LCD 
For each of command you should wait at least 100 usec
But for clearing LCD (code=0x01) and Return home (code=0x02) you should wait for 2 msec

Sending Data to the LCD

To send any of the Data, make pin RS ‘1’ and R/W  ‘0’ and then put data in pin D0-D7
For each of command you should wait at least 100 usec
Then send a high-to-low pulse at pin E to enable the internal latch of the LCD

Sending Code or Data in 4-bit mode

        In 4-bit, we initialize LCD with 0x33, 0x32 and 0x28
The nibble 3, 3, 3 and 2 sets the LCD into 4-bit mode and 0x28 initialize the LCD for 5X7 matrix and 4-bit operation
select command register(RS=0)/Data register(RS=1)
Mask lower 4-bits
Send to the LCD port
Send enable signal
Mask higher 4-bits
Send to LCD port
Send enable signal

The Initial Setting Up for LCD

The LCD module must be connected to the port bits as follows:
 [LCD]             [AVR Port]
  RS (pin4) ------- bit 0
  RD (pin 5) ------ bit 1
  EN (pin 6) ------ bit 2
  DB4 (pin 11) --- bit 4
  DB5 (pin 12) --- bit 5
  DB6 (pin 13) --- bit 6
  DB7 (pin 14) --- bit 7
You must also connect the LCD power supply and contrast control voltage, 
according to the data sheet.

Some of the functions used for LCD

unsigned char lcd_init(unsigned char lcd_columns)
initializes the LCD module, clears the display and sets the printing character position 
at row 0 and column 0. The numbers of columns of the LCD must be specified (e.g. 16). 
No cursor is displayed.
void lcd_clear(void)
clears the LCD and sets the printing character position at row 0 and column 0.
void lcd_gotoxy(unsigned char x, unsigned char y)
sets the current display position at column x and row y. The row and column 
numbering starts from 0.
void lcd_putsf(char flash *str)
displays at the current display position the string str, located in FLASH

8-bit Connection












4-bit Connection
























Depending on how many lines are used for connecting an LCD to the microcontroller, there are 8-bit and 4-bit LCD modes. The appropriate mode is selected at the beginning of the operation in the process called ‘initialization’. The 8-bit LCD mode uses outputs D0- D7 to transfer data as explained on the previous page.
The main purpose of the 4-bit LCD mode is to save valuable I/O pins of the microcontroller. Only 4 higher bits (D4-D7) are used for communication, while others may be left unconnected. Each piece of data is sent to the LCD in two steps- four higher bits are sent first (normally through the lines D4-D7), then four lower bits. Initialization enables the LCD to link and interpret received bits correctly.
Advantages
LED consumes lot of power
Advantages of LCD
-Built in Data Controller
-Consume less power
-Able to display both Alphanumeric and custom Build characters.
-Can be used as a cheap alternative of debugging tools.


Circuit Diagram of Basic Language Program 



Circuit Diagram of C Language Program 






Code of Basic Language:

Define CONF_WORD = 0x3f72
Define CLOCK_FREQUENCY = 12
AllDigital

Define LCD_BITS = 8
Define LCD_DREG = PORTD
Define LCD_DBIT = 0
Define LCD_RSREG = PORTE
Define LCD_RSBIT = 0
Define LCD_RWREG = PORTE
Define LCD_RWBIT = 1
Define LCD_EREG = PORTE
Define LCD_EBIT = 2
Define LCD_READ_BUSY_FLAG = 1

Lcdinit

loop:
Lcdcmdout LcdClear
Lcdout "Hello World "
Lcdcmdout LcdLine2Home
Lcdout "ABCDEFGHIJ"
WaitMs 500

Goto loop

Code of C Language:

// LCD module connections
sbit LCD_RS at RD3_bit;
sbit LCD_EN at RD2_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_RS_Direction at TRISD3_bit;
sbit LCD_EN_Direction at TRISD2_bit;
sbit LCD_D7_Direction at TRISD7_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D4_Direction at TRISD4_bit;
// End LCD module connections


void main() {
TRISC=1;
TRISB=0;
lcd_init();
lcd_cmd(_LCD_CLEAR);
lcd_cmd(_LCD_CURSOR_OFF);
lcd_out(1,1," Hello World");
delay_ms(500);
lcd_out(2,1,"ABCDEFGHIJ");
delay_ms(500);

while(1)
        {}

}