Skip to content

Commit

Permalink
DS18B20 Temperature sensor support
Browse files Browse the repository at this point in the history
This is currently a failed hack, but I wanted to keep the code anyway
because I may be able to salvage it in the future.  So I'm creating a
separate branch named temperature to store this work.

The DS18B20 is installed by connecting the GND, DQ, and Vdd pins to
the ATmega's GND, PC2, and PC5 pins with a 4.7k pull-up between PC2
and PC5.  I drilled a small hole in the base of the case and inserted
the head of the DS18B20 through the hole to get ambient temperature.

This commit displays temperature (in Fahrenheit) along with the date.

I consider this a failed hack because the Ice Tube Clock generates
heat, and the clock itself and surrounding areas has a temperature
that is 1-8 degrees Fahrenheit higher than ambient temperature.  So,
the temperature reading is seldom accurate.  :-(

This commit does include code that is a good example of how to query
the DS18B20 via the 1-Wire protocol.
  • Loading branch information
John Archie committed Feb 11, 2013
1 parent 5e05f00 commit 32e1425
Show file tree
Hide file tree
Showing 12 changed files with 351 additions and 36 deletions.
2 changes: 1 addition & 1 deletion Makefile
Expand Up @@ -13,7 +13,7 @@ PROJECT ?= icetube

# object files
OBJECTS ?= icetube.o system.o time.o alarm.o pizo.o \
display.o buttons.o mode.o usart.o gps.o
display.o buttons.o mode.o usart.o gps.o temp.o

# avr microcontroller processing unit
AVRMCU ?= atmega328p
Expand Down
20 changes: 15 additions & 5 deletions config.h
Expand Up @@ -14,7 +14,7 @@
// "next selected option," or "increment selected number."
//
//
#define ADAFRUIT_BUTTONS
// #define ADAFRUIT_BUTTONS


// AUTOMATIC DIMMER HACK
Expand All @@ -27,7 +27,7 @@
// http://forums.adafruit.com/viewtopic.php?f=41&t=12932
//
//
// #define AUTOMATIC_DIMMER
#define AUTOMATIC_DIMMER


// GPS TIMEKEEPING
Expand All @@ -53,7 +53,7 @@
// http://forums.adafruit.com/viewtopic.php?f=41&t=14941
//
//
// #define EXTERNAL_CLOCK
#define EXTERNAL_CLOCK


// EXTENDED BATTERY HACK
Expand All @@ -71,7 +71,17 @@
// http://forums.adafruit.com/viewtopic.php?f=41&t=36697
//
//
// #define PICO_POWER
#define PICO_POWER


// TEMPERATURE SENSOR HACK
//
// With a DS18B20 digial sensor probe attached to PC2, the clock can display
// temperature readings.
//
//
#define TEMPERATURE_SENSOR
#define TEMPERATURE_ADJUST -96


// DISPLAY BRIGHTNESS / BOOST CONFIGURATION
Expand Down Expand Up @@ -106,7 +116,7 @@
// macros defined in usart.h. The default speed is 9600 baud.
//
//
// #define DEBUG
#define DEBUG


// USART BAUD RATE
Expand Down
24 changes: 12 additions & 12 deletions display.c
Expand Up @@ -3,7 +3,6 @@
//
// PB5 (SCK) MAX6921 CLK pin
// PB3 (MOSI) MAX6921 DIN pin
// PC5 photoresistor pull-up
// PC4 (ADC4) photoresistor voltage
// PC3 MAX6921 BLANK pin
// PC0 MAX6921 LOAD pin
Expand Down Expand Up @@ -63,6 +62,7 @@ uint8_t ee_display_digit_times[] EEMEM = {15, 15, 15, 15, 15, 15, 15, 15, 15};
#define DISPLAY_DOT SEG_H
#define DISPLAY_DASH SEG_G
#define DISPLAY_SLASH SEG_B | SEG_G | SEG_E
#define DISPLAY_DEGREE SEG_A | SEG_B | SEG_F | SEG_G;
#define DISPLAY_WILDCARD SEG_A | SEG_G | SEG_D

// codes for vfd letter display
Expand Down Expand Up @@ -154,12 +154,12 @@ void display_init(void) {
// as inputs *without* pull-ups!?!?)
DDRB &= ~_BV(PB5) & ~_BV(PB3); // set to input

// configure photoresistor pull-up pin
DDRC |= _BV(PC5); // set pin as output
PORTC &= ~_BV(PC5); // pull to ground

#ifdef AUTOMATIC_DIMMER
// disable digital circuitry on photoresistor pins
DIDR0 |= _BV(ADC5D) | _BV(ADC4D);
#else
PORTC |= _BV(PC4); // enable pull-up on unused pin
#endif // AUTOMATIC_DIMMER

// set initial photo_avg to maximum ambient light
display.photo_avg = UINT16_MAX;
Expand Down Expand Up @@ -187,10 +187,7 @@ uint8_t display_onbutton(void) {

// enable display after low-power mode
void display_wake(void) {
// enable external and internal photoresistor pull-ups (the latter
// ensures a defined value if no photoresistor installed)
PORTC |= _BV(PC5) | _BV(PC4); // output +5v, enable pull-up

#ifdef AUTOMATIC_DIMMER
// enable analog to digital converter
power_adc_enable();

Expand All @@ -203,6 +200,7 @@ void display_wake(void) {
// ADSC = 1: start ADC conversion now
// ADPS2:0 = 110: system clock / 64 (8 MHz / 4 = 125 kHz)
ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADPS2) | _BV(ADPS1);
#endif // AUTOMATIC_DIMMER

// configure spi sck and mosi pins as outputs
DDRB |= _BV(PB5) | _BV(PB3);
Expand Down Expand Up @@ -230,12 +228,11 @@ void display_sleep(void) {
PORTD &= ~_BV(PD6); // boost fet off (pull low)
PORTD |= _BV(PD3); // MAX6921 power off (pull high)

// disable external and internal photoresistor pull-ups
PORTC &= ~_BV(PC5) & ~_BV(PC4); // pull to ground, disable pull-up

#ifdef AUTOMATIC_DIMMER
// disable analog to digital converter
ADCSRA = 0; // disable ADC before power_adc_disable()
power_adc_disable();
#endif // AUTOMATIC_DIMMER

// configure MAX6921 LOAD and BLANK pins
PORTC &= ~_BV(PC0) & ~_BV(PC3); // clamp to ground
Expand Down Expand Up @@ -661,6 +658,9 @@ void display_char(uint8_t idx, char c) {
case '/':
display.prebuf[idx] = DISPLAY_SLASH;
break;
case '\370':
display.prebuf[idx] = DISPLAY_DEGREE;
break;
default:
display.prebuf[idx] = DISPLAY_WILDCARD;
break;
Expand Down
12 changes: 0 additions & 12 deletions gps.c
@@ -1,7 +1,5 @@
// gps.c -- parses gps output from usart and sets time accordingly
//
// PB4 gps power control; high normally, pulled low during sleep
//


#include "config.h"
Expand Down Expand Up @@ -47,10 +45,6 @@ uint8_t ee_gps_rel_utc_minute EEMEM = 0;
// load time offsets from gmt/utc
void gps_init(void) {
gps_loadrelutc();

// configure gps power pin (gps off)
PORTB &= ~_BV(PB4); // clamp to ground
DDRB |= _BV(PB4); // set to ouput
}


Expand All @@ -59,9 +53,6 @@ void gps_wake(void) {
// enable usart rx interrupt
UCSR0B |= _BV(RXCIE0);

// configure gps power pin (gps on)
PORTB |= _BV(PB4); // clamp to +5v

// give gps time to acquire signal before issuing "gps lost" warning
gps.warn_timer = GPS_WARN_TIMEOUT;
}
Expand All @@ -71,9 +62,6 @@ void gps_wake(void) {
void gps_sleep(void) {
// disable usart rx interrupt
UCSR0B &= ~_BV(RXCIE0);

// configure gps power pin (gps off)
PORTB &= ~_BV(PB4); // clamp to ground
}


Expand Down
25 changes: 25 additions & 0 deletions icetube.c
Expand Up @@ -34,6 +34,7 @@
#include "mode.h"
#include "usart.h"
#include "gps.h"
#include "temp.h"


// define ATmega328p lock bits
Expand Down Expand Up @@ -87,6 +88,9 @@ int main(void) {
#ifdef GPS_TIMEKEEPING
gps_init();
#endif // GPS_TIMEKEEPING
#ifdef TEMPERATURE_SENSOR
temp_init();
#endif // TEMPERATURE_SENSOR

// if the system is on battery power, sleep until power restored
if(system_power() == SYSTEM_BATTERY) {
Expand All @@ -99,6 +103,7 @@ int main(void) {
sei(); // enable interrupts

// wakey, wakey
system_wake();
#if defined(DEBUG) || defined(GPS_TIMEKEEPING)
usart_wake();
#endif // DEBUG || GPS_TIMEKEEPING
Expand All @@ -111,6 +116,9 @@ int main(void) {
#ifdef GPS_TIMEKEEPING
gps_wake();
#endif // GPS_TIMEKEEPING
#ifdef TEMPERATURE_SENSOR
temp_wake();
#endif // TEMPERATURE_SENSOR

// half-second beep on system reset
pizo_setvolume(3, 0);
Expand All @@ -129,11 +137,13 @@ ISR(TIMER2_COMPA_vect) {
sei(); // allow nested interrupts

if(system.status & SYSTEM_SLEEP) {
system_semitick();
time_tick();
alarm_tick();
pizo_tick();
wdt_reset();
} else {
system_semitick();
time_tick();
buttons_tick();
alarm_tick();
Expand All @@ -143,6 +153,9 @@ ISR(TIMER2_COMPA_vect) {
#ifdef GPS_TIMEKEEPING
gps_tick();
#endif // GPS_TIMEKEEPING
#ifdef TEMPERATURE_SENSOR
temp_tick();
#endif // TEMPERATURE_SENSOR
if(semitick_successful) wdt_reset();
semitick_successful = 0;
}
Expand All @@ -167,6 +180,7 @@ ISR(TIMER0_OVF_vect) {

// code below runs every "semisecond" or
// every 0.99 microseconds (1.01 khz)
system_semitick();
time_semitick();
buttons_semitick();
alarm_semitick();
Expand All @@ -176,6 +190,9 @@ ISR(TIMER0_OVF_vect) {
#ifdef GPS_TIMEKEEPING
gps_semitick();
#endif // GPS_TIMEKEEPING
#ifdef TEMPERATURE_SENSOR
temp_semitick();
#endif // TEMPERATURE_SENSOR

semitick_successful = 1;
}
Expand All @@ -199,12 +216,16 @@ ISR(ANALOG_COMP_vect) {
buttons_sleep(); // disable button pull-up resistors
time_sleep(); // save current time
mode_sleep(); // does nothing
#ifdef TEMPERATURE_SENSOR
temp_sleep();
#endif // TEMPERATURE_SENSOR
#ifdef GPS_TIMEKEEPING
gps_sleep(); // disable usart rx interrupt
#endif // GPS_TIMEKEEPING
#if defined(DEBUG) || defined(GPS_TIMEKEEPING)
usart_sleep(); // disable usart
#endif // DEBUG || GPS_TIMEKEEPING
system_sleep(); // pulls PC5 low, if necessary
pizo_sleep(); // adjust buzzer for slower clock

// the bod settings allow the clock to run a battery down to 1.7 - 2.0v.
Expand All @@ -220,6 +241,7 @@ ISR(ANALOG_COMP_vect) {
sei(); // allow interrupts

pizo_wake(); // adjust buzzer for faster clock
system_wake(); // pulls PC5 high, if necessary
mode_wake(); // display time after waking
buttons_wake(); // enable button pull-ups
alarm_wake(); // enable alarm switch pull-up
Expand All @@ -229,5 +251,8 @@ ISR(ANALOG_COMP_vect) {
#ifdef GPS_TIMEKEEPING
gps_wake(); // enable usart rx interrupt
#endif // GPS_TIMEKEEPING
#ifdef TEMPERATURE_SENSOR
temp_wake();
#endif // TEMPERATURE_SENSOR
display_wake(); // start boost timer and enable display
}
14 changes: 13 additions & 1 deletion mode.c
Expand Up @@ -18,6 +18,7 @@
#include "buttons.h" // for processing button presses
#include "gps.h" // for setting the utc offset
#include "usart.h" // for debugging output
#include "temp.h" // for displaying current temperature


// extern'ed clock mode data
Expand Down Expand Up @@ -116,11 +117,16 @@ void mode_semitick(void) {
if(time.dateformat & TIME_DATEFORMAT_SHOWYEAR) {
mode_update(MODE_YEAR_DISPLAY, DISPLAY_TRANS_LEFT);
} else {
mode_update(MODE_TIME_DISPLAY, DISPLAY_TRANS_UP);
mode_update(MODE_TEMP_DISPLAY, DISPLAY_TRANS_LEFT);
}
}
return; // time ourselves; skip code below
case MODE_YEAR_DISPLAY:
if(btn || ++mode.timer > 1250) {
mode_update(MODE_TEMP_DISPLAY, DISPLAY_TRANS_LEFT);
}
return; // time ourselves; skip code below
case MODE_TEMP_DISPLAY:
if(btn || ++mode.timer > 1250) {
mode_update(MODE_TIME_DISPLAY, DISPLAY_TRANS_UP);
}
Expand Down Expand Up @@ -1447,6 +1453,12 @@ void mode_update(uint8_t new_state, uint8_t disp_trans) {
display_digit(5, time.year / 10);
display_digit(6, time.year % 10);
break;
case MODE_TEMP_DISPLAY:
display_pstr(0, PSTR(" xx \370F"));
int16_t degF = temp_degF();
display_digit(3, degF / 10);
display_digit(4, degF % 10);
break;
case MODE_ALARMSET_DISPLAY:
display_pstr(0, PSTR("alar set"));
break;
Expand Down
1 change: 1 addition & 0 deletions mode.h
Expand Up @@ -16,6 +16,7 @@ enum {
MODE_DAYOFWEEK_DISPLAY,
MODE_MONTHDAY_DISPLAY,
MODE_YEAR_DISPLAY,
MODE_TEMP_DISPLAY,
MODE_ALARMSET_DISPLAY,
MODE_ALARMIDX_DISPLAY,
MODE_ALARMTIME_DISPLAY,
Expand Down
36 changes: 31 additions & 5 deletions system.c
@@ -1,8 +1,9 @@
// system.c -- system functions (idle, sleep, interrupts)
//
// PB4 (MISO) unused pin
// PC2 unused pin
// PC1 power from voltage regulator
// PC5 photoresistor pull-up / temperature sensor power
// PC2 1-Wire bus for temperature sensor
// PC1 unused pin or power from voltage regulator
// AIN1 (PD7) divided system voltage
// analog comparator detects low voltage (AIN1)
//
Expand Down Expand Up @@ -37,12 +38,22 @@ void system_init(void) {

// enable pull-up resistors on unused pins to ensure a defined value
PORTB |= _BV(PB4);
#ifdef PICO_POWER
PORTC |= _BV(PC2);

#if defined(TEMPERATURE_SENSOR) || defined(AUTOMATIC_DIMMER)
DDRC |= _BV(PC5); // set pin as output
PORTC &= ~_BV(PC5); // pull to ground
#else
PORTC |= _BV(PC2) | _BV(PC1);
PORTC |= _BV(PC5); // enable pull-up
#endif // TEMPERATURE_SENSOR || AUTOMATIC_DIMMER

#ifndef PICO_POWER
PORTC |= _BV(PC2);
#endif // PICO_POWER

#ifndef TEMPERATURE_SENSOR
PORTC |= _BV(PC1);
#endif // TEMPERATURE_SENSOR

// use internal bandgap as reference for analog comparator
// and enable analog comparator interrupt on falling edge
// of AIN1 (interrupt triggers when adaptor power fails)
Expand All @@ -56,6 +67,21 @@ void system_init(void) {
power_all_disable();
}

#if defined(TEMPERATURE_SENSOR) || defined(AUTOMATIC_DIMMER)
// pull power indicator pin high when waking
void system_wake(void) {
PORTC |= _BV(PC5);
}
#endif // TEMPERATURE_SENSOR || AUTOMATIC_DIMMER


#if defined(TEMPERATURE_SENSOR) || defined(AUTOMATIC_DIMMER)
// place managed pins in low power state
void system_sleep(void) {
PORTC &= ~_BV(PC5); // pull low when sleeping
}
#endif // TEMPERATURE_SENSOR || AUTOMATIC_DIMMER


// repeatedly enter idle mode forevermore
void system_idle_loop(void) {
Expand Down

0 comments on commit 32e1425

Please sign in to comment.