Atmega16 automatic water filling system

Publisher:blq0681Latest update time:2016-10-24 Source: eefocusKeywords:Atmega16 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
//The question requires designing an automatic water filling system, using two water pipes to fill the water tank, and being able to display time and quality

//The following is the program for the automatic water filling system. Use the infrared remote control to set the water level. Four scales can be set: 500g, 1000g, 1500g, and 2000g.
//Use the electrode method, that is, pass 12V into the water tank, place four wires on the set scale line, and connect them to the four I/O ports of Atmega16 respectively.
//Control the 12V water pump by controlling the 5V relay. When the water reaches the set water level, the water pump stops pumping, the buzzer sounds, and the LED light flashes.
#include
#include
#include
#include"12864.h"
#define BIT(bit) (1<<(bit))
uchar show_set_flag; //Show the set quality flag
uchar end_flag=1;
uchar end_count; //Number of times the water reaches the scale
uchar second,minute; //Seconds, minutes
uchar count;//Number of infrared decoded codes
uint now_quality,set_quality;//Actual quality, set quality
uint s_count;
uint date_code;//Address code and address inverse code obtained by infrared decoding
void display()//Display function
{
 uchar shuju[5];
 uchar i;
 if(end_flag==0)//If end_flag==0, water starts to enter
 {
  shuju[0]=minute/10+48;//Tens digit
  shuju[1]=minute%10+48;//Ones digit
  shuju[2]=':';
  shuju[3]=second/10+48;//Tens digit
  shuju[4]=second%10+48;//Ones digit
  set_position(0,3);
  for(i=0;i<5;i++)
  {
   write_date(shuju[i]);
  }
 // write_date('g');
 }
 if(show_set_flag)//Display set quality
 {
  shuju[0]=set_quality/1000+48;//thousands
  shuju[1]=set_quality/100%10+48;//hundreds
  shuju[2]=set_quality%100/10+48;//tens
  shuju[3]=set_quality%10+48;//units
  set_position(1,5);
  for(i=0;i<4;i++)
  {
   write_date(shuju[i]);
  } 
  write_date('g');
  set_position(3,0);
  show_string(" ");
  show_set_flag=0;
   
 }
// set_position(1,0);
// show_string(L7);//display string
}
void quality_display()//display of current quality
{
 uchar zhiliang[4];
 uchar i;
 zhiliang[0]=now_quality/1000+48;//thousands
 digitzhiliang[1]=now_quality/100%10+48;//hundreds
 digitzhiliang[2]=now_quality%100/10+48;//tens
 digitzhiliang[3]=now_quality%10+48;//units
 digitset_position(2,5);
 for(i=0;i<4;i++)
 {
  write_date(zhiliang[i]);
 } 
 write_date('g');
}
void Bee()//buzzer alarm, when the set water level is reached, the buzzer sounds and the LED flashes
{
 uchar i,j;
 for(j=0;j<7;j++)
 {
  for(i=0;i<100;i++)
  {
   PORTB^=BIT(PB0);
   _delay_ms(3);
  }
 }
}
void moden_500g()//set the water level to 500g mode
{
 if(!(PINB&BIT(PB1)))//Judge whether the water level has reached the 500g mark
 {
 // if((PINB&BIT(PB2)==1)&&(PINB&BIT(PB3)===1)&&(PINA&BIT(PA3)==1)
  _delay_ms(5);//Delay to prevent misoperationif
  (!(PINB&BIT(PB1)))//Judge again whether the water level has reached the scale
  {
   PORTD&=~(BIT(PD0)|BIT(PD1));//Output 0, i.e. close the solenoid valve
   end_flag=1;
   TIMSK&=~BIT(TOIE0);//Disable timer 0 overflow interrupt enable
   now_quality=500;
   quality_display();
   set_position(3,0);
   show_string("reached set quality");
   Bee();
   end_count=1;
  }
 }
}

void moden_1000g()//Set the water level to 1000g mode
{
 if(end_count==0)//Judge whether the water level has reached the 500g scale
 {
  if(!(PINB&BIT(PB1)))
  {
   _delay_ms(5);
   if(!(PINB&BIT(PB1)))
   {
    end_count=1;
    now_quality=500;
    quality_display();
    }
  }
 }
 else//If the water level exceeds 500g but has not reached the 1000g scale
 {
 //if((PINB&BIT(PB1)==0)&&(PINB&BIT(PB3)===1)&&(PINA&BIT(PA3)==1)
  if(!(PINB&BIT(PB2)))//Judge whether the water level has reached the 1000g scale
  {
   _delay_ms(5);
   if(!(PINB&BIT(PB2)))
   {
    PORTD&=~(BIT(PD0)|BIT(PD1));//Output 0, i.e. close the solenoid valveend_flag
    =1;
    TIMSK&=~BIT(TOIE0);//Disable timer 0 overflow interrupt
    enablenow_quality=1000;
    quality_display();
    set_position(3,0);
    show_string("reached the set quality");
    Bee();
    end_count=2;
   }
  }
 }
}

void moden_1500g()//Set the water level to 1500g mode
{
 if(end_count==0)//Judge whether the water level has reached the 500g scale
 {
  if(!(PINB&BIT(PB1)))
  {
   _delay_ms(5);
   if(!(PINB&BIT(PB1)))
   {
    end_count=1;
    now_quality=500;
    quality_display();
    }
  }
 }
 else if(end_count<2)//If the water level exceeds 500g but has not reached the 1000g scale
 {
  if(!(PINB&BIT(PB2)))//Judge whether the water level has reached the 1000g scale
  {
   _delay_ms(5);
   if(!(PINB&BIT(PB2)))
   {
    end_count=2;
    now_quality=1000;
    quality_display();
   }
  }
 }
 else //If the water level exceeds the 1000g mark but does not reach the 1500g mark
 {
  if(!(PINB&BIT(PB3)))//Judge whether the water level has reached the 1500g mark
  {
   _delay_ms(5);
   if(!(PINB&BIT(PB3)))
   {
    PORTD&=~(BIT(PD0)|BIT(PD1));//Output 0, i.e. close the solenoid valveend_flag
    =1;
    TIMSK&=~BIT(TOIE0);//Disable timer 0 overflow interrupt enablenow_quality
    =1500;
    quality_display();
    set_position(3,0);
    show_string("Arrived at the set quality");
    Bee();
    end_count=3;
   }
  }
 } 
}

void moden_2000g()//Set the water level to 2000g mode
{
 if(end_count==0)//Judge whether the water level has reached the 500g scale
 {
  if(!(PINB&BIT(PB1)))
  {
   _delay_ms(5);
   if(!(PINB&BIT(PB1)))
   {
    end_count=1;
    now_quality=500;
    quality_display();
    }
  }
 }
 else if(end_count<2)//If the water level exceeds 500g but has not reached the 1000g scale
 {
  if(!(PINB&BIT(PB2)))
  {
   _delay_ms(5);
   if(!(PINB&BIT(PB2)))
   {
    end_count=2;
    now_quality=1000;
    quality_display();
   }
  }
 }
 else if(end_count<3)//If the water level exceeds the 1000g mark but does not reach the 1500g mark
 {
  if(!(PINB&BIT(PB3)))
  {
   _delay_ms(5);
   if(!(PINB&BIT(PB3)))
   {
    end_count=3;
    now_quality=1500;
    quality_display();
   }
  }
 }
 else //If the water level exceeds the 1500g mark but does not reach the 2000g mark
 {
  if(!(PINA&BIT(PA3)))//Judge whether the water level has reached the 2000g mark
  {
   _delay_ms(5);
   if(!(PINA&BIT(PA3)))
   {
    PORTD&=~(BIT(PD0)|BIT(PD1));//Output 0, i.e. close the solenoid
    valveend_flag=1;
    TIMSK&=~BIT(TOIE0); //Disable timer 0 overflow interrupt enable
    now_quality=2000;
    quality_display();
    set_position(3,0);
    show_string("reached set quality");
    Bee();
    end_count=4;
   }
  }
 }
}
void init()//initialization function
{
 DDRA|=BIT(PA7)|BIT(PA6)|BIT(PA5);//Set the 6th bit of PA port (RS control pin of 12864) and the 7th bit (EN control pin of 12864) to output
 DDRA&=~BIT(PA3);//Set the 3rd bit of PA port to input, connect to the water level line
 PORTA|=BIT(PA3);//Enable the pull-up resistor of the 3rd bit of PA port
 DDRB&=~(BIT(PB1)|BIT(PB2)|BIT(PB3));//PB port 1, 2, 3 bits are input, connect to the water level line
 DDRB|=BIT(PB0);//Set PB0 port to output, control the buzzer and LED
 PORTB&=~BIT(PB0);//PB0 port outputs 0, turns off the buzzer and LED 
 PORTB|=BIT(PB1)|BIT(PB2)|BIT(PB3);//Enable the pull-up resistor of the high four bits of the PD port
 DDRC=0xff;//Set all to output
 DDRD&=~BIT(PD6);//Set the ICP1 pin to input
 DDRD|=BIT(PD0)|BIT(PD1);//Set PD0 and PD1 ports to output, control the relay and then control the solenoid valve
 PORTD|=BIT(PD6);//Enable the pull-up resistor of the ICP1 pin
 PORTD&=~(BIT(PD0)|BIT(PD1));//Output 0, that is, close the solenoid valve
 TCNT1=0;//Initial value is 0
 TIMSK=BIT(TICIE1)|BIT(TOIE0);//Input capture interrupt enable, timer 0 overflow interrupt enable;
 sei(); //Open the total interrupt
 TCCR1B=BIT(ICNC1)|BIT(CS11); //8 division, and start timer 1. After 8 division, the 8M crystal oscillator counts at a speed of 1M, that is, it counts once every 1us.
// TCNT0=55; //The initial value is 55, that is, it counts 255-55=200 times, overflows and enters the timer 0 interrupt function
// TCCR0|=_BV(CS01); //8 division, and start timer 0. After 8 division, the 8M crystal oscillator counts at a speed of 1M, that is, it counts once every 1us, and counting 100 times is 100us, that is, it enters the timer 0 interrupt function once every 100us
 init_12864(); //12864 LCD initialization 
 set_position(0,0);
 show_string("Time: "); //Display string 
 set_position(1,0);
 show_string("Quality settings: ");
 set_position(2,0);
 show_string("Quality: ");
}
int main()

 init();

 while(1)
 {
   
  if(end_flag==0)
  {
   switch(set_quality)
   {
    case 500:moden_500g();break;//Set the water level to 500g mode
    case 1000:moden_1000g();break;//Set the water level to 1000g mode
    case 1500:moden_1500g();break;//Set the water level to 1500g mode
    case 2000:moden_2000g();break;//Set the water level to 2000g mode
   }
  }
  display();//Display
 }
}

volatile uint ICP_lastValue=0,ICP_value=0,time=0;
ISR(TIMER1_CAPT_vect)//ICP input capture interrupt function, input pin is ICP1 PD6 (pin 20)
{
 ICP_value=ICR1;//Read the time when the ICP input capture event occurs
 if(ICP_lastValue>ICP_value)time=0xffff-ICP_lastValue+1+ICP_value;//Calculate the time taken between two falling edges
 else time=ICP_value-ICP_lastValue;
 //TIFR|=BIT(ICF1);//This statement is optional, because ICF1 is automatically cleared to 0 when the interrupt is executed, and this statement can also be used to implement software clearing
 ICP_lastValue=ICP_value;
 if(time>950&&time<1225)time=0;
 else if(time>2050&&time<2345)time=1; 
 else if(time>13325&&time<13600)//Judge the leading code
 {
  date_code=0;
  count=0;
  return;
 }
 else {return;}//Remove interference. This statement works when the falling edge and the end code when preparing to enter the leading code are received. Without this statement, it can only receive once
 count++;
 if(count>16&&count<32)
 {
  date_code=date_code|time;
  date_code=date_code<<1;
 }
 else if(count==32)//Receive 32 bits

 {
  date_code=date_code|time;
  PORTB^=BIT(PB0);
  _delay_ms(7);
  PORTB^=BIT(PB0);
  _delay_ms(7);
  if(end_flag)
  {
   switch(date_code)
   {
    case 0x807f:set_quality=500; show_set_flag=1;break;//1
    case 0x40bf:set_quality=1000;show_set_flag=1;break;//2
    case 0xc03f:set_quality=1500;show_set_flag=1;break;//3
    case 0x20df:set_quality=2000;show_set_flag= 1;break;//4
    case 0x30cf:{
         if(set_quality>now_quality)
         {
          s_count=0;
          second=0;
          minute=0;
          end_flag=0;
          TIMSK|=BIT(TOIE0); //Enable timer 0 overflow interrupt
          TCNT0=55; //The initial value is 55, that is, count 255-55=200 overflows and enter the timer 0 interrupt function
          TCCR0|=BIT (CS01); //8 division, and start timer 0. After 8M crystal is divided by 8, it counts at a speed of 1M, that is, it counts once every 1us, and 100 times is 100us, that is, 100us Enter the timer 0 interrupt function
          PORTD|=BIT(PD0)|BIT(PD1); //output 1, that is, open the solenoid valve to let water flow into the tank

         }
         else 
         {
          set_position(3,0);
          show_string("Please reset");   
         }
         break;
        }
   }
  }
 }
}

SIGNAL(SIG_OVERFLOW0)//Timer 0 interrupt service function
{
 TCNT0=55;
 s_count++;
 if(s_count>=4900)
 {
  s_count=0;
  second++;
  if(second==60)
  {
   second=0;
   minute++;
   if(minute==60)
   {
    minute=0;
   }
  }
 }
}

//12864 LCD display header file

#define uchar unsigned char
#define uint unsigned int
//Bit 5 of PA port (parallel/serial interface selection control pin of 12864)
#define PSB PORTA |= (1 << 5) //Bit 5 outputs high level parallel port mode
//Bit 6 of PA port (RS control pin of 12864) and bit 7 (EN control pin of 12864)
//Data command end
#define lcdrs_L PORTA &= ~(1 << 6) //Bit 6 outputs low level command
#define lcdrs_H PORTA |= (1 << 6) //Bit 6 outputs high level data
//Enable end
#define lcden_L PORTA &= ~(1 << 7) //Bit 7 outputs low level disable enable
#define lcden_H PORTA |= (1 << 7) //Bit 7 outputs high level enable void
write_com(uchar com)//write command function
{
 lcdrs_L;
 PORTC=com;
 _delay_ms(5);
 lcden_H;
 _delay_ms(5);
 lcden_L;
}
void write_date(uchar date)//write data function
{
 lcdrs_H;
 PORTC=date;
 _delay_ms(5);
 lcden_H;
 _delay_ms(5);
 lcden_L;
}
void init_12864()//12864 LCD initialization function
{
 PSB;//parallel port mode
 lcden_L;//enable first
 write_com(0x30);//basic instruction set expansion instruction set is 0x34
 _delay_ms(5);
 write_com(0x01);//clear screen
 _delay_ms(5);
 write_com(0x0c);//turn on display, do not display cursor, cursor does not blink
 _delay_ms(5);
 write_com(0x02);//Clear the address counter and put the cursor back to the origin
 _delay_ms(5);
 write_com(0x80);//Start displaying from this address Start displaying from the origin
 _delay_ms(5);
 //write_com(0x18); Execute once, the whole screen moves left once
 //write_com(0x1c); Execute once, the whole screen moves right once

}
void set_position(uchar x, uchar y)
{
 uchar position=0;
 switch(x%4)
  {
  case 0: position=0x80;break; //first line start address
  case 1: position=0x90;break; //second line
  case 2: position=0x88;break; //third line
  case 3: position=0x98;break; //fourth line
  }
 position+=y;//coordinates to be displayed
 write_com(position);
}
void show_string(uchar *string)//display string function
{
 while(*string)
 {
  write_date(*string++);
 }
}

Keywords:Atmega16 Reference address:Atmega16 automatic water filling system

Previous article:Atmega16 Timer 0 usage
Next article:IR remote control decoding with Atmega16 input capture function

Recommended ReadingLatest update time:2024-11-16 14:58

ATMEGA16 microcontroller keyboard and display circuit
The input and display circuit uses 4 buttons and function switching to complete the setting of output voltage and display switching. The display part uses a common anode digital tube for dynamic display, as shown in the figure. The single-chip microcomputer ATMEGA16 uses an internal 8 MHz crystal oscillator. Figure
[Microcontroller]
ATMEGA16 microcontroller keyboard and display circuit
atmega16 vs ad530
#include #include macros.h #define   uchar unsigned char #define   uint   unsigned int void delay() {     uchar i;   for(i=0;i 100;i++); } void init() {      DDRB|=0XA0;    DDRA|=BIT(PA1);      SPCR=0X57; } void ad5300(uchar x) {      uchar temp1=0,temp2=0,status;    temp1|=x 4;    temp2|=x 4;    
[Microcontroller]
AVR microcontroller Atmega16 electronic clock program + simulation, internal timer implementation
Atmega16 electronic clock, internal timer, adjustable alarm. The simulation schematic diagram is as follows, and   the microcontroller source program is as follows: #include iom16v.h #include macros.h #define  key_bz    0b00000111 char smg_zx ={0x3f,0x06,0x5b,0x4f,0x66,0x6d, 0x7d,0x07,0x7f,0x6f}; // global variab
[Microcontroller]
AVR microcontroller Atmega16 electronic clock program + simulation, internal timer implementation
DS18B20 temperature measurement program based on ATMEGA16
Download the complete program source code: http://www.51hei.com/f/avrds.rar main function: /* Program function: 18B20 temperature measurement results are displayed on 1602 LCD Author: Zhu Bo Date: January 31, 2012 Description: PA5 is the input port 18B20 parameters: temper
[Microcontroller]
DS18B20 temperature measurement program based on ATMEGA16
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号