Jump to content
43oh

Simple temperature display project


Recommended Posts

I know, I know, not another temperature project . This one is a little different in that it is very simple and uses readily available and inexpensive components. A $1.99 display from Electronic Goldmine: http://www.goldmine-elec-products.com/p ... ber=G15318

or even cheaper at $1.85 from All Electronics: http://www.allelectronics.com/make-a-st ... LCD/1.html

a $4.29 breadboard power supply that provides both 5.0vdc and 3.3vdc using and ordinary 9 - 12 vdc wall wart:

http://www.ebay.com/itm/Perfect-High-Qu ... 3f0f10117f

and a 74HC595N 8 bit shift register at a quantity of 5 for as low as $1.85 including shipping from Ebay.

I started this project to learn more about ADC and the '595 8 bit shift register. Along the way I learned about integer to ascii conversion (necessary for displaying the temperature value). It was also just plain fun working with the LCD display.

 

p><p><a class=post-3266-135135520202_thumb.jpg

' alt='>'>

 

The schematic:

p><p><a class=post-3266-135135520213_thumb.jpg

' alt='>'>

 

Here's the code:

//******************************************************************************
// A simple temperature display project utilizing a $1.99 surplus LCD display module,
// a 74HC595N serial/parallel chip, TI Launchpad with an MSP430G2231 installed and a $4.29
// power supply from Ebay that provides 5vdc and 3.3vdc from a wall wart.
// Code to obtain the temperature came directly from TI's example files, itoa function from
// Google group comp.lang.c and display routines from RobG's "Using 3 wires to control
// parallel LCD display with timotet's adaptation for the Wintek 1x24 char LCD display.
//
//R.G. Rioux - October, 2011
//
// MSP430G2x31 Demo - ADC10, Sample A10 Temp and Convert to oC and oF
//  Description: A single sample is made on A10 with reference to internal
//  1.5V Vref. Software sets ADC10SC to start sample and conversion - ADC10SC
//  automatically cleared at EOC. ADC10 internal oscillator/4 times sample
//  (64x) and conversion. In Mainloop MSP430 waits in LPM0 to save power until
//  ADC10 conversion complete, ADC10_ISR will force exit from any LPMx in
//  Mainloop on reti. Temperaure in oC stored in IntDegC, oF in IntDegF.
//  Uncalibrated temperature measured from device to device will vary with
//  slope and offset - please see datasheet.
//  ACLK = n/a, MCLK = SMCLK = default DCO ~1.2MHz, ADC10CLK = ADC10OSC/4
//
//  D. Dang
//  Texas Instruments Inc.
//  October 2010
//
//                MSP430G2x31
//             -----------------
//        /|\|              XIN|-
//          | |                 |
//          --|RST          XOUT|-
//            |                 |
//            |A10              |
//   ENABLE<--|P1.4         P1.6|-->DATA
//    CLOCK<--|P1.5             |   _____
//            |             P1.7|-->RESET  (for Wintek 1x24 Char Display)
//
//  Built with CCS Version 4.2.4.00033
//  R.G. Rioux October 2011
//******************************************************************************
#include  "msp430g2231.h"
#include 
#include 

//------------------------------------------------------------------------------
// Display related definitions
//------------------------------------------------------------------------------
#define sendData(data) send(data, 1)
#define sendInstruction(data) send(data, 0)
#define initDisplay() sendInstruction(0x1C); sendInstruction(0x14); sendInstruction(0x28); sendInstruction(0x4F); sendInstruction(0xE0) 
#define clearDisplay() sendInstruction(0x01); sendInstruction(0xE3); _delay_cycles(2000)
#define DATAPIN BIT6		// P1.6 
#define CLOCKPIN BIT5		// P1.5
#define ENABLEPIN BIT4		// P1.4
#define RESETPIN BIT7		// P1.7

//------------------------------------------------------------------------------
// Display related functions and variables
//------------------------------------------------------------------------------
void send(char data, char registerSelect);
void sendStr(char data[], int length);
void reset(void);
char charIndex = 0;
char bitCounter = 0;

//------------------------------------------------------------------------------
//  Global variables in program
//------------------------------------------------------------------------------

char buffer[4];
long temp;
long IntDegF;
long IntDegC;

//------------------------------------------------------------------------------
// itoa functions
//------------------------------------------------------------------------------

static char *i2a(unsigned i, char *a, unsigned r);
char *itoa(int i, char *a, int r);

// main

void main(void)
{
 WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
 _delay_cycles(100000);					// Wait for display to settle
 DCOCTL = 0x00;                          // Set DCOCLK to 1MHz
 BCSCTL1 = CALBC1_1MHZ;
 DCOCTL = CALDCO_1MHZ;
 P1DIR |= ENABLEPIN + CLOCKPIN + DATAPIN + RESETPIN; // sets ENABLEPIN,CLOCKPIN,DATAPIN and RESETPIN to outputs
 P1OUT &= ~(CLOCKPIN + DATAPIN + RESETPIN);        // sets CLOCKPIN,RESETPIN and DATAPIN low
 P1OUT |= ENABLEPIN;
 ADC10CTL1 = INCH_10 + ADC10DIV_3;         // Temp Sensor ADC10CLK/4
 ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON + ADC10IE;
 __enable_interrupt();                     // Enable interrupts.
 TACCR0 = 30;                              // Delay to allow Ref to settle
 TACCTL0 |= CCIE;                          // Compare-mode interrupt.
 TACTL = TASSEL_2 | MC_1;                  // TACLK = SMCLK, Up mode.
 LPM0;                                     // Wait for delay.
 TACCTL0 &= ~CCIE;                         // Disable timer Interrupt
 __disable_interrupt();
 reset();									// reset Wintek 1x24 LCD display
 initDisplay();							// initialize display
 sendStr("Temperature:", 12);

 while(1)
 {
   ADC10CTL0 |= ENC + ADC10SC;             // Sampling and conversion start
   __bis_SR_register(CPUOFF + GIE);        // LPM0 with interrupts enabled

   // oF = ((A10/1024)*1500mV)-923mV)*1/1.97mV = A10*761/1024 - 468
   temp = ADC10MEM;
   IntDegF = ((temp - 630) * 761) / 1024;

   // oC = ((A10/1024)*1500mV)-986mV)*1/3.55mV = A10*423/1024 - 278
   temp = ADC10MEM;
   IntDegC = ((temp - 673) * 423) / 1024;

   sendInstruction(0xF2);			// position cursor
   itoa (IntDegF, buffer, 10);		// convert to ascii chars   			  			
sendStr(buffer, strlen(buffer));
send(0xB0, 1);
sendStr("F", 1);
sendInstruction(0xF7);			// position cursor
itoa(IntDegC, buffer, 10);
sendStr(buffer, strlen(buffer));
send(0xB0, 1);
sendStr("C", 1);
 }
}

// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR (void)
{
 __bic_SR_register_on_exit(CPUOFF);        // Clear CPUOFF bit from 0(SR)
}

#pragma vector=TIMERA0_VECTOR
__interrupt void ta0_isr(void)
{
 TACTL = 0;
 LPM0_EXIT;                                // Exit LPM0 on return
}

void send(char data, char registerSelect) {
bitCounter = 0;
while(bitCounter < 8) {
	(data & BIT7) ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN);
	data <<= 1;
	P1OUT |= CLOCKPIN;
	P1OUT &= ~CLOCKPIN;
	bitCounter++;
}
registerSelect ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN);
P1OUT &= ~ENABLEPIN;
_delay_cycles(3000);
P1OUT |= ENABLEPIN;
_delay_cycles(10000);
P1OUT &= ~ENABLEPIN;
}

void sendStr(char string[], int size) {
int charIndex = 0;
while(charIndex < size) {
	sendData(string[charIndex]);
	charIndex++;
}
}

void reset() {
P1OUT &= ~RESETPIN;                     // RESETPIN low
   _delay_cycles(10000);
   P1OUT |= RESETPIN;
}

 /*
 ** The following two functions together make up an itoa()
 ** implementation. Function i2a() is a 'private' function
 ** called by the public itoa() function.
 **
 ** itoa() takes three arguments:
 **        1) the integer to be converted,
 **        2) a pointer to a character conversion buffer,
 **        3) the radix for the conversion
 **           which can range between 2 and 36 inclusive
 **           range errors on the radix default it to base10
 ** Code from Google group comp.lang.c
 */

 static char *i2a(unsigned i, char *a, unsigned r)
 {
   if (i/r > 0) a = i2a(i/r,a,r);
   *a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i%r];
   return a+1;
 }

 char *itoa(int i, char *a, int r)
 {
   if ((r < 2) || (r > 36)) r = 10;
   if (i < 0)
   {
       *a = '-';
       *i2a(-(unsigned)i,a+1,r) = 0;
   }
   else *i2a(i,a,r) = 0;
   return a;
 } 

Link to post
Share on other sites
good work!

I like that LCD. I just used one in a project Im working on. Cheap! :P

 

Thanks timotet! I couldn't get this display to work until I saw your post in RobG's "Using 3 wires to control parallel LCD display." The key was using RESET P1.7 on pin 3 of the display. After that it "lit up."

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...