Can we use temperature sensor (NTC thermistor) with ADC MCP3008 for temperature

jpanhalt

Joined Jan 18, 2008
10,531
Yes, the MCP3008 will "talk" with your PIC18F using SPI. The KY-013 includes both the thermistor and a fixed resistor as a voltage divider, so its output is a voltage that varies with temperature. (Datasheet: https://datasheetspdf.com/pdf-file/1402026/Joy-IT/KY-013/1) You will need to write the code for converting that voltage to temperature (or cut and paste from another site).

If you want something a little simpler and just for learning SPI, you might consider the MAX31856 module from Adafruit and others that communicates temperatures by SPI or the MAX31855 module (same sources) which produces an analog voltage that is linearly proportional to temperature and use the MCP3008 to digitize that and send it by SPI to your PIC.

I chose the MAX31856 chip.
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
352
@JohnInTX @jpanhalt

I have two doubts in my head

  1. Which is more accurate internal ADC or External ADC? I found external ADC but don't know why ?
  2. Can we use pot with SPI MCP3008 to measure voltage between 0v to 5V DC ? I think yes
 

JohnInTX

Joined Jun 26, 2012
4,345
@JohnInTX @jpanhalt

I have two doubts in my head

  1. Which is more accurate internal ADC or External ADC? I found external ADC but don't know why ?
  2. Can we use pot with SPI MCP3008 to measure voltage between 0v to 5V DC ? I think yes
1) The internal ADC is 12 bits, the MCP3008 is 10 bits so the internal ADC has more resolution. Which one is more accurate depends on many factors and requires analysis beyond the scope of a post. For now, either would work for your purposes.
2) Sure. A pot as a voltage divider would work. Pay attention to the maximum recommended input impedence for the particular ADC.

If you are just trying out SPI though, I recommend something simpler to start with.

Good luck!
 

JohnInTX

Joined Jun 26, 2012
4,345
Hi JohnInTX
I am looking simpler way to start with SPI. I have only MCP3008 that work on SPI.
OK. Well, just hook it up and get started. Review the datasheet to find out how to configure the inputs to read the voltage on one pin. You'll know when you have SPI working when you get values back that get higher with higher input voltages and vice versa. You can verify the accuracy later.
Do note that the conversion clock of this ADC is also the SPI clock. That means you have to generate the SPI clock at a rate that works for the ADC. See section 6.2 in the datasheet for that.
http://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf

Also look for application notes that will help you with the thermistor stuff:
http://ww1.microchip.com/downloads/en/Appnotes/00685b.pdf

Have fun!
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
352
OK. Well, just hook it up and get started. Review the datasheet to find out how to configure the inputs to read the voltage on one pin. You'll know when you have SPI working when you get values back that get higher with higher input voltages and vice versa. You can verify the accuracy later.
I hope all connection are okay

MCP3008 VDD to 5V.
MCP3008 VREF to 5V.
MCP3008 AGND to GND.
MCP3008 DGND to GND.
MCP3008 CLK to PIC pin 18. Yellow
MCP3008 SDO to PIC pin 24. Green
MCP3008 SDI to PIC pin 23. Coral
MCP3008 SC to PIC pin 7. grey

KY 013 + to 5V
KY 013 - to GND
KY 013 S to MCP CH0 Pin1 White

1603904888251.png
 

JohnInTX

Joined Jun 26, 2012
4,345
OK. First verify that the voltage from the sensor varies with temperature
Then list the data you will have to send to the ADC to read the single-ended CH 0 and flow out the command and data sequences that you’ll need to do the conversion and read the result.
 
Last edited:

Thread Starter

Djsarakar

Joined Jul 26, 2020
352
OK. First verify that the voltage from the sensor varies with temperature
How to verify that the voltage from the sensor varies with temperature?

I am planning to display temperature value on hyper terminal

Here is my code (I have not completed yet. I am working on part to convert digits into string)

C:
#define _XTAL_FREQ 20000000

// PIC18F45K80 Configuration Bit Settings

// CONFIG1L
#pragma config RETEN = ON // VREG Sleep Enable bit (Ultra low-power regulator is Enabled (Controlled by SRETEN bit))
#pragma config INTOSCSEL = LOW // LF-INTOSC Low-power Enable bit (LF-INTOSC in Low-power mode during Sleep)
// SOSCSEL = No Setting
#pragma config XINST = OFF // Extended Instruction Set (Disabled)
// CONFIG1H#pragma config FOSC = HS2 // HS oscillator (high power, 16 MHz-25 MHz
#pragma config PLLCFG = OFF // PLL x4 Enable bit (Disabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor (Disabled)
#pragma config IESO = OFF // Internal External Oscillator Switch Over Mode (Disabled)
// CONFIG2L#pragma config PWRTEN = ON // Power Up Timer (Enabled)
#pragma config BOREN = OFF // Brown Out Detect (Disabled in hardware, SBOREN disabled)
#pragma config BORV = 0 // Brown-out Reset Voltage bits (3.0V)
#pragma config BORPWR = LOW // BORMV Power level (BORMV set to low power level)
// CONFIG2H#pragma config WDTEN = OFF // Watchdog Timer (WDT disabled in hardware; SWDTEN bit disabled)
#pragma config WDTPS = 1 // Watchdog Postscaler (1:1)
// CONFIG3H#pragma config CANMX = PORTC // ECAN Mux bit (ECAN TX and RX pins are located on RC6 and RC7, respectively)
#pragma config MSSPMSK = MSK5 // MSSP address masking (5 bit address masking mode)
#pragma config MCLRE = OFF // Master Clear Enable (MCLR Disabled, RE3 Enabled)
// CONFIG4L#pragma config STVREN = OFF // Stack Overflow Reset (Disabled)
#pragma config BBSIZ = BB1K // Boot Block Size (1K word Boot Block size)
// CONFIG5L#pragma config CP0 = ON // Code Protect 00800-01FFF (Enabled)
#pragma config CP1 = ON // Code Protect 02000-03FFF (Enabled)
#pragma config CP2 = ON // Code Protect 04000-05FFF (Enabled)
#pragma config CP3 = ON // Code Protect 06000-07FFF (Enabled)
// CONFIG5H#pragma config CPB = ON // Code Protect Boot (Enabled)
#pragma config CPD = ON // Data EE Read Protect (Enabled)
// CONFIG6L#pragma config WRT0 = ON // Table Write Protect 00800-01FFF (Enabled)
#pragma config WRT1 = ON // Table Write Protect 02000-03FFF (Enabled)
#pragma config WRT2 = ON // Table Write Protect 04000-05FFF (Enabled)
#pragma config WRT3 = ON // Table Write Protect 06000-07FFF (Enabled)
// CONFIG6H#pragma config WRTC = ON // Config. Write Protect (Enabled)
#pragma config WRTB = ON // Table Write Protect Boot (Enabled)
#pragma config WRTD = ON // Data EE Write Protect (Enabled)
// CONFIG7L#pragma config EBTR0 = ON // Table Read Protect 00800-01FFF (Enabled)
#pragma config EBTR1 = ON // Table Read Protect 02000-03FFF (Enabled)
#pragma config EBTR2 = ON // Table Read Protect 04000-05FFF (Enabled)
#pragma config EBTR3 = ON // Table Read Protect 06000-07FFF (Enabled)
// CONFIG7H#pragma config EBTRB = ON // Table Read Protect Boot (Enabled)
// #pragma config statements should precede project file includes.// Use project enums instead of #define for ON and OFF.
#include <xc.h>

#define TRUE 1
#define CS_PIN LATAbits.LATA5 // MCP3204/3208 CS pin

void Port_Initialized (void)
{
    ANCON0 = 0; // Set to digital port
    ANCON1 = 0; // Set to digital port
    CM1CON = 0; // Comparator off
    CM2CON = 0; // Comparator off
    ADCON0 = 0; // A/D conversion Disabled
    ADCON1 = 0; // A/D conversion Disabled
    ADCON2 = 0; // A/D conversion Disabled
   
    LATA = 0; // Make all PORTA pins low
    LATB = 0; // Make all PORTB pins low
    LATC = 0; // Make all PORTC pins low
    LATD = 0; // Make all PORTD pins low
    LATE = 0; // Make all PORTE pins low
   
    TRISA = 0b0000000; // Slave Select (SS) RA5/AN4/C2INB/
    TRISB = 0b0000000; // all are output, Unused
   
    //Serial Data Out (SDO) RC5/SDO,
    //Serial Data In (SDI) RC4/SDA/SDI
    //Serial Clock (SCK) RC3/REF0/SCL/SCK
    TRISC = 0b0010010;   //  C6=Tx, C7=Rx  C4 = Data in
    TRISD = 0b0000000; // all are output, show low byte
    TRISE = 0b0000000; // All are output, show high 2 bits
}

void send(char message)
{
    while(TXIF == 0 );   // Wait till the transmitter register becomes empty
    TXREG1 = message;
}

void string(char *p)
{
   while(*p != '\0') {
       __delay_ms(1);
     send(*p);
     p++;
   }
}
void Uart_Initialized(void)
{
    //TXSTAx TRANSMIT STATUS AND CONTROL REGISTER
    TXSTA1bits.CSRC = 0;    //: Don?t care.
    TXSTA1bits.TX9 = 0;    // Selects 8-bit transmission bit
    TXSTA1bits.TXEN = 1;   // Transmit Enable
    TXSTA1bits.SYNC  = 0;   // Asynchronous mode
    TXSTA1bits.SENDB = 0;
    TXSTA1bits.BRGH =  1;   // High speed mode
    TXSTA1bits.TX9D = 0;
    //RCSTAx: RECEIVE STATUS AND CONTROL REGISTER
    RCSTA1bits.SPEN  = 1 ;   // Serial port enabled
    RCSTA1bits.RX9 = 0;     // Selects 8-bit reception
    RCSTA1bits.SREN  = 1 ;   // Don?t care.
    RCSTA1bits.CREN  = 1 ;   // Enables receiver
    RCSTA1bits.ADDEN = 0;      
    RCSTA1bits.FERR  = 0 ;  // No framing error
    RCSTA1bits.OERR  = 1 ; // Overrun error
    RCSTA1bits.RX9D   = 0 ;// Selects 8-bit reception
    SPBRGH1 = 0;
    SPBRG1 = 129,
    INTCON = 0x00;
    PIR1 = 0x00;
    PIR2= 0x00;
    PIR3 = 0x00;
    PIR4 = 0x00;
    PIR5 = 0x00;
    PIE1 = 0x00;
    PIE2 = 0x00;
    PIE3 = 0x00;
    PIE4 = 0x00;
    PIE5 = 0x00;
    IPR1 = 0x00;
    IPR2 = 0x00;
    IPR3 = 0x00;
    IPR4 = 0x00;

}

// SPI in master Mode
void SPI_Init_Master()
{
    SSPSTAT = 0b01000000; // SSPSTAT: MSSP STATUS REGISTER (SPI MODE) SMP=0, CKE=1
    SSPCON1 = 0b00100010; // Master mode,Serial enable, Idle state for clock is a low level
    PIR1bits.SSPIF=0;  
}

unsigned char SPI(unsigned char Sendchar)
{
    SSPBUF = Sendchar; // Copy data in SSBUF to transmit
    while (!PIR1bits.SSPIF); // Wait for complete 1 byte transmission
    PIR1bits.SSPIF = 0; // Clear SSPIF flag
    return SSPBUF;
}

//start main program
void main(void)
{
    unsigned char buffer[16];
    unsigned char High_byte; // temporary ADC receive byte - 2 bits only
    unsigned char low_byte; // temporary ADC receive byte
   
    Port_Initialized();
    SPI_Init_Master();
   
    while (TRUE)
    {
        CS_PIN = 0; // Set CS pin low
        SPI(0x01); // Send "Start" bit
        High_byte = SPI(0b00000000);
        low_byte = SPI(0x00); // Send dummy, receive lower 8 bits
        CS_PIN = 1; // Set CS pin high
        LATD = low_byte; // show result on PORTD
        LATE = High_byte; // show result top 2 bits
       
        // incomplete from this line
        string(buffer);
    }
   
}
 

JohnInTX

Joined Jun 26, 2012
4,345
That's not a whole lot of swing but probably good enough to start.. You probably would be better off to start using a 1K-5K pot in place of the sensor for a bigger voltage range.
 

JohnInTX

Joined Jun 26, 2012
4,345
I am working on part to convert digits into string
What is wrong with using sprintf() to convert data into ASCII characters in a buffer or the similar printf() to convert and output directly to the UART? These can be memory intensive but XC8 is better than most and you have plenty of program space to work with.
Combine the low and high ADC bytes to an integer then use (s)printf to format that binary integer into text automatically.

ADCvalue = (ADC_byteH * 256) + ADCbyteL;

printf("ADC value: %d\n\r",ADCvalue);
OR
sprintf(A_buffer,"ADC value: %d\n\r",ADCvalue);
send_string(A_buffer);

Done!
 
Last edited:
Top