728x90

728x90

Showing posts with label ADC. Show all posts
Showing posts with label ADC. Show all posts

Saturday, December 23, 2023

PIC16F887 LM35 and LCD Interfacing Example Using XC8

LM35 is an analog temperature sensor that can convert environment temperature between -55 to 150 degree Celsius. It need a stable DC supply voltage between 4 and 30V. It generates a linear analog output voltage that's 10mV per degree Celsius. We can interpret this analog signal with an ICL7107 analog to BCD seven-segment display converter, or even a micro-controller's analog to digital converter (ADC).

PIC16F887 LM35 and LCD Interfacing Example Using XC8
On-board LM35 16x2 LCD and PIC16F887 micro-controller

Using a micro-controller with ADC module is common we can select any output display type, a seven segment display or character or graphical LCD. In this example I use a PIC16F887 micro-controller and a 16x4 character LCD from Tinsharp.

I use the internal ADC module of PIC16F887. It has 10-bit resolution. Its voltage reference pins are wired internally by software to GND and VDD (+5VDC). LM35 connects to RA5(AN4) pin of PIC16F887.

The LCD operates in 4-bit data transfer mode. I connect the on-board LCD as follow,

  • RS -> RB5
  • RW-> RB6
  • EN -> RB7
  • DB4...DB7 -> RD0...RD3

PORTB has an alternative analog inputs function. So we have to clear ANSELH SFR first.

  1. /*
  2.  * File: main.c
  3.  * Author: Admin
  4.  *
  5.  * Created on December 22, 2023, 2:59 PM
  6.  */
  7.  
  8.  
  9. #include <xc.h>
  10. #include "config.h"
  11.  
  12. #define _XTAL_FREQ 8000000UL
  13.  
  14. #include "lcd.h"
  15. #include <stdio.h>
  16.  
  17. void main(void) {
  18. /*8MHz Internal OSC*/
  19. OSCCONbits.IRCF=7;
  20. /*Internal ADC FOSC*/
  21. ADCON0bits.ADCS=3;
  22. /*Select AN4*/
  23. ADCON0bits.CHS=4;
  24. __delay_ms(10);
  25. /*Turn On ADC*/
  26. ADCON0bits.ADON=1;
  27. /*Right Justify*/
  28. ADCON1bits.ADFM=1;
  29. /*VDD and VSS VFRE*/
  30. ADCON1bits.VCFG1=0;
  31. ADCON1bits.VCFG0=0;
  32.  
  33. lcdInit();
  34. PORTA=0;
  35. TRISA5=1;
  36. lcdString("Temperature:");
  37. double temp=0;
  38. char message[16];
  39. lcdCommand(0x0C);
  40. __delay_ms(1000);
  41. while(1){
  42. ADCON0bits.GO=1;
  43. while(ADCON0bits.GO==0);
  44. temp=((ADRESH<<8)+ADRESL);
  45. temp=100*(5.0*temp/1023);
  46. sprintf(message,"%3.2f%cC ",temp,223);
  47. lcdXY(1,2); lcdString(message);
  48. lcdXY(1,3); lcdString("On-Board LM35DZ");
  49. lcdXY(1,4); lcdString("Connects To RA5");
  50. __delay_ms(250);
  51. }
  52. return;
  53. }
  54.   

I use MPLABX IDE v6.15 and XC8 C compiler v2.36 free edition without code optimization. So it requires a lot of program memory space up to 91% due to C floating point and sprintf function usage.

PIC16F887 LM35 and LCD Interfacing Example Using XC8
MPLABX IDE v6.15 and XC8 v2.36 free edition resource usage

Proteus is popular for most of electronics hobbyist here but we have to pay for license.

PIC16F887 LM35 and LCD Interfacing Example Using XC8
Proteus Simulation

Click here to download its source file.

PIC16F887 LM35 and LCD Interfacing Example Using XC8
PIC16F887 Prototyping Board



Saturday, August 21, 2021

Reading The Analog Temperature From LM35 With PIC16F819 In PICC

 

Overview Of LM35

The LM35 is an analog temperature sensor with only three pins, positive supply voltage, ground and analog temperature output voltage. It could convert the temperature between -55 to 150 degree Celsius.

Reading The Analog Temperature From LM35 With PIC16F819 In PICC
LM35DZ in TO-92 Package

Supply voltage ranges from 4 to 30 V. It’s temperature accuracy is about 0.25 degree Celsius. DOUT is the analog temperature output. The equivalence temperature is 10 mV per degree Celsius.

Reading The Analog Temperature From LM35 With PIC16F819 In PICC
Typical connection diagram

PIC Programming And Interfacing

I use the ADC module of PIC16F819 to read the analog temperature value, fed into RA0.

In the positive temperature condition, LM35 creates a positive output voltage. Similarly, it creates a negative voltage output value in the below-zero temperature condition. The main problem is to make PIC16F819 able to read negative voltage value.

PIC16F819 has two voltage reference pins,

  • VREF+ at RA3
  • VREF- at RA2

But by default the voltage reference is internally connected to +5 V and GND. Anyway, I use external voltage references for the ADC. VREF+ connects to +2.5 V and VREF- connects to -2.5 V. The total reference voltage still stays at 5 V.

PIC16F819 has an internal RC oscillator, clocks up to 8 MHz. I decided to use this internal clock due to extra components placement and circuit designing add-on.

A character LCD displays connects to PORTB, displays the temperature data. It works in 4-bit mode.

Reading The Analog Temperature From LM35 With PIC16F819 In PICC
Schematic Diagram

To create a -2.5/+2.5 V negative voltage pair, I use two 2.5 V zener diode pair as shown in the schematic diagram.

#include<16F819.h>
#device adc=10
#fuses INTRC_IO,NOWDT
#use delay(clock=8M)
#define LCD_ENABLE_PIN PIN_B2
#define LCD_RS_PIN PIN_B0
#define LCD_RW_PIN PIN_B1
#define LCD_DATA4 PIN_B4
#define LCD_DATA5 PIN_B5
#define LCD_DATA6 PIN_B6
#define LCD_DATA7 PIN_B7
#include<lcd.c>
void main(void){
char degree=223;
int16 adc;
float voltage;
setup_oscillator(OSC_8MHz);
output_A(0x00);
set_tris_A(0xFF);
setup_adc(ADC_CLOCK_INTERNAL );
set_adc_channel( 0 );
setup_adc_ports(AN0_VREF_VREF);
lcd_init();
lcd_gotoxy(1,1);
printf(LCD_PUTC,"Temperature:");
while(1){
adc=read_adc(ADC_START_AND_READ);
voltage=(adc*5.0)/1024;
voltage=voltage-2.5;
voltage*=100;
lcd_gotoxy(1,2);
printf(LCD_PUTC,"%0.2f %cC",voltage,degree);
}
}


Reading The Analog Temperature From LM35 With PIC16F819 In PICC
This program consumes 78 % of program memory, and 16 % of device’s RAM.

Reading The Analog Temperature From LM35 With PIC16F819 In PICC
A simulation screen shot


Monday, August 16, 2021

PIC16F818 ADC Read and Display Voltage on 7-Segments Display

 

Introduction

Analog-to-Digital Converter (ADC) operates with analog signal input to microcontroller. Input signal from any device is converted to analog voltage before it’s fed to analog input pin.

Typical reference voltage of ADC is 5V. Maximum direct input voltage to analog input channel must not exceed +5V. For a 10-bit resolution ADC the step voltage is 0.048V.

In this example the controller is programmed to read and show input voltage to ADC input channel 0 – AN0 of PIC16F818. The result will show on a single common anode 7-Segments display.

Programming in MPLABX XC8

There are some additional codes over previous post that convert ADC result to analog voltage, and displaying. A display is one inch in digit size.

PIC16F818 ADC Read and Display Voltage on 7-Segments Display
One inch red common anode seven-segments display

Circuit Design

System runs without external crystal oscillator as it comes with internal oscillator with maximum 8MHz frequency.

PIC16F818 ADC Read and Display Voltage on 7-Segments Display
Schematic Design

AN0 reads input voltage while Port B display the result. Input voltage is varied due to the adjustment of RV1 POT.

Programming

Main program loop keeps track of ADC reading and result updating. Most of source code here is often seen in some previous posts relate to PIC16F818 ADC programming in MPLABX XC8.

/*
 * PIC16F818 Analog Voltage Reading
 */
#include <xc.h>
// PIC16F818 Configuration Bit Settings
#pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTRC oscillator; port I/O function on both RA6/OSC2/CLKO pin and RA7/OSC1/CLKI pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON       // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB3/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off)
#pragma config CCPMX = RB2      // CCP1 Pin Selection bit (CCP1 function on RB2)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
void readVoltage(void){
        /*Seven-Segment output data*/
         char displayAnode[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
        /*Start the conversion*/
        ADCON0bits.GO_nDONE=1;
        /*When GO_nDONE is clear A/D conversion is completed*/
        while(GO_nDONE);
        /*Wait for some microseconds*/
        for(int i=0;i<1000;i++);
        /*Make a 10-bit A/D converter result*/
        int _L=ADRESL;
        int _H=ADRESH;
        unsigned int adcResult=(_H<<8)+_L;
        /*convert to voltage with +0.1V offset*/
        adcResult=(float)adcResult*5.1/1024;
        /*Show voltage reading*/
        PORTB=displayAnode[adcResult];
}
void main(void){
    /*Select 8MHz internal oscillator*/
    OSCCONbits.IRCF=0x07;
    /*Clear Port A*/
    PORTA=0x00;
    /*Clear Port B*/
    PORTB=0x00;
    /*RA0 analog input*/
    TRISA=0x01;
    /*Port B digital output*/
    TRISB=0x00;
    /*Select internal RC oscillator of A/D converter*/
    ADCON0bits.ADCS=0x01;
    /*Select analog channel 0 - AN0*/
    ADCON0bits.CHS=0x00;
    /*RA0-AN0 analog input, AVDD and AVSS voltage references*/
    ADCON1bits.PCFG=14;
    /*Result is right justified*/
    ADCON1bits.ADFM=1;
    /*Turn on A/D converter module*/
    ADCON0bits.ADON=1;
    /*Main Program Loop*/
    while(1){
        readVoltage();
    }
}

Click here to download zip file of this working example.

320x50

Search This Blog

Labels

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

tyro-728x90