Thursday, December 28, 2023

PIC16F887 HC-SR04 Distance Sensor LCD Using XC8

Overview

HC-SR04 is an ultrasonic range finder. It uses sound wave traveling to find detected object distance. Its working range is between 4cm and 4m. To control and get distance data from this sensor we can use a digital circuit, or a microprocessor, or even manually by hand. Its echo output is a logic high level TTL signal with a specific period. A microprocessor's timer is used for calculating the timing signal associated with distance. For more details about using this sensor with a simple PIC16F84A micro-controller you can see this post.

PIC16F887 HC-SR04 Distance Sensor LCD Using XC8
PIC16F887 Prototyping Board

PIC16F887 HC-SR04 Distance Sensor LCD Using XC8
PIC16F887 Prototyping Board
 
PIC16F887 HC-SR04 Distance Sensor LCD Using XC8
HC-SR04 Module Front

PIC16F887 HC-SR04 Distance Sensor LCD Using XC8
HC-SR04 Module Back

MPLABX IDE and XC8 C Programming

In this XC8 programming example, I use a PIC16F887 8-bit micro-controller to read distance data, and displaying its timing value with calculated distance on a 16x4 character LCD. I use Timer0 timer/counter to measure the sensor's TTL high pulse period.







PIC16F887 HC-SR04 Distance Sensor LCD Using XC8
Schematic and Program Simulation

An 8MHz internal RC oscillator is used for the system. Timer0 prescaler is set to 1:2 to get a 1µs timing ticks. Since this timer module is an 8-bit timer/counter I use TIMER0 interrupt to expand its timing period. Hence it becomes a 16-bit timer with the aid of timing interrupt. 

An 8-bit micro-controller is easy to program using C in MPLABX IDE and XC8 embedded C compiler from Microchip Technology. An HD44780 character LCD is very simple to interface and program. This character LCD is common operate in 4-bit data transfer mode.

  1. /*
  2.  * File: main.c
  3.  * Author: Admin
  4.  *
  5.  * Created on December 28, 2023, 9:51 PM
  6.  */
  7.  
  8. #include <xc.h>
  9. #include "config.h"
  10. #include "lcd.h"
  11.  
  12. #include <stdio.h>
  13.  
  14. #define _XTAL_FREQ 8000000UL
  15.  
  16. #define TRIGGER RD6
  17. #define ECHO RD7
  18.  
  19. volatile uint8_t T0OV=0;
  20. volatile uint16_t myCounter=0;
  21. volatile uint16_t getDistance=0, temp=0;
  22.  
  23. void __interrupt() T0_ISR(){
  24. if(T0IF==1){
  25. T0OV+=1;
  26. myCounter++;
  27. T0IF=0;
  28. }
  29. }
  30.  
  31. void readDistance(void){
  32. char msg[8];
  33. TRIGGER=1;
  34. __delay_us(10);
  35. TRIGGER=0;
  36. __delay_us(30);
  37. while(ECHO==0){
  38. /*Waiting For High Pulse Response, Or Sensor Present*/
  39. temp++;
  40. __delay_us(10);
  41. if(temp>=20) break;
  42. }
  43. TMR0=0;
  44. T0OV=0;
  45. while(ECHO==1);
  46. temp=(T0OV<<8)+TMR0+14;
  47. getDistance=temp/58;
  48.  
  49. lcdXY(5,4);
  50. sprintf(msg,"%4d %cS ",temp,228);
  51. lcdString(msg);
  52. lcdXY(5,2);
  53. if(temp>=116&&getDistance<=400){
  54. sprintf(msg,"%3d",getDistance);
  55. lcdString(msg);
  56.  
  57. temp%=58;
  58. temp=(temp*100)/58;
  59. sprintf(msg,".%d%dcm",temp/10,temp%10);
  60. lcdString(msg);
  61. }else lcdString("Invalid");
  62. temp=0;
  63. T0OV=0;
  64. TMR0=0;
  65. }
  66.  
  67. void main(void) {
  68. /*8MHz internal oscillator*/
  69. OSCCONbits.IRCF=7;
  70. lcdInit();
  71. /*RD7 as input*/
  72. PORTD=0;
  73. TRISD=0x80;
  74. /*Select system clock*/
  75. T0CS=0;
  76. /*Timer0 Prescaler*/
  77. PSA=0;
  78. /*Select 1:2 Prescaler*/
  79. OPTION_REGbits.PS=0;
  80. /*Enable Timer0 Interrupt*/
  81. T0IE=1;
  82. GIE=1;
  83. T0IF=0;
  84.  
  85. lcdXY(5,1);
  86. lcdString("PIC16F887 ");
  87. lcdXY(1,2);
  88. lcdString("HC-SR04 Distance");
  89. lcdXY(2,3); lcdString("Sensor Example");
  90. lcdXY(2,4); lcdString("MPLABX IDE XC8");
  91. __delay_ms(2000);
  92. lcdCommand(0x0C);
  93. lcdCommand(0x01);
  94. __delay_ms(5);
  95. lcdXY(5,1);
  96. lcdString("Distance: ");
  97. lcdXY(1,3);
  98. lcdString("TIMER0 Duration:");
  99. TMR0=0;
  100. while(1){
  101. if(myCounter>=5000){
  102. readDistance();
  103. myCounter=0;
  104. }
  105. }
  106. return;
  107. }
  108.  
  109.  
  110.  

The Interrupt Service Routine (ISR) for PIC micro-controller in XC8 programming is differ depends on the version of the compiler. Some time the source codes can generate error in other version. In some case, it can be build but the ISR does not work during run-time. So we will need to read its compiler user manual. 

PIC16F887 HC-SR04 Distance Sensor LCD Using XC8
MPLABX IDE Dashboard

Click here to download its source file.




Wednesday, December 27, 2023

PIC16F887 DHT-11 LCD Example Using XC8

DHT11 converts the surrounding temperature and humidity to serial digital data for any micro-processor. It uses only one serial data wire. It able to convert between 0 and 50 degree Celsius in temperature, and 0 to 90RH for humidity. It's suitable for air conditioning system, agricultural application, etc.

PIC16F887 DHT-11 LCD Example Using XC8
DHT-11 Sensor

PIC16F887 DHT-11 LCD Example Using XC8
Prototyping Board

It contains 5 bytes (40 bits) of digital data. They are 1 byte of humidity, 1 byte of temperature, and 1 byte of check sum. For more information about decoding its data byte please check this post.

PIC16F887 DHT-11 LCD Example Using XC8
DTH-11 Sensor

 
PIC16F887 DHT-11 LCD Example Using XC8
TC1604A-01 16x4 Character LCD Module

In this example, I use an 8-bit PIC micro-controller PIC16F887, a DHT-11 sensor module, and a 16x2 character LCD to read and display the environmental data. I use the Microchip MPLABX IDE v6.15 and its XC8 C compiler v2.36 (free version).

  1. /*
  2.  * File: main.c
  3.  * Author: Admin
  4.  *
  5.  * Created on December 26, 2023, 9:03 PM
  6.  * PIC16F887 DHT-11 Sensor and LCD Example
  7.  * MPLABX IDE v6.15 XC8 v2.36
  8.  */
  9.  
  10. #include <xc.h>
  11. #include "config.h"
  12. #include "LCD4Bits.h"
  13. #include <stdio.h>
  14.  
  15. #define _XTAL_FREQ 8000000UL
  16.  
  17. #define DATA_PIN RD0
  18. #define DATA_DIR TRISD0
  19.  
  20. uint8_t data[5];
  21. void readDHT11(void){
  22. for(uint8_t i=0;i<5;i++) data[i]=0;
  23. DATA_DIR=0;
  24. DATA_PIN=1;
  25. __delay_ms(10);
  26. DATA_PIN=0;
  27. __delay_ms(18);
  28. DATA_PIN=1;
  29. __delay_us(30);
  30. DATA_PIN=0;
  31. DATA_DIR=1;
  32. __delay_us(10);
  33. while(DATA_PIN==0);
  34. __delay_us(10);
  35. while(DATA_PIN==1);
  36. __delay_us(10);
  37.  
  38. //Start of Transmission
  39. for(uint8_t i=0;i<5;i++) {
  40. for(uint8_t j=0;j<8;j++){
  41. __delay_us(5);
  42. while(DATA_PIN==0);
  43. __delay_us(50);
  44. if(DATA_PIN==1) { data[i]|=(1<<7-j); while(DATA_PIN==1);}
  45. }
  46. __delay_us(10);
  47. }
  48. /*CRC Calculation - the last byte data[4] is check sum*/
  49. uint8_t crc = data[0]+data[1]+data[2]+data[3];
  50. if(crc!=data[4]) {for(uint8_t i=0;i<4;i++) data[i]=0; return;}
  51. __delay_us(10);
  52. }
  53.  
  54.  
  55. void main(void) {
  56. OSCCONbits.IRCF=7;
  57. char msg[8];
  58. PORTA=0;
  59. TRISA=0;
  60. lcdInit();
  61. lcdString("Temperature:");
  62. __delay_ms(1000);
  63. while(1){
  64. readDHT11();
  65. sprintf(msg,"%2dRH",data[0]);
  66. lcdXY(1,2); lcdString(msg);
  67. sprintf(msg,"%2d%cC",data[2],223);
  68. lcdXY(8,2); lcdString(msg);
  69. __delay_ms(500);
  70. }
  71. return;
  72. }
  73.  

I use its 8MHz internal oscillator clock source leaving the XTAL1 and XTAL2 pin opened.

PIC16F887 DHT-11 LCD Example Using XC8

Dashboard

PIC16F887 DHT-11 LCD Example Using XC8

Running Program



PIC16F887 DHT-11 LCD Example Using XC8

Running Program

 

PIC16F887 DHT-11 LCD Example Using XC8

Simulating Program


Proteus VSM can be used for circuit design and simulation. Click here to download its source file.



Sunday, December 24, 2023

PIC16F887 DS18B20 LCD Example Using XC8

Overview

For a micro-controller that doesn't have a analog to digital converter module, the designer can choose any others temperature sensor that use any communication method, I2C, SPI, or even 1-Wire serial communication interface. A 1-Wire digital thermometer is very popular due to its low cost, multiples device communication, low pins count (a few wires).

PIC16F887 DS18B20 LCD Example Using XC8
Prototype Board Test

DS18X20 temperature sensor is in common now. Using only one data pin the controller able to control up to 127 DS18X20 devices on a single bus with distinct device unique ID (ROM). Here I use a DS18B20 temperature sensor to interface with a Microchip PIC16F887 micro-controller. I don't write any more details here you check it in previous post.







PIC16F887 DS18B20 LCD Example Using XC8
DS18B20 Pin Configurations

This device requires only three wires GND, DQ, and VDD, or ever two wires mode (parasitic power supply). These three wires will share with other 1-Wire devices for multiple device connections. 

MPLABX IDE and XC8 Programming

Arduino platform has various libraries for this sensor. Other C compilers such as MikroC, CCS PICC also has their own libraries for this device. However I write my own libraries follow the original application note created by the device manufacture. 

MPLABX IDE and XC8 C compiler for 8-bit PIC micro-controller is free to use (without code optimization). 

In this example, I use my own 8-bit PIC Prototyping Board to test this program. It has an on-board 16x2 LCD module (TINSHARP TC1604A-01).

PIC16F887 DS18B20 LCD Example Using XC8
TC1604A-01 Front

PIC16F887 DS18B20 LCD Example Using XC8
TC1604A-01 Back View

PIC16F887 doesn't require an external crystal oscillator. It's operated by its internal RC oscillator with a selected 8MHz clock frequency.

  1. /*
  2.  * File: main.c
  3.  * Author: Admin
  4.  *
  5.  * Created on December 24, 2023, 5:56 PM
  6.  * PIC16F887 DS18B20 and LCD Example
  7.  * MPLABX IDE v6.15
  8.  * XC8 v2.36
  9.  */
  10.  
  11.  
  12. #include <xc.h>
  13. #include "config.h"
  14. #include "lcd.h"
  15. #include "ds18b20.h"
  16.  
  17. #define _XTAL_FREQ 8000000UL
  18.  
  19. unsigned char byte[10];
  20. unsigned char TH=0,TL=0;
  21.  
  22. void sensorRead(void){
  23. ow_reset();
  24. writeByte(0xCC);
  25. writeByte(0x44);
  26. __delay_us(104);
  27. ow_reset();
  28. writeByte(0xCC);
  29. writeByte(0xBE);
  30. for(int i=0;i<9;i++) byte[i]=readByte();
  31. TH=byte[1];
  32. TL=byte[0];
  33. __delay_ms(10);
  34. }
  35.  
  36. void main(void) {
  37. OSCCONbits.IRCF=7;
  38. PORTD=0;
  39. TRISD=0;
  40. lcdInit(); lcdString("PIC16F887 LCD");
  41. lcdXY(1,2); lcdString("DS18B20 1-Wire");
  42. lcdXY(1,3); lcdString("Programming With");
  43. lcdXY(1,4); lcdString("MPLABX IDE XC8");
  44. __delay_ms(2500);
  45. lcdCommand(0x0C);
  46. lcdCommand(0x01);
  47. __delay_ms(5);
  48. lcdXY(3,1); lcdString("Temperature:");
  49. lcdXY(1,3); lcdString("DS18B20 Connects");
  50. lcdXY(1,4); lcdString("Pin RD7.");
  51. int temp=0, fraction=0;
  52. while(1){
  53. sensorRead();
  54. temp=(TH<<8)+TL;
  55. TH=temp>>4;
  56. lcdXY(1,2); lcdString("1Wire: ");
  57. if(temp&0x8000){
  58. temp=~temp+1;
  59. TH=temp>>4;
  60. TH&=0x7F;
  61. lcdData('-');
  62. lcdData(48+TH/10);
  63. lcdData(48+TH%10);
  64. }else{
  65. lcdData((TH>=100)?(48+TH/100):' ');
  66. lcdData((TH>=10)?(48+(TH%100)/10):' ');
  67. lcdData(48+TH%10);
  68. }
  69. fraction=temp&0x000F;
  70. fraction*=625;
  71. lcdData('.');
  72. lcdData(48+fraction/1000);
  73. lcdData(48+(fraction%1000)/100);
  74. lcdData(223);
  75. lcdData('C');
  76. __delay_ms(500);
  77. }
  78. return;
  79. }
  80.  

Without using C floating point and sprintf() function, it saves ROM and RAM usage. 

PIC16F887 DS18B20 LCD Example Using XC8
MPLABX IDE Dashboard
 

Proteus can be used for schematic design, or even circuit simulation.

PIC16F887 DS18B20 LCD Example Using XC8
Initialization

 
PIC16F887 DS18B20 LCD Example Using XC8
Temperature Reading In Simulator

Click here to download its source file. I use MPLABX IDE v6.15 and XC8 C compiler v2.36 free edition.

PIC16F887 DS18B20 LCD Example Using XC8

 
PIC16F887 DS18B20 LCD Example Using XC8
Temperature Reading

This old DIY prototyping board works well easing component placement board breadboard.




Search This Blog

Labels

25AA010A (1) 8051 (7) 93AA46B (1) ADC (30) Analog Comparator (1) Arduino (15) ARM (6) AT89C52 (7) ATMega32 (54) AVR (57) CCS PICC (28) DAC (1) DHT11 (2) Display (105) Distance Sensor (3) DS18B20 (3) dsPIC (2) dsPIC30F1010 (2) EEPROM (5) Environment Sensor (4) esp8266 (1) I2C (29) Input/Output (67) Interrupt (19) Keil (5) Keypad (10) LCD (46) Master/Slave (1) MAX7221 (1) MCP23017 (5) MCP23S17 (4) Meter (3) MikroC (2) Motor (15) MPLABX (66) Nokia 5110 LCD (3) OLED (2) One-Wire (6) Oscillator (8) PCB (6) PCD8544 (3) PCF8574 (5) PIC (107) PIC12F (2) PIC16F628A (2) PIC16F630 (1) PIC16F716 (3) PIC16F818 (10) PIC16F818/819 (2) PIC16F84A (15) PIC16F876A (1) PIC16F877A (9) PIC16F88 (1) PIC16F887 (60) PIC18 (19) PIC18F1220 (4) PIC18F2550 (3) PIC18F4550 (12) PWM (11) RTC (8) Sensor (10) SH1106 (1) Shift Register (11) Shift Registers (2) SPI (24) STM32 (6) STM32 Blue Pill (6) STM32CubeIDE (6) STM32F103C8T6 (6) SysTick (3) temperature sensor (11) Thermometer (21) Timer/Counter (30) TM1637 (2) UART (7) Ultrasonic (4) Voltmeter (7) WDT (1) XC16 (2) XC8 (94)