Infrared Temperature Pen

13
Infrared Temperature Pen Charlie Aylward, Emmett Harper

Transcript of Infrared Temperature Pen

Page 1: Infrared Temperature Pen

Infrared Temperature Pen

Charlie Aylward, Emmett Harper

Page 2: Infrared Temperature Pen

Introduction:

The goal of this final project is to utilize a sensor to create a prototype for a sellable

product. This project aims to apply various embedded system design aspects to build a simple

system to monitor a sensor and display the sensor output. In this project, an infrared

thermometer interfaced with an MSP430 is utilized to ensure beverages are at an ideal serving

temperature. A portable pen-style design will enable this device to be used on the go and in

various environments.

System Requirements:

This device shall provide temperature readings of specific beverages and compare them

to ideal serving temperatures. There shall be two buttons on the device to control beverage

modes and device power. When the device is pointed toward a beverage with the power button

held pressed, the system shall determine the beverage temperature and display its relation to

the ideal temperature via an LED array. The LEDs are centered around a green LED

representing the correct temperature. Four red and blue LEDs on either side of the green LED

shall signify whether the drink is too hot or cold. With the power button held down, a second

button may be pressed to toggle between beverage modes and display that mode by lighting up

Page 3: Infrared Temperature Pen

an LED adjacent to the indicating label for the mode. The device shall operate on two

replaceable AAA batteries.

System Specifications:

Table 1. System Specifications

Specifications Value Units

MLX VCC 3.0 Volts

MLX VSS (GND) 0 Volts

Measurement Resolution 0.02 oCelcius

Accuracy 0.5 oCelcius

Resistors 10K Ohms

Temperature Range -40 to 125 oCelcius

MLX Clock 20 kHz

MSP430 Clock 1 MHz

Weight 54.86 grams

Diameter 2.3 cm

Length 16.5 cm

Field of View -20 to 20 Degrees

Sensor Communication I2C N/A

GPIO Pins 4 N/A

System Architecture:

The system is composed of 5 main components: mode button, power button, MSP430,

MLX90614 (sensor), and a LED array. The power button supplies a 3V battery source to the

system when pressed. This enables the MSP430 to communicate with the sensor and control

the LED array. Regular operation involves I2C communication between the sensor and the

Page 4: Infrared Temperature Pen

MSP430. The mode button interrupts regular operation and changes the preset temperature

value being compared to. All of the system components are arranged within an ergonomic, pen-

style design to allow for easy portability.

Figure 1. Block Level Diagram of Infrared Beverage Thermometer

Component Design:

The MSP430 microcontroller software begins I2C communication with the MLX by

sending a start signal followed by the MLX90614 slave address. If the MLX90614 lowers the

specified acknowledge bit, then the two devices have successfully initiated communication.

Following acknowledgement, the MLX90614 receives a transmitted sequence representing a

command and the slave address byte once more.Upon another acknowledgement, the

MLX90614 sends two bytes (each requiring acknowledgement from the MSP430) representing

the sensor temperature value. The MSP430 lights up the appropriate LEDs based on how far

the temperature is with the ideal temperature. Pressing the mode button while the power button

is held initiates an interrupt to change the ideal temperature value being compared against. This

loop repeats until the MSP430 loses power via the main button being unpressed. An overview of

the software flow is depicted in Figure 2.

Page 5: Infrared Temperature Pen

Figure 2. Block Level Diagram of Software Flow for Infrared Beverage Thermometer

Figure 3. Schematic for the Infrared Beverage Thermometer

The MLX90614 SDA and SCL pins are tied to ports 1.7 and 1.6 respectively on the

MSP430 with pull-up resistors to Vcc. 9 LEDs soldered to a separate PCB and are connected to

Page 6: Infrared Temperature Pen

MSP430 pins 1.1-1.5 and 2.0-2.3 with a resistor between ground and the LED cathodes to

reduce the voltage drop across the LEDs.

The MLX90614 sensor ships factory calibrated and features a SMBus output with a

resolution of ±0.02 oCelcius (courtesy of a built-in 17-bit ADC). The temperature range of the

sensor is from -70.01 oC to +382.19 oC. The sensor stores the temperature as a hex value when

provided power.The MSP430 reads the appropriate registers to pull the stored temperature

value ranging from 0x27AD (-70.01 oC) to 0x7FFF (382.19 oC). The relation between the values

stored in memory to the temperature reading is shown in Figure 4 with the hex values converted

to decimal.

Figure 4. Relation between temperature readings and value stored in sensor registers

Amp Hours of storage = 1150 mA/h

Average Device Current = 2.9mA

Battery Autonomy = 396.5 hours

Bill of Materials:

Table 2. Bill of Materials

Page 7: Infrared Temperature Pen

Item Name Part # Supplier Name Quantity Price Each Extended Price Total

MSP430G2553 1308126433 TI 1 $10.00 $10.00

MLX90164 MLX90614xAA Melexis 1 $19.95 $19.95

4.7kOhm Resistor 271-1121 Radio Shack 3 $0.10 $0.30

1kOhm Resistor 271-1149 Radio Shack 2 $0.10 $0.20

Large Tactile Push Button

bi00107 Generic 1 $0.10 $0.10

Small Tactile Push Button

bi00106 Generic 1 $0.10 $0.10

Breadboard Wires 276-173 Radio Shack 30 $0.05 $1.50

Blue LED Strip 12620 SparkFun 1 $2.95 $2.95

Red LED Strip 12619 SparkFun 1 $2.95 $2.95

Green LED Strip 12622 SparkFun 1 $4.95 $4.95

$43.00

System Integration:

The two AAA 1.5V batteries connected to the power button supply 3.0V to the system.

Using an inline battery holder, the diameter of the final design is minimized. The array of LEDs

are manipulated with conditional logic based on how far the actual temperature is from the ideal

temperature. Larger differences between the ideal temperature and the temperature detected is

signified by more than one LED lighting up. Each LED in either direction (hot or cold) signified

steps of ±2 oF from the ideal temperature. The second button is hooked up to a resistor and

then connected to pin 2.3. This “mode” button is used to cycle through preset #DEFINEs

representing specific beverages’ ideal serving temperature. Each LED corresponds to a

beverage specified on an adjacent label adjacent. Each press of the “mode” button sequentially

steps through the 8 specified beverage modes.

Conclusion:

This project really pushed us to take an idea and go through the struggles it takes to

have a working prototype. We both learned that with I2C communication between the two

devices takes a really long time to get everything just right. Our biggest problem was

Page 8: Infrared Temperature Pen

frequencies and baud rates that should’ve been the same were producing different results and

in the end we have to brute force find the one that supplied correct communication. Another

huge time sink was debugging what we already had packaged. Sometimes you run across bugs

or quirks when you put the whole system into your package, resulting in taking it out of the

package to test it only to put it back in the package. We found that testing in slow steps reduces

the overall time it takes to fine tune and debug our product. The concepts that are involved in

getting a device like this to work are not hard but you never think about all the time and effort

you have to put in for research and debugging. We both have a much realer sense of what to

expect when taking on a project like this.

Appendices:

#include <msp430g2553.h> //#define ROOM 14905 //76 deg #define MILK 13712 //34 deg #define SODA 13823 //38 deg (coke) #define BEER 14073 //47 deg (pale ales) #define WHITEWINE 14212 //52 deg #define WATER 14295 //55 deg #define REDWINE 14434 //60 deg #define COFFEE 17207 //159 deg #define GREENTEA 17629 //175 deg #define OPTIONS 8 #define TIMEOUT 30000 int sleeping = 0; int mode; char modeCount; int TXByteCtr, RXByteCtr; int Rx = 0; char command = 0x07; unsigned char data_received[3]; unsigned char *PRxData; char itgAddress = 0x5A; int temperature; void init_I2C(void); void Transmit(void); void Receive(void); char temp_lower, temp_upper; void get_mode(); void write_SegC (char value); char read_SegC (); int delay; int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT P1OUT &= ~(BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5); P1DIR |= BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5; P2DIR |= BIT0 | BIT1 | BIT2; P2OUT &= ~(BIT0 | BIT1 | BIT2); //BUTTON CONFIGURE P2REN |= BIT3 | BIT4; P2IES |= BIT3 | BIT4; P2IFG &= ~(BIT3 | BIT4);

Page 9: Infrared Temperature Pen

P2DIR &= ~(BIT3 | BIT4); P2SEL &= ~(BIT3 | BIT4); P2SEL2 &= ~(BIT3 | BIT4); P2IE |= BIT3; //1MHz Clock DCOCTL = 0; // Select lowest DCOx and MODx settings BCSCTL1 = CALBC1_1MHZ; // Set range DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0 P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0 modeCount = read_SegC(); switch (modeCount) { case 0: mode = MILK; break; case 1: mode = SODA; break; case 2: mode = BEER; break; case 3: mode = WHITEWINE; break; case 4: mode = WATER; break; case 5: mode = REDWINE; break; case 6: mode = COFFEE; break; case 7: mode = GREENTEA; break; default: break; } get_mode(); __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts } //------------------------------------------------------------------------------- // The USCI_B0 data ISR is used to move received data from the I2C slave // to the MSP430 memory. It is structured such that it can be used to receive //------------------------------------------------------------------------------- #pragma vector = USCIAB0TX_VECTOR __interrupt void USCIAB0TX_ISR(void) { if(Rx == 1){ // Master Recieve? if (RXByteCtr) { *PRxData++ = UCB0RXBUF; // Get RX data RXByteCtr--; } else{ IFG2 &= ~UCB0RXIFG; // Clear USCI_B0 TX int flag Rx = 0; __bic_SR_register_on_exit(CPUOFF); // Exit LPM0 } if (RXByteCtr == 1) { UCB0CTL1 |= UCTXSTP; // I2C stop condition IFG2 &= ~UCB0RXIFG; // Clear USCI_B0 TX int flag __bic_SR_register_on_exit(CPUOFF); // Exit LPM0 } } else{ // Master Transmit if (TXByteCtr) // Check TX byte counter

Page 10: Infrared Temperature Pen

{ UCB0TXBUF = command; // Load TX buffer TXByteCtr--; // Decrement TX byte counter } else { IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag __bic_SR_register_on_exit(CPUOFF); // Exit LPM0 } } } void init_I2C(void) { UCB0CTL1 |= UCSWRST; // Enable SW reset UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset UCB0BR0 = 50; // fSCL = SMCLK/50 = ~20kHz UCB0BR1 = 0; UCB0I2CSA = itgAddress; // Slave Address is 069h UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation IE2 |= UCB0RXIE + UCB0TXIE; //Enable RX and TX interrupt } void Transmit(void){ TACTL = TASSEL_2 + MC_2; CCTL0 = CCIE; // Set timeout interrupt UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition CCR0 += TIMEOUT; __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts } void Receive(void){ TACTL = TASSEL_2 + MC_2; CCTL0 = CCIE; // Set timeout interrupt UCB0CTL1 &= ~UCTR ; // Clear UCTR UCB0CTL1 |= UCTXSTT; // I2C start condition CCR0 += TIMEOUT; __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts } #pragma vector=PORT2_VECTOR __interrupt void button_isr(void) { if (P2IFG & BIT3) { modeCount++; if (modeCount >= OPTIONS){ modeCount = 0; } switch (modeCount) { case 0: mode = MILK; P1OUT = BIT0; P2OUT = 0; break; case 1: mode = SODA; P1OUT = BIT1; P2OUT = 0; break; case 2: mode = BEER; P1OUT = BIT2; P2OUT = 0; break; case 3: mode = WHITEWINE; P1OUT = BIT3; P2OUT = 0; break; case 4:

Page 11: Infrared Temperature Pen

mode = WATER; P1OUT = BIT5; P2OUT = 0; break; case 5: mode = REDWINE; P1OUT = 0; P2OUT = BIT0; break; case 6: mode = COFFEE; P1OUT = 0; P2OUT = BIT1; break; case 7: mode = GREENTEA; P1OUT = 0; P2OUT = BIT2; break; default: break; } } write_SegC(modeCount); for(delay=0; delay<1000; delay++){ __delay_cycles(1500); } // CLEAR INTERRUPT FLAG P2IFG &= ~(BIT3 |BIT4); } void get_mode() { int i; for(i = 0; i < 9; i++){ switch(i){ case 0: P1OUT = BIT0; P2OUT = 0; break; case 1: P1OUT = BIT1; P2OUT = 0; break; case 2: P1OUT = BIT2; P2OUT = 0; break; case 3: P1OUT = BIT3; P2OUT = 0; break; case 4: P1OUT = BIT4; P2OUT = 0; break; case 5: P1OUT = BIT5; P2OUT = 0; break; case 6: P1OUT = 0; P2OUT = BIT0; break; case 7: P1OUT = 0; P2OUT = BIT1; break;

Page 12: Infrared Temperature Pen

case 8: P1OUT = 0; P2OUT = BIT2; break; } __delay_cycles(15000); } while(1){ sleeping = 0; init_I2C(); PRxData = &(data_received[0]); //Transmit process Rx = 0; TXByteCtr = 1; Transmit(); //Receive process Rx = 1; RXByteCtr = 3; Receive(); temp_lower = data_received[0]; temp_upper = data_received[1]; temperature = (temp_upper << 8) | temp_lower; __delay_cycles(100); if(temperature < (mode - 30)){ if ((mode - temperature) > 300) { P1OUT = BIT0 | BIT1 | BIT2 | BIT3; P2OUT = 0; } else if ((mode - temperature) > 180) { P1OUT = BIT1 | BIT2 | BIT3; P2OUT = 0; } else if ((mode - temperature) > 90) { P2OUT = 0; P1OUT = BIT2 | BIT3; } else { P1OUT = BIT3; P2OUT = 0; } } else if(temperature > (mode + 30)){ if ((temperature - mode) > 300) { P1OUT = BIT5; P2OUT = BIT0 | BIT1 | BIT2; } else if ((temperature - mode) > 180) { P1OUT = BIT5; P2OUT = BIT0 | BIT1; } else if ((temperature - mode) > 90) { P1OUT = BIT5; P2OUT = BIT0; } else { P1OUT = BIT5; P2OUT = 0; } } else { P1OUT = BIT4; P2OUT = 0; } __delay_cycles(100); } }

Page 13: Infrared Temperature Pen

void write_SegC (char value) { char *Flash_ptr; // Flash pointer unsigned int i; Flash_ptr = (char *) 0x1040; // Initialize Flash pointer FCTL1 = FWKEY + ERASE; // Set Erase bit FCTL3 = FWKEY; // Clear Lock bit *Flash_ptr = 0; // Dummy write to erase Flash segment FCTL1 = FWKEY + WRT; // Set WRT bit for write operation for (i=0; i<64; i++) { *Flash_ptr++ = value; // Write value to flash } FCTL1 = FWKEY; // Clear WRT bit FCTL3 = FWKEY + LOCK; // Set LOCK bit } char read_SegC() { char *Flash_ptr; // Flash pointer Flash_ptr = (char *) 0x1040; // Initialize Flash pointer return *Flash_ptr; } #pragma vector=TIMER0_A0_VECTOR __interrupt void Timer_A (void) { __bic_SR_register_on_exit(CPUOFF); // Exit LPM0 TACTL = MC_0; }

References:

MLX9016 datasheet

MSP430G2553 Data Sheet