SparkFun Forums 

Where electronics enthusiasts find answers.

Discussions on the software and hardware for Atmel's STK standard.
By enmsh
#128245
here is ,if condition to compare between constant temperature(Tl,Th)and the readable temperature T.
the lamp didn't respond to change in T .it doesn't switch on if T below the range or off when it is out of range
Code: Select all
#include <stdio.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "lcd_lib.h"

//adjust LCDsendChar() function for stream
static int LCDsendstream(char c, FILE *stream);
//----set output stream to LCD-------
static FILE lcd_str = FDEV_SETUP_STREAM(LCDsendstream, NULL, _FDEV_SETUP_WRITE);


void delay1s(void);
void adc_init(void);
void adc_start_conversion(uint8_t);
static int LCDsendstream(char c , FILE *stream);
void init(void);
void init_interrupt0(void);

//current channel
uint8_t ch;
volatile uint16_t temp_current;
volatile uint8_t temp_min=20;
volatile uint8_t temp_max=27;
char x,j;
//strings for LCD stored in Flash memory
const uint8_t temp[] PROGMEM="temp:\0";
const uint8_t celsuis[] PROGMEM="C \0";
const uint8_t enterlowtemp[] PROGMEM="enterlowtemp\0";
const uint8_t enterHItemp[] PROGMEM="enterHItemp\0";
const uint8_t MENU[] PROGMEM="MENU\0";
const uint8_t UP[] PROGMEM="UP\0";
const uint8_t OK[] PROGMEM="OK\0";

const uint8_t Tl[] PROGMEM="Tl=\0";
const uint8_t Th[] PROGMEM="Th=\0";

const uint8_t CLRROW[] PROGMEM="                \0";
const uint8_t *LCDXY[] ={
		temp,	//for ADC0
		enterlowtemp,Tl,enterHItemp,Th,MENU,UP,OK};	



//  ADC module initialization 
//
//*****************************************************************************
void adc_init(void)
{
//select reference voltage
//AVCC with external capacitor at AREF pin
ADMUX|=(0<<REFS1)|(1<<REFS0);
//set prescaller and enable ADC
ADCSRA|=(1<<ADEN)|(1<<ADIE);//enable ADC with dummy conversion
//set sleep mode for ADC noise reduction conversion
//set_sleep_mode(SLEEP_MODE_ADC);

}
//*****************************************************************************
//
//  ADC single conversion routine 
//
//*****************************************************************************
void adc_start_conversion(uint8_t channel)
{
//remember current ADC channel;
ch=channel;
//set ADC channel
ADMUX=(ADMUX&0xF0);
//Start conversionio with Interupt after conversion
//enable global interrupts
	//continue infinitely

sei();
ADCSRA |= (1<<ADSC)|(1<<ADIE);

}

//
//  delay 1s 
//
//*****************************************************************************

//delay 1s
void delay1s(void)
{
	uint8_t i;
	for(i=0;i<100;i++)
	{
		_delay_ms(10);
	}
}

//*****************************************************************************
//
//  Set LCD stream function 
//
//*****************************************************************************
static int LCDsendstream(char c , FILE *stream)
{
LCDsendChar(c);
return 0;
}

//*****************************************************************************
//
//  init AVR
//
//*****************************************************************************

void init(void)
{
	//init stream
	stdout = &lcd_str;
	//init LCD
	LCDinit();//init LCD bit, dual line, cursor right
	LCDclr();//clears LCD
	LCDGotoXY(0, 0);//Cursor Home
	//Init ADC
	adc_init();

}

//
//  ADC conversion complete service routine 
//
//*****************************************************************************
ISR(ADC_vect)
{  
    
	uint16_t adc_value;
	adc_value = (((unsigned long)ADC*500+512)/1024);  
		
	CopyStringtoLCD(CLRROW, 0, ch );
	CopyStringtoLCD(LCDXY[(ch)], 0, ch );
	
	//LCDGotoXY(6, 0);
	printf("%d", adc_value);
    CopyStringtoLCD(celsuis,9, 0);
	LCDGotoXY(7, 0);
	LCDsendChar(0xDF);
	
	temp_current=adc_value;
    
	
  }
	

//*****************************************************************************
//
//  run analog digital converter, timer. 
//
//*****************************************************************************

int main(void)
{
	
	init();
	printf("temp.controller");
	
	DDRB |= 0x10; 
	delay1s();
	while(1)//loop demos
	{
	//read lm35
	
	adc_start_conversion(0);
	_delay_ms(50);
   
    CopyStringtoLCD(MENU, 12, 1);

   if (((temp_min<temp_current)&&(temp_current<temp_max))||(temp_current>temp_max))  // compare       temperature
	{
	   PORTB |= 0x00; //make Bit 4 of PORTB low to turn LED off
	 }

    else if  (temp_current<temp_min)//&&(PINC & 0x04))// if temp< low & press ok
	{
	PORTB |= 0x10; //make Bit 4 of PORTB High to turn LED on
	}
	
	init_interrupt0();
 
   }
	return 0;
	
}
By n1ist
#128336
A few issues:

- You have a volatile uint16. You need to turn off interrupts before accessing it in the mainline code, and back on right afterwards. Otherwise, if an interrupt happens between reading the low and high bytes of it, you will end up with a garbage result.

- ISRs need to be "lean and mean". They should not call slow functions like printf or LCD ones (that likely have delays in them) or functions that may depend on other interrupts. Generally, ISRs just read or write the hardware and set flags.

- This won't do what you think. You need to use AND to turn bits off, and OR to turn them on.
Code: Select all
PORTB |= 0x00; //make Bit 4 of PORTB low to turn LED off
- You don't show the code for init_interrupt0();

- I would prefer to see the sei(); in the mainline rather than in adc_start_conversion(). Normally, you configure all the periphals, turn on interrupts, and then wait for them.
By enmsh
#128542
yes the problem was in AND , I FORGET IT .
I have another problem when I pressed the reset button ,it resets the atmega after that it dispalys the data very fast on lcd and moving it .
Is there problem with connection ?
the pin is connected to high ,when i pressed it becomes connected to ground.
By OrlandoArias
#130444
enmsh wrote:the pin is connected to high ,when i pressed it becomes connected to ground.
Not sure I follow this properly, but if you have something like:
Code: Select all
              ____
GND |---------.  .---------+--------| Vcc
                           |
                         ~RES
You need a pull up resistor between Vcc the RESET pin, otherwise, when you press the button, you will short the line, which is what may be causing your LCD to go wild like that [Vcc line becomes really unstable]. The datasheet for the chip you are using should give you a good value for the pullup. From the AVRISP mkII manual:
The Reset line should not have a stronger pull up than 4.7k ohm. Any de-coupling capacitor should not be larger than 10uF.