NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Project Help and Ideas » can this be done?

May 22, 2010
by cinta51
cinta51's Avatar

ok well here was my idea when buying the nerd kit. i would like to build a automatic frozen fish feeder for my saltwater tank. what I would like the controller to do is:

  1. be able to keep a box that holds the frozen food at a set temp.
  2. be able to program what time of day to dispence the food (up to 4 times a day)
  3. I will have a step motor that turns a feed screw to dispence the food.

i already have the step motor and a few thermo units along with other things but will I be able to make my dream come true with this?

I am tring to learn c code but it is turing out to be harder than I thought but I am trying.

thanks for any help.

Sam

May 23, 2010
by n3ueaEMTP
n3ueaEMTP's Avatar

Cinta51, That sounds like a fun project. I worked on a similar project for work (keeping IV fluid at a set temp) but never actually built the device. I would suggest merging the Real Time Clock tutorial with the tempsensor.c project that came with your NK. This way, you can have the RTC time to a certain amount of time, dispense the food and then reset to start over. The tempsensor.c code could monitor the frozen food temp. Is it safe to assume that the four feeding times will occur at regular intervals every 6 hours? If so, you could use a state machine with the timeout set to 216000 milliseconds (360minutes).

Here is the code that I had adapted from some of the code included with my NK, hopefully it will help you:

// fluidwarmer.c
// for NerdKits with ATmega168
// adaptation of tempsenor.c by Mike Robbins (mrobbins@mit.edu)
//by Christopher J Buchmoyer

#define F_CPU 14745600

#include <stdio.h>
#include <math.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"
#include "../libnerdkits/uart.h"

// PIN DEFINITIONS: // // PC0 -- temperature sensor analog input // PC1 -- temperature sensor analog input // PC2 -- temperature sensor analog input // PC3 -- temperature sensor analog input

void set_lights(uint8_t lights) { // the bits of lights tells us which LEDs to turn on:

// set outputs PORTB &= ~(0x07 << PB1); PORTB |= ((lights >> 4) & (0x07)) << PB1; }

void speaker_off() { TCCR1A &= ~(1<<COM1A0); }

void speaker_on() { TCCR1A |= (1<<COM1A0); }

void adc_init() { // set analog to digital converter // for external reference (5v)

// set analog to digital converter // to be enabled, with a clock prescale of 1/128 // so that the ADC clock runs at 115.2kHz. ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);

// fire a conversion just to get the ADC warmed up ADCSRA |= (1<<ADSC); }

uint16_t adc_read() { // read from ADC, waiting for conversion to finish // (assumes someone else asked for a conversion.) // wait for it to be cleared while(ADCSRA & (1<<ADSC)) { // do nothing... just hold your breath. } // bit is cleared, so we have a result.

// read from the ADCL/ADCH registers, and combine the result // Note: ADCL must be read first (datasheet pp. 259) uint16_t result = ADCL; uint16_t temp = ADCH; result = result + (temp<<8);

// set ADSC bit to get the next conversion started ADCSRA |= (1<<ADSC);

return result; }

double sampleToFahrenheit(uint16_t sample) { // conversion ratio in DEGREES/STEP: // (5000 mV / 1024 steps) * (1 degree / 10mV) // ^^^ ^^ // from ADC from LM34 return sample * (5000.0 / 1024.0 / 10.0);
}

int main() {

// set PB4,PB5 as output DDRB |= (1<<PB5) | (1<<PB4) |(1<<PB3) | (1<<PB2);

// start up the LCD lcd_init(); FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE); lcd_home();

// start up the Analog to Digital Converter adc_init();

// start up the serial port uart_init(); FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW); stdin = stdout = &uart_stream;

// use Timer1 for buzzer sound. // CTC mode, WGM12 TCCR1B |= (1<<WGM12); // enable output pin to toggle on match //TCCR1A = (1<<COM1A0); // see speaker_on() // toggle on 255 overflow, and get 450Hz OCR1AH = 0; OCR1AL = 255; // divide the 14.7456MHz by 64 TCCR1B |= (1<<CS11) | (1<<CS10);

// holder variables for temperature data uint16_t last_sample1 = 0; uint16_t last_sample2 = 0; uint16_t last_sample3 = 0; uint16_t last_sample4 = 0; uint16_t avg_temp = 0; double this_temp; double temp_avg; uint16_t i;

while(1) { // take 400 samples and average them! temp_avg = 0.0; for(i=0; i<400; i++) { ADMUX = 0; last_sample1 = adc_read(); ADMUX = 1; last_sample2 = adc_read(); ADMUX = 2; last_sample3 = adc_read(); ADMUX = 3; last_sample4 = adc_read(); avg_temp = (last_sample1 + last_sample2 + last_sample3 + last_sample4)/4; this_temp = sampleToFahrenheit(avg_temp);

  // add this contribution to the average
  temp_avg = temp_avg + this_temp/400.0;
}
//turns heating element on if less than 99 degrees and off if above 103 degrees
if(temp_avg >= 103) 
    {
    PORTB &= ~(1<<PB4);
    lcd_line_two();
    fprintf_P(&lcd_stream, PSTR("Temp: %.1f"), temp_avg);
    lcd_write_data(0xdf);
    lcd_write_string(PSTR("F              "));
    }
if(temp_avg <= 99) 
    {
    PORTB |= (1<<PB4);
    lcd_line_two();
    fprintf_P(&lcd_stream, PSTR("Temp: %.1f"), temp_avg);
    lcd_write_data(0xdf);
    lcd_write_string(PSTR("F  Heater On"));
    }

 // write message to LCD & light appropiate LED
lcd_home();
if (temp_avg<98)
    {
    speaker_on();
    set_lights(0x00);
    PORTB |= (1<<PB5);
    lcd_write_string(PSTR("   WARNING LOW TEMP!!!     "));
    }
else if (temp_avg>104)
    {
    set_lights(0x40);
    speaker_on();
    PORTB &= ~(1<<PB5);
    lcd_write_string(PSTR("  WARNING HIGH TEMP!!!     "));
    lcd_line_two();
    fprintf_P(&lcd_stream, PSTR("Temp: %.1f"), temp_avg);
    lcd_write_data(0xdf);
    lcd_write_string(PSTR("F              "));
    }
else if ((temp_avg>98) && (temp_avg<104))
    {
    set_lights(0x20);
    PORTB &= ~(1<<PB5);
    speaker_off();
    lcd_write_string(PSTR("   TEMPERATURE NORMAL   "));
    lcd_line_two();
    fprintf_P(&lcd_stream, PSTR("Temp: %.1f"), temp_avg);
    lcd_write_data(0xdf);
    lcd_write_string(PSTR("F "));
    }

// write message to serial port
printf_P(PSTR("%.2f degrees F"), temp_avg);
if (temp_avg<98)
    {
    printf_P(PSTR("   WARNING LOW TEMP!!!       "));
    printf_P(PSTR("\7"));
    printf_P(PSTR(" Heater On     \r\n\n"));
    }
else if (temp_avg>105)
    {
    printf_P(PSTR("  WARNING HIGH TEMP!!!     \r\n\n"));
    printf_P(PSTR("\7"));
    }
else if ((temp_avg>98) && (temp_avg<104))
    {
    printf_P(PSTR("   TEMPERATURE NORMAL\r\n\n"));
    }

} return 0; }

I cannot guarantee this code will work as I have not tried it other than in simulations. Enjoy!

Chris B, n3ueaEMTP

Post a Reply

Please log in to post a reply.

Did you know that many systems in nature can be described by a first order response? Learn more...