/* thermometer_NTC_C */
/* 3 digit unsigned "xx.x" temperature presentation */
// Arduino UNO R3
// AVR_ATmega328P
#define F_CPU 16000000UL
#include <avr/io.h> // AVR register names/addresses and bit names/numbers
#include <avr/cpufunc.h> // for the nop instruction
#include <util/delay.h>
void _delay_ms ( double );
void _delay_us ( double );
void init_AD( void );
unsigned int get_AD( void);
/* --- Temperature calculation --- */
float temperatureNTC( unsigned int ADvalue );
/* --- serial shift 3 digit 7-segment display --- */
#define SEG7_DDR DDRD
#define SEG7_PORT PORTD
#define SEG7_LOAD PIND2 // (D02)
#define SEG7_SCLK PIND3 // (D03)
#define SEG7_SDI PIND4 // (D04)
void display_init( void );
void shiftByte( unsigned char );
void display_temperature( unsigned int );
/* *********************************** */
/* MAIN PROGRAM */
/* *********************************** */
int main(void)
{
unsigned int ADvalue;
float temp;
unsigned int tempvalue;
display_init( );
init_AD( );
while(1)
{
// thermometer measurement
ADvalue = get_AD( );
temp = temperatureNTC( ADvalue );
tempvalue = (unsigned int)(temp * 10.0);
// 7-segment display
display_temperature( tempvalue );
_delay_ms(200);
}
}
/* *********************************** */
/* FUNCTIONS */
/* *********************************** */
/* ------------------------ */
/* AD conversion */
/* ------------------------ */
void init_AD( void )
{
// Bits in ADCSRA register: "ADEN ADSC ADATE ADIF ADIE ADPS2 ADPS1 ADPS0"
// F_ADC = F_CPU/PRESCALE sample rate (50kHz < F_ADC < 200kHz)
// 16MHz/128 = 125KHz so we set ADC prescaler to 128
ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // "-----111" ADPS 128
ADCSRA |= (1 << ADEN); // "1-------" Enable AD converter
// Bits in ADMUX register: "REFS1 REFS0 ADLAR - MUX3 MUX2 MUX1 MUX0"
// Select AD0 "----0000" is default, nothing has to be done
// Set 10 bit Right adjust "--0-----" is default, nothing has to be done
// In main program to start AD
// ADCSRA |= (1 << ADSC);
// In main program to wait for AD done
// while(ADCSRA & (1<<ADSC)){}
}
unsigned int get_AD( void)
{
unsigned int num;
ADCSRA |= (1 << ADSC); // Start AD (ADCSRA "-1------")
while( ADCSRA & (1 << ADSC) ) {} // Wait for AD done
num = ADC; // result 10 bit right adjusted
return num;
}
/* ------------------------ */
/* Temperature conversion */
/* ------------------------ */
float temperatureNTC( unsigned int ADvalue ) // using Steinhart-Hart
{
const float BETA = 3950;
// should match the Beta Coefficient of the thermistor
float celsius = 1 / (log(1 / (1023. / ADvalue - 1)) / BETA + 1.0 / 298.15) - 273.15;
if(celsius < 0) celsius = 0;
return celsius;
}
/* ----------------------------- */
/* Shiftregister 7-seg display */
/* ----------------------------- */
void display_init( void )
{
SEG7_PORT &= (~( 1 << SEG7_LOAD )); // Load = 0
SEG7_DDR |= (1 << SEG7_LOAD); // Output
SEG7_PORT &= (~( 1 << SEG7_SCLK )); // SCLK = 0
SEG7_DDR |= (1 << SEG7_SCLK); // Output
SEG7_PORT &= (~( 1 << SEG7_SDI )); // Load = 0
SEG7_DDR |= (1 << SEG7_SDI); // Output
}
void display_temperature( unsigned int temperature )
{
unsigned char data;
unsigned int temp;
unsigned char NUMBERS[] = {
// "0123465789 -" for active Low display
0x03, // 0000 0011 "0"
0x9F, // 1001 1111 "1"
0x25, // 0010 0101 "2"
0x0D, // 0000 1101 "3"
0x99, // 1001 1001 "4"
0x49, // 0100 1001 "5"
0x41, // 0100 0001 "6"
0x1F, // 0001 1111 "7"
0x01, // 0000 0001 "8"
0x19, // 0001 1001 "9"
0xFF, // 1111 1111 "Blank"
0xFD // 1111 1101 "Minus"
};
SEG7_PORT &= (~( 1 << SEG7_LOAD )); // Load = 0
temp = temperature % 10; // x--
data = (unsigned char) temp;
data = NUMBERS[data];
// data &= 0xFE; // insert decimal point x.--
shiftByte( data );
temperature = temperature / 10;
temp = temperature % 10; // -x-
data = (unsigned char) temp;
data = NUMBERS[data];
data &= 0xFE; // insert decimal point -x.-
shiftByte( data );
temperature = temperature / 10;
temp = temperature % 10; // --x
data = (unsigned char) temp;
data = NUMBERS[data];
// data &= 0xFE; // insert decimal point --x.
shiftByte(data );
_delay_ms(1);
SEG7_PORT |= ( 1 << SEG7_LOAD ); /* "1" */
}
void shiftByte( unsigned char data)
{
unsigned char i;
SEG7_PORT &= ~( 1 << SEG7_SCLK ); /* "0" */
for( i = 0; i < 8; i++ )
{
if (data & 0x01) SEG7_PORT |= ( 1 << SEG7_SDI );
else SEG7_PORT &= ~( 1 << SEG7_SDI );
SEG7_PORT |= ( 1 << SEG7_SCLK ); /* "1" */
_delay_ms(1);
SEG7_PORT &= ~( 1 << SEG7_SCLK ); /* "0" */
data >>= 1;
}
_delay_ms(1);
}
/* *********************************** */
/* HARDWARE */
/* *********************************** */
/* Chip ATMega328 Arduino Uno R3 stackable header
_______
Digital: _____/ \__ Analog:
______________ ______________ txd ->-|D00 >RXD A5|-
| \/ | rxd -<-|D01 <TXD A4|-
Res---|01 PC6/RES' ATM328 SCL/PC5 28|-(A5)- SEG7_Load -<-|D02 A3|-
txd ->-(D00)-|02 PD0/RXD SDA/PC4 27|-(A4)- SEG7_SCLK -<-|D03~ A2|-
rxd -<-(D01)-|03 PD1/TXD PC3 26|-(A3)- SEG7_SDI -<-|D04 A1|-
Load-(D02)-|04 PD2/INT0 PC2 25|-(A2)- -|D05~ A0|-<-NTC_OUT
SCLK-(D03)-|05 PD3/INT1/PWM PC1 24|-(A1)- -|D06~ | Power:
SDI-(D04)-|06 PD4 PC0 23|-(A0)-<-NTC_OUT -|D07 Vin|-
+5V ---|07 VCC GND 22|--- Gnd | GND|--- GND
Gnd ---|08 GND AREF 21|--- Vin -|D08 GND|-
Xtal |X|--|09 PB6/OSC1 AVCC 20|--- +5V -|D09~ +5V|--- +5V
16MHz |X|--|10 PB7/OSC2 SCK/PB5 19|-(D13)- -|D10~ +3.3V|-
-(D05)-|11 PD5/PWM MISO/PB4 18|-(D12)- -|D11~ Res|-
-(D06)-|12 PD6/PWM PWM/MOSI/PB3 17|-(D11)- -|D12 IOREF|-
-(D07)-|13 PD7 PWM/SS'/PB2 16|-(D10)- -|D13 LED --- |
-(D08)-|14 PB0 PWM/PB1 15|- -|GND |
|______________________________| -|AREF |
-|SCL |
-|SDA |
|________________|
*/
/*
74HC595 Shiftregister for 3 digit 7-segment display
______________________________________
| SEG7 Active low '0' LED on |
+5V ---|Vcc /-a-\ Vcc|---
GND ---|Gnd f b Gnd|---
D04 ->-|SDI |-g-| a.b.c.d.e.f.g.dp SDO|---
D03 ->-|SCLK e c lsb first SCLK|---
D02 ->-|Load \-d-/ dp Load|---
|______________________________________|
*/
/*
________________
| NTC Thermistor |
OUT -| NTC 10k |
VCC -| R 10k |
GND -| |
|________________|
*/