Код: Выделить всё
/*
* main.cpp
* Project: G.E.C.K.
* Created: 21.10.2017 20:18:55
* Author: Сергей Набоков
*/
//КОНСТАНТЫ
#define F_CPU 16000000UL //задаем частоту МК
#define F_SCL 100000L //задаем частоту I2C
#define UART_Start_symbol '*' //Старт символ пакета
#define UART_Stop_symbol '#' //Стоп символ пакета
#define UART_buffer_size 255 //Буфер для служебного обмена данными с внутренними устройствами
#define Input_command_size 13 //Размер входного пакета данных
#define String_end_symbol '\0' //Стоп символ строки
#define RTC_module 0xD0 // Адрес RTC на шине I2C
#define LCD_module 0x7e // Адрес LCD на шине I2C
#define LCD_RS 0
#define LCD_RW 1
#define LCD_E 2
#define LCD_BL 3
//----------------------------------------
#define Device_type {"G.E.C.K. - HFG"}
#define Firmware_version {"FW: v1.5b"}
//-----------------------------------------
//БИБЛИОТЕКИ
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <avr/eeprom.h>
#include <avr/wdt.h>
//СТРУКТУРЫ
typedef struct {uint8_t HH;
uint8_t MM;
uint8_t SS;} Time;
typedef struct {uint8_t DD;
uint8_t MM;
uint8_t YY;} Date;
typedef struct {char Name[17];
uint8_t State;
uint8_t Auto_Enable;
uint8_t *EEPROM_AE;
Time Enable_Time;
uint8_t *EEPROM_ET_HH;
uint8_t *EEPROM_ET_MM;
uint8_t *EEPROM_ET_SS;
uint8_t Auto_Disable;
uint8_t *EEPROM_AD;
Time Disable_Time;
uint8_t *EEPROM_DT_HH;
uint8_t *EEPROM_DT_MM;
uint8_t *EEPROM_DT_SS;
uint8_t Cycle;
uint8_t *EEPROM_CYCLE;
uint8_t Cycle_Start_Day;
uint8_t *EEPROM_CSD;
uint8_t Water;
uint8_t Force_Enable;} Channel;
//ЭНЕРГОНЕЗАВИСИМАЯ ПАМЯТЬ
uint8_t System_first_run EEMEM = 0;
uint8_t White_light_AE EEMEM = 0;
uint8_t White_light_ET_HH EEMEM = 0;
uint8_t White_light_ET_MM EEMEM = 0;
uint8_t White_light_ET_SS EEMEM = 0;
uint8_t White_light_AD EEMEM = 0;
uint8_t White_light_DT_HH EEMEM = 0;
uint8_t White_light_DT_MM EEMEM = 0;
uint8_t White_light_DT_SS EEMEM = 0;
uint8_t White_light_CYCLE EEMEM = 0;
uint8_t White_light_CSD EEMEM = 1;
uint8_t Grow_light_AE EEMEM = 0;
uint8_t Grow_light_ET_HH EEMEM = 0;
uint8_t Grow_light_ET_MM EEMEM = 0;
uint8_t Grow_light_ET_SS EEMEM = 0;
uint8_t Grow_light_AD EEMEM = 0;
uint8_t Grow_light_DT_HH EEMEM = 0;
uint8_t Grow_light_DT_MM EEMEM = 0;
uint8_t Grow_light_DT_SS EEMEM = 0;
uint8_t Grow_light_CYCLE EEMEM = 0;
uint8_t Grow_light_CSD EEMEM = 1;
uint8_t Water_pump_AE EEMEM = 0;
uint8_t Water_pump_ET_HH EEMEM = 0;
uint8_t Water_pump_ET_MM EEMEM = 0;
uint8_t Water_pump_ET_SS EEMEM = 0;
uint8_t Water_pump_AD EEMEM = 0;
uint8_t Water_pump_DT_HH EEMEM = 0;
uint8_t Water_pump_DT_MM EEMEM = 0;
uint8_t Water_pump_DT_SS EEMEM = 0;
uint8_t Water_pump_CYCLE EEMEM = 0;
uint8_t Water_pump_CSD EEMEM = 1;
//ПЕРЕМЕННЫЕ
uint8_t Calendar[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; //Календарь
uint8_t Calendar_leap[12] = {31,29,31,30,31,30,31,31,30,31,30,31}; //Високосный календарь
bool RTC_error = false; //Ошибка модуля RTC
char UART_input_buffer[50];
bool UART_start_symbol_detected = false; //Обнаружен стартовый символ
bool UART_stop_symbol_detected = false; //Обнаружен стоповый символ
bool UART_user_control = true;
char Input_command[Input_command_size]; //Входящая команда
uint8_t IC_c = 0;
Time System_time = {0,0,0}; //Системное время
bool SST_command = false;
Time t_time = {0,0,0};
Date System_date = {0,0,0}; //Системная дата
bool SSD_command = false;
Date t_date = {0,0,0};
Channel White_light = {"White light:", //Холодный свет
0,
0,
&White_light_AE,
{0,0,0},
&White_light_ET_HH,
&White_light_ET_MM,
&White_light_ET_SS,
0,
&White_light_AD,
{0,0,0},
&White_light_DT_HH,
&White_light_DT_MM,
&White_light_DT_SS,
0,
&White_light_CYCLE,
1,
&White_light_CSD,
0,
0};
Channel Grow_light = {"Grow light:", //Фитосвет
0,
0,
&Grow_light_AE,
{0,0,0},
&Grow_light_ET_HH,
&Grow_light_ET_MM,
&Grow_light_ET_SS,
0,
&Grow_light_AD,
{0,0,0},
&Grow_light_DT_HH,
&Grow_light_DT_MM,
&Grow_light_DT_SS,
0,
&Grow_light_CYCLE,
1,
&Grow_light_CSD,
0,
0};
Channel Water_pump = {"Water pump:", //Насос
0,
0,
&Water_pump_AE,
{0,0,0},
&Water_pump_ET_HH,
&Water_pump_ET_MM,
&Water_pump_ET_SS,
0,
&Water_pump_AD,
{0,0,0},
&Water_pump_DT_HH,
&Water_pump_DT_MM,
&Water_pump_DT_SS,
0,
&Water_pump_CYCLE,
1,
&Water_pump_CSD,
1,
0};
Channel *t_channel;
bool SET_command = false;
bool SDT_command = false;
bool RCS_command = false;
bool SAE_command = false;
bool SAD_command = false;
bool SCS_command = false;
bool SCC_command = false;
bool RSI_command = false;
bool WP_ON_command = false;
Time WP_manual_time = {0,0,30};
bool LDS_command = false;
bool First_run = false;
bool Flash_time_string = true;
uint8_t I2C_last_device;
bool I2C_last_write_mode;
//===РАЗНОЕ===
void Segment_Normalize(char *d_t_segment)
{
if (strlen(d_t_segment)<2)
{
d_t_segment[2]=String_end_symbol;
d_t_segment[1]=d_t_segment[0];
d_t_segment[0]='0';
}
}
uint8_t BCD_to_INT(uint8_t BCD)
{
return (((BCD>>4)& 0b00001111)*10+(BCD & 0b00001111));
}
uint8_t INT_to_BCD(uint8_t Integer)
{
uint8_t BCD_1=0;
uint8_t BCD_2=0;
uint8_t j=0;
for (uint8_t i=0; i<90; i=i+10)
{
if (Integer-i<10 && Integer-i>=0)
{
BCD_1 = j;
BCD_2 = Integer-i;
}
j++;
}
return (((BCD_1<<4)&0b11110000)|(BCD_2&0b00001111));
}
void DATE_to_STRING(char *d_string, Date *date)
{
char Date_string[3];
char Month_string[3];
char Year_string[3];
itoa(date->DD,Date_string,10);
itoa(date->MM,Month_string,10);
itoa(date->YY,Year_string,10);
//Нормализация строки даты
Segment_Normalize(Date_string);
Segment_Normalize(Month_string);
Segment_Normalize(Year_string);
int dsi = 0;
//Дата
for (int di=0;di<strlen(Date_string);di++)
{
d_string[dsi] = Date_string[di];
dsi++;
}
d_string[dsi] = '.';
dsi++;
for (int mi=0;mi<strlen(Month_string);mi++)
{
d_string[dsi] = Month_string[mi];
dsi++;
}
d_string[dsi] = '.';
dsi++;
for (int yi=0;yi<strlen(Year_string);yi++)
{
d_string[dsi] = Year_string[yi];
dsi++;
}
d_string[dsi]= String_end_symbol;
}
void TIME_to_STRING(char *t_string, Time *time, bool show_sec=false, bool flash = false)
{
char Hours_string[3];
char Minutes_string[3];
char Seconds_string[3];
itoa(time->HH,Hours_string,10);
itoa(time->MM,Minutes_string,10);
itoa(time->SS,Seconds_string,10);
//Нормализация строки времени
Segment_Normalize(Hours_string);
Segment_Normalize(Minutes_string);
Segment_Normalize(Seconds_string);
char dots = ' ';
if ((time->SS % 2) == 1 && flash == true)
{
dots = ' ';
}
else
{
dots = ':';
}
int tsi = 0;
//Время
for (int hi=0;hi<strlen(Hours_string);hi++)
{
t_string[tsi] = Hours_string[hi];
tsi++;
}
t_string[tsi] = dots;
tsi++;
for (int mi=0;mi<strlen(Minutes_string);mi++)
{
t_string[tsi] = Minutes_string[mi];
tsi++;
}
if (show_sec == true)
{
t_string[tsi] = dots;
tsi++;
for (int si=0;si<strlen(Seconds_string);si++)
{
t_string[tsi] = Seconds_string[si];
tsi++;
}
}
t_string[tsi]= String_end_symbol;
}
void DATE_TIME_to_STRING(char *d_t_string, Date *date, Time *time, bool show_sec=false, bool flash = false)
{
char date_string[9];
char time_string[6];
DATE_to_STRING(date_string, date);
TIME_to_STRING(time_string, time, show_sec, flash);
int dtsi = 0;
//Дата
for (int i=0;i<strlen(date_string);i++)
{
d_t_string[dtsi] = date_string[i];
dtsi++;
}
d_t_string[dtsi] = ' ';
dtsi++;
d_t_string[dtsi] = ' ';
dtsi++;
d_t_string[dtsi] = ' ';
dtsi++;
//Время
for (int i=0;i<strlen(time_string);i++)
{
d_t_string[dtsi] = time_string[i];
dtsi++;
}
d_t_string[dtsi]= String_end_symbol;
}
bool String_Compare(char *ds1, char *ds2, int ds1_start_pos, int ds2_start_pos, int length)
{
bool Result = true;
for (int i = 0; i<length; i++)
{
if (ds1[i+ds1_start_pos] != ds2[i+ds2_start_pos])
{
Result = false;
}
}
return Result;
}
uint8_t Days_In_Month(uint8_t month, uint8_t year)
{
if (year%4 == 0 && year != 0)
{
return Calendar_leap[month-1];
}
else
{
return Calendar[month-1];
}
}
void Time_Add(Time *time, Time *add_time)
{
if ((time->SS + add_time->SS) >= 60)
{
time->MM++;
time->SS = time->SS + add_time->SS-60;
}
else
{
time->SS = time->SS + add_time->SS;
}
if ((time->MM + add_time->MM) >= 60)
{
time->HH++;
time->MM = time->MM + add_time->MM-60;
}
else
{
time->MM = time->MM + add_time->MM;
}
if ((time->HH + add_time->HH) >= 24)
{
time->HH = time->HH + add_time->HH - 24;
}
else
{
time->HH = time->HH + add_time->HH;
}
}
void Date_Add(Date *date, uint8_t days)
{
for (uint8_t i=0; i<days;i++)
{
date->DD++;
uint8_t d_i_m = Days_In_Month(date->MM, date->YY);
if (date->DD > d_i_m)
{
date->MM++;
if(date->MM >12)
{
date->YY++;
if(date->YY >99)
{
date->YY = date->YY - 99;
}
date->MM = date->MM -12;
}
date->DD = date->DD - d_i_m;
}
}
}
void (*Reset)(void) = 0x0000;
void Light_Channel_Enable_String(char *data_string, Channel *channel)
{
int chsi = 0;
char En_caption[] = {"On: "};
char En_time[9];
TIME_to_STRING(En_time, &channel->Enable_Time, 0);
for (int i=0;i<strlen(En_caption);i++)
{
data_string[chsi] = En_caption[i];
chsi++;
}
for (int i=0;i<strlen(En_time);i++)
{
data_string[chsi] = En_time[i];
chsi++;
}
data_string[chsi]= String_end_symbol;
}
void Light_Channel_Disable_String(char *data_string, Channel *channel)
{
int chsi = 0;
char Dis_caption[] = {"Off: "};
char Dis_time[9];
TIME_to_STRING(Dis_time, &channel->Disable_Time , 0);
for (int i=0;i<strlen(Dis_caption);i++)
{
data_string[chsi] = Dis_caption[i];
chsi++;
}
for (int i=0;i<strlen(Dis_time);i++)
{
data_string[chsi] = Dis_time[i];
chsi++;
}
data_string[chsi]= String_end_symbol;
}
void Water_Channel_Enable_String(char *data_string, Channel *channel)
{
int chsi = 0;
char En_caption[] = {"On: "};
char En_time[9];
TIME_to_STRING(En_time, &channel->Enable_Time, 1);
for (int i=0;i<strlen(En_caption);i++)
{
data_string[chsi] = En_caption[i];
chsi++;
}
for (int i=0;i<strlen(En_time);i++)
{
data_string[chsi] = En_time[i];
chsi++;
}
data_string[chsi]= String_end_symbol;
}
void Water_Channel_Disable_String(char *data_string, Channel *channel)
{
int chsi = 0;
char Dis_caption[] = {"Off: "};
char Dis_time[9];
TIME_to_STRING(Dis_time, &channel->Disable_Time , 1);
for (int i=0;i<strlen(Dis_caption);i++)
{
data_string[chsi] = Dis_caption[i];
chsi++;
}
for (int i=0;i<strlen(Dis_time);i++)
{
data_string[chsi] = Dis_time[i];
chsi++;
}
data_string[chsi]= String_end_symbol;
}
void Channel_AE_String(char *data_string, Channel *channel)
{
char caption_ON[] = {"Auto on: On"};
char caption_OFF[] = {"Auto on: Off"};
if (channel->Auto_Enable == 1)
{
strcpy(data_string,"Auto on: On");
}
else
{
strcpy(data_string,"Auto on: Off");
}
}
void Channel_AD_String(char *data_string, Channel *channel)
{
if (channel->Auto_Disable == 1)
{
strcpy(data_string,"Auto off: On");
}
else
{
strcpy(data_string,"Auto off: Off");
}
}
void Channel_State_String(char *data_string, Channel *channel)
{
if (channel->State == 1)
{
strcpy(data_string,"Activated");
}
else
{
strcpy(data_string,"Deactivated");
}
}
void Channel_Cycle_String(char *data_string, Channel *channel)
{
uint8_t dsi = 0;
char cycle[3];
char cycle_caption_1[]= {"Cycle:"};
char cycle_caption_2_1[]= {" day"};
char cycle_caption_2_2[]= {" days"};
itoa(channel->Cycle, cycle, 10);
if (channel->Cycle != 0)
{
if (channel->Cycle > 1)
{
if (channel->Cycle > 9)
{
for (uint8_t i=0; i<strlen(cycle_caption_1); i++)
{
data_string[dsi]= cycle_caption_1[i];
dsi++;
}
data_string[dsi]= ' ';
dsi++;
data_string[dsi]= ' ';
dsi++;
data_string[dsi]= ' ';
dsi++;
for (uint8_t i=0; i<strlen(cycle); i++)
{
data_string[dsi]= cycle[i];
dsi++;
}
for (uint8_t i=0; i<strlen(cycle_caption_2_2); i++)
{
data_string[dsi]= cycle_caption_2_2[i];
dsi++;
}
data_string[dsi] = String_end_symbol;
}
else
{
for (uint8_t i=0; i<strlen(cycle_caption_1); i++)
{
data_string[dsi]= cycle_caption_1[i];
dsi++;
}
data_string[dsi]= ' ';
dsi++;
data_string[dsi]= ' ';
dsi++;
data_string[dsi]= ' ';
dsi++;
data_string[dsi]= ' ';
dsi++;
for (uint8_t i=0; i= strlen(cycle); i++)
{
data_string[dsi]= cycle[i];
dsi++;
}
for (uint8_t i=0; i<strlen(cycle_caption_2_1); i++)
{
data_string[dsi]= cycle_caption_2_1[i];
dsi++;
}
data_string[dsi] = String_end_symbol;
}
}
else
{
strcpy(data_string,"Cycle: 1 day");
}
}
else
{
strcpy(data_string,"Cycle: everyday");
}
}
void Channel_Cycle_Start_Day_String(char *data_string, Channel *channel)
{
uint8_t dsi = 0;
char cycle_start_day[3];
char cycle_start_day_caption[]= {"Next cycle: "};
itoa(channel->Cycle_Start_Day, cycle_start_day, 10);
Segment_Normalize(cycle_start_day);
for (uint8_t i=0; i<strlen(cycle_start_day_caption); i++)
{
data_string[dsi]= cycle_start_day_caption[i];
dsi++;
}
for (uint8_t i=0; i<strlen(cycle_start_day); i++)
{
data_string[dsi]= cycle_start_day[i];
dsi++;
}
data_string[dsi] = String_end_symbol;
}
//TIMERS
void TC1_Init(void)
{
TCCR1B = (1 << CS12);
TCNT1 = 65536-31250;
TIMSK1 = (1 << TOIE1);
}
//===UART===
void UART_Send_Num(uint8_t data_num)
{
char data_string[3];
itoa(data_num,data_string,16);
PORTB = 1<< PORTB5;
for (int i=0; i<strlen(data_string); i++)
{
while( !(UCSR0A & (1<<UDRE0)))
{
}
UDR0 = data_string[i];
}
PORTB = 0<< PORTB5;
}
void UART_Send_Char(char data_char)
{
PORTB = 1<< PORTB5;
while( !(UCSR0A & (1<<UDRE0)))
{
}
UDR0 = data_char;
PORTB = 0<< PORTB5;
}
void UART_Send_String(char *data_string)
{
PORTB = 1<< PORTB5;
for (int i=0; i<strlen(data_string); i++)
{
while( !(UCSR0A & (1<<UDRE0)))
{
}
UDR0 = data_string[i];
}
PORTB = 0<< PORTB5;
}
void UART_Init(void)
{
UBRR0H = 0;
UBRR0L = 8; //скорость передачи 115200 бит/с
UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0); //активируем Tx, Rx и прерывания
UCSR0C = (0<<UPM01)|(0<<UPM00)|(0<<USBS0)|(0<<UCSZ02)|(1<<UCSZ01)|(1<<UCSZ00); //8 bit, 1 stop bit
}
//EEPROM
void EEPROM_Init(void)
{
if (eeprom_read_byte(&System_first_run) != 0)
{
eeprom_write_byte(&White_light_AE, 0);
eeprom_write_byte(&White_light_ET_HH, 0);
eeprom_write_byte(&White_light_ET_MM, 0);
eeprom_write_byte(&White_light_ET_SS, 0);
eeprom_write_byte(&White_light_AD, 0);
eeprom_write_byte(&White_light_DT_HH, 0);
eeprom_write_byte(&White_light_DT_MM, 0);
eeprom_write_byte(&White_light_DT_SS, 0);
eeprom_write_byte(&White_light_CYCLE, 0);
eeprom_write_byte(&White_light_CSD, 1);
eeprom_write_byte(&Grow_light_AE, 0);
eeprom_write_byte(&Grow_light_ET_HH, 0);
eeprom_write_byte(&Grow_light_ET_MM, 0);
eeprom_write_byte(&Grow_light_ET_SS, 0);
eeprom_write_byte(&Grow_light_AD, 0);
eeprom_write_byte(&Grow_light_DT_HH, 0);
eeprom_write_byte(&Grow_light_DT_MM, 0);
eeprom_write_byte(&Grow_light_DT_SS, 0);
eeprom_write_byte(&Grow_light_CYCLE, 0);
eeprom_write_byte(&Grow_light_CSD, 1);
eeprom_write_byte(&Water_pump_AE, 0);
eeprom_write_byte(&Water_pump_ET_HH, 0);
eeprom_write_byte(&Water_pump_ET_MM, 0);
eeprom_write_byte(&Water_pump_ET_SS, 0);
eeprom_write_byte(&Water_pump_CYCLE, 0);
eeprom_write_byte(&Water_pump_CSD, 1);
eeprom_write_byte(&Water_pump_AD, 0);
eeprom_write_byte(&Water_pump_DT_HH, 0);
eeprom_write_byte(&Water_pump_DT_MM, 0);
eeprom_write_byte(&Water_pump_DT_SS, 0);
eeprom_write_byte(&System_first_run, 0);
First_run = true;
}
}
void EEPROM_Read_Data(void)
{
White_light.Auto_Enable = eeprom_read_byte(&White_light_AE);
White_light.Enable_Time.HH = eeprom_read_byte(&White_light_ET_HH);
White_light.Enable_Time.MM = eeprom_read_byte(&White_light_ET_MM);
White_light.Enable_Time.SS = eeprom_read_byte(&White_light_ET_SS);
White_light.Auto_Disable = eeprom_read_byte(&White_light_AD);
White_light.Disable_Time.HH = eeprom_read_byte(&White_light_DT_HH);
White_light.Disable_Time.MM = eeprom_read_byte(&White_light_DT_MM);
White_light.Disable_Time.SS = eeprom_read_byte(&White_light_DT_SS);
Grow_light.Auto_Enable = eeprom_read_byte(&Grow_light_AE);
Grow_light.Enable_Time.HH = eeprom_read_byte(&Grow_light_ET_HH);
Grow_light.Enable_Time.MM = eeprom_read_byte(&Grow_light_ET_MM);
Grow_light.Enable_Time.SS = eeprom_read_byte(&Grow_light_ET_SS);
Grow_light.Auto_Disable = eeprom_read_byte(&Grow_light_AD);
Grow_light.Disable_Time.HH = eeprom_read_byte(&Grow_light_DT_HH);
Grow_light.Disable_Time.MM = eeprom_read_byte(&Grow_light_DT_MM);
Grow_light.Disable_Time.SS = eeprom_read_byte(&Grow_light_DT_SS);
Water_pump.Auto_Enable = eeprom_read_byte(&Water_pump_AE);
Water_pump.Enable_Time.HH = eeprom_read_byte(&Water_pump_ET_HH);
Water_pump.Enable_Time.MM = eeprom_read_byte(&Water_pump_ET_MM);
Water_pump.Enable_Time.SS = eeprom_read_byte(&Water_pump_ET_SS);
Water_pump.Cycle = eeprom_read_byte(&Water_pump_CYCLE);
Water_pump.Cycle_Start_Day = eeprom_read_byte(&Water_pump_CSD);
Water_pump.Auto_Disable = eeprom_read_byte(&Water_pump_AD);
Water_pump.Disable_Time.HH = eeprom_read_byte(&Water_pump_DT_HH);
Water_pump.Disable_Time.MM = eeprom_read_byte(&Water_pump_DT_MM);
Water_pump.Disable_Time.SS = eeprom_read_byte(&Water_pump_DT_SS);
}
//===IO Ports===
void IO_Init(void)
{
DDRB = 1<<PORTB5; //Индикатор UART
DDRD = 1<<PORTD5 |1<<PORTD6|1<<PORTD7; //Исполнительные механизмы
}
//===I2C====
void I2C_Init(void)
{
TWSR = 0;
TWBR = ((F_CPU/F_SCL)-16)/2;
}
void I2C_TWINT_Wait(void)
{
while(!(TWCR &(1<<TWINT)))
{
}
}
void I2C_Start(void)
{
cli();
_delay_us(10);
TWCR =(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
I2C_TWINT_Wait();
sei();
}
void I2C_Stop(void)
{
cli();
TWCR =(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
_delay_us(10);
sei();
}
void I2C_Send_Device_Address(uint8_t dev_address, bool write)
{
cli();
I2C_last_device = dev_address;
I2C_last_write_mode = write;
if (write == true)
{
TWDR = dev_address;
}
else
{
TWDR = dev_address|1;
}
TWCR = (1<<TWINT)|(1<<TWEN);
I2C_TWINT_Wait();
sei();
}
void I2C_Send_Register_Address(uint8_t reg_address)
{
cli();
TWDR = reg_address;
TWCR =(1<<TWINT)|(1<<TWEN);
I2C_TWINT_Wait();
sei();
}
void I2C_Send_Data_ACK(uint8_t data)
{
cli();
TWDR = data;
TWCR =(1<<TWINT)|(1<<TWEN)|(1<<TWEA);
I2C_TWINT_Wait();
sei();
}
void I2C_Send_Data_NACK(uint8_t data)
{
cli();
TWDR = data;
TWCR =(1<<TWINT)|(1<<TWEN);
I2C_TWINT_Wait();
sei();
}
uint8_t I2C_Read_Data_ACK(void)
{
cli();
uint8_t Result = 0;
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
I2C_TWINT_Wait();
Result = TWDR;
return Result;
sei();
}
uint8_t I2C_Read_Data_NACK(void)
{
cli();
uint8_t Result = 0;
TWCR = (1<<TWINT)|(1<<TWEN);
I2C_TWINT_Wait();
Result = TWDR;
return Result;
sei();
}
bool I2C_Check_Device(uint8_t dev_address)
{
bool Result = false;
I2C_Start();
TWDR = dev_address;
TWCR =(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while(!(TWCR &(1<<TWINT)))
{
}
if((TWSR & 0xF8)== 0x18)
{
Result = true;
}
I2C_Stop();
return Result;
}
void I2C_Device_Map(void)
{
UART_Send_String("I2C network:");
for (uint8_t dev_address=0x00; dev_address<0xFF; dev_address++)
{
if (I2C_Check_Device(dev_address)==true)
{
char text[25];
itoa(dev_address,text,16);
UART_Send_String(" 0x");
UART_Send_String(text);
}
}
}
//===RTC===
void RTC_Set_System_Time(Time *time)
{
I2C_Start();
I2C_Send_Device_Address(RTC_module, 1);
I2C_Send_Register_Address(0x00);
I2C_Send_Data_ACK(INT_to_BCD(time->SS));
I2C_Send_Data_ACK(INT_to_BCD(time->MM));
I2C_Send_Data_NACK(INT_to_BCD(time->HH));
I2C_Stop();
}
void RTC_Set_System_Date(Date *date)
{
I2C_Start();
I2C_Send_Device_Address(RTC_module, 1);
I2C_Send_Register_Address(0x04);
I2C_Send_Data_ACK(INT_to_BCD(date->DD));
I2C_Send_Data_ACK(INT_to_BCD(date->MM));
I2C_Send_Data_NACK(INT_to_BCD(date->YY));
I2C_Stop();
}
void RTC_Get_System_Date_Time(void)
{
RTC_error = !I2C_Check_Device(RTC_module);
if (RTC_error == false)
{
I2C_Start();
I2C_Send_Device_Address(RTC_module, 1);
I2C_Send_Register_Address(0x00);
I2C_Start();
I2C_Send_Device_Address(RTC_module, 0);
System_time.SS = BCD_to_INT(I2C_Read_Data_ACK());
System_time.MM = BCD_to_INT(I2C_Read_Data_ACK());
System_time.HH = BCD_to_INT(I2C_Read_Data_ACK());
int8_t day_of_week = BCD_to_INT(I2C_Read_Data_ACK());
System_date.DD = BCD_to_INT(I2C_Read_Data_ACK());
System_date.MM = BCD_to_INT(I2C_Read_Data_ACK());
System_date.YY = BCD_to_INT(I2C_Read_Data_NACK());
I2C_Stop();
}
else
{
White_light.State = 0;
Grow_light.State = 0;
Water_pump.State = 0;
PORTD = White_light.State<<PORTD5|Grow_light.State<<PORTD6| Water_pump.State<<PORTD7;
Reset();
}
}
//===LCD===
void LCD_Write_Command(uint8_t command)
{
command = command & ~(1<<LCD_E);
command = command | (1<<LCD_E);
I2C_Send_Data_ACK(command);
_delay_us(40);
command = command & ~(1<<LCD_E);
command = command | (0<<LCD_E);
I2C_Send_Data_ACK(command);
_delay_us(40);
}
void LCD_Send_Command(uint8_t data, bool BL, bool RS, bool RW)
{
uint8_t LCD_input_buffer = 0;
uint8_t data_H = data & 0b11110000;
uint8_t data_L = (data<<4) & 0b11110000;
LCD_input_buffer = data_H | BL<<LCD_BL| RS<<LCD_RS| RW<<LCD_RW;
I2C_Send_Data_ACK(LCD_input_buffer);
LCD_Write_Command(LCD_input_buffer);
LCD_input_buffer = data_L | BL<<LCD_BL| RS<<LCD_RS| RW<<LCD_RW;
I2C_Send_Data_ACK(LCD_input_buffer);
LCD_Write_Command(LCD_input_buffer);
}
void LCD_Command_Clear_Display(void)
{
LCD_Send_Command(0b00000001,1,0,0); //Clear display
_delay_ms(2);
}
void LCD_Command_Cursor_Return(void)
{
LCD_Send_Command(0b00000010,0,0,0);
}
void LCD_Command_Put_Cursor(uint8_t x, uint8_t y)
{
uint8_t addr = 0; // line 0 begins at addr 0x00
switch (y)
{
case 0: addr = 0x00; break;
case 1: addr = 0x40; break;
}
LCD_Send_Command(0b10000000 + addr + x,1,0,0);
}
void LCD_Command_Display_Shift_Right(uint8_t count)
{
for (uint8_t i=0;i<count;i++)
{
LCD_Send_Command(0b00011000,1,0,0); //Cursor/display shift
}
}
void LCD_Command_Cursor_Shift_Right(uint8_t count)
{
for (uint8_t i=0;i<count;i++)
{
LCD_Send_Command(0b00010100,1,0,0); //Cursor/display shift
}
}
void LCD_Command_Cursor_Direction_Right(void)
{
LCD_Send_Command(0b00000110,1,0,0); //Entry mode set
}
void LCD_Command_Cursor_Direction_Left(void)
{
LCD_Send_Command(0b00000100,1,0,0); //Entry mode set
}
void LCD_Command_Send_Char(char symbol)
{
uint8_t LCD_input_buffer = 0;
uint8_t data_H = symbol & 0b11110000;
uint8_t data_L = (symbol<<4) & 0b11110000;
LCD_input_buffer = data_H | 1<<LCD_BL| 1<<LCD_RS| 0<<LCD_RW;
I2C_Send_Data_ACK(LCD_input_buffer);
LCD_Write_Command(LCD_input_buffer);
LCD_input_buffer = data_L | 1<<LCD_BL| 1<<LCD_RS| 0<<LCD_RW;
I2C_Send_Data_ACK(LCD_input_buffer);
LCD_Write_Command(LCD_input_buffer);
}
void LCD_Command_Send_String_With_Delay(char *data_string, int8_t num)
{
int delay = 100;
LCD_Command_Put_Cursor(0,num);
LCD_Command_Cursor_Direction_Right();
for (int8_t i=0; i<strlen(data_string); i++)
{
LCD_Command_Send_Char(data_string[i]);
_delay_ms(delay);
}
}
void LCD_Command_Send_String(char *data_string, int8_t num)
{
LCD_Command_Put_Cursor(0,num);
LCD_Command_Cursor_Direction_Right();
for (int8_t i=0; i<strlen(data_string); i++)
{
LCD_Command_Send_Char(data_string[i]);
}
}
void LCD_Command_Clear_String_With_Delay(int8_t num)
{
int delay = 25;
LCD_Command_Put_Cursor(15,num);
LCD_Command_Cursor_Direction_Left();
for (int8_t i=0; i<16; i++)
{
LCD_Command_Send_Char(' ');
_delay_ms(delay);
}
LCD_Command_Put_Cursor(0,num);
}
void LCD_Command_Clear_String(int8_t num)
{
LCD_Command_Put_Cursor(15,num);
LCD_Command_Cursor_Direction_Left();
for (int8_t i=0; i<16; i++)
{
LCD_Command_Send_Char(' ');
}
LCD_Command_Put_Cursor(0,num);
}
void LCD_Init()
{
_delay_ms(50);
//Инициализация LCD в соответствии с блок-схемой в даташите
I2C_Start();
I2C_Send_Device_Address(LCD_module,1);
LCD_Send_Command(0b00110011,0,0,0);
_delay_us(100);
LCD_Send_Command(0b00110010,0,0,0);
_delay_ms(5);
//Настройка LCD
LCD_Send_Command(0b00101000,0,0,0); //Function set
LCD_Send_Command(0b00001000,0,0,0); //Display on/off control
LCD_Send_Command(0b00000001,0,0,0); //Clear display
_delay_ms(2);
LCD_Send_Command(0b00000110,0,0,0); //Entry mode set
//Включение LCD
LCD_Send_Command(0b00001100,1,0,0); //Display on/off control
I2C_Stop();
}
void LCD_Show_String(char *data_string, int8_t num)
{
I2C_Start();
I2C_Send_Device_Address(LCD_module,1);
LCD_Command_Send_String_With_Delay(data_string, num);
I2C_Stop();
}
void LCD_Clear_Display(void)
{
I2C_Start();
I2C_Send_Device_Address(LCD_module,1);
LCD_Command_Clear_Display();
I2C_Stop();
}
void LCD_Flash_String(char *data_string, int8_t num)
{
int delay = 500;
I2C_Start();
I2C_Send_Device_Address(LCD_module,1);
LCD_Command_Send_String_With_Delay(data_string, num);
_delay_ms(delay);
LCD_Command_Clear_String_With_Delay(num);
I2C_Stop();
}
void LCD_Flash_First_Run_Message(void)
{
if (First_run == true)
{
int delay = 500;
I2C_Start();
I2C_Send_Device_Address(LCD_module,1);
LCD_Command_Send_String_With_Delay("G.E.C.K.", 0);
LCD_Command_Send_String_With_Delay("defaults loaded", 1);
_delay_ms(delay);
I2C_Stop();
First_run = false;
}
}
void LCD_Flash_Reset_Message(void)
{
int delay = 500;
I2C_Start();
I2C_Send_Device_Address(LCD_module,1);
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Clear_String_With_Delay(0);
LCD_Command_Send_String_With_Delay("G.E.C.K.", 0);
LCD_Command_Send_String_With_Delay("loading defaults", 1);
_delay_ms(delay);
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Clear_String_With_Delay(0);
LCD_Command_Send_String_With_Delay("G.E.C.K.", 0);
LCD_Command_Send_String_With_Delay("restarting", 1);
_delay_ms(delay);
I2C_Stop();
}
void LCD_Flash_Start_Message(void)
{
int delay = 500;
I2C_Start();
I2C_Send_Device_Address(LCD_module,1);
LCD_Command_Send_String_With_Delay("G.E.C.K.", 0);
LCD_Command_Send_String_With_Delay("started", 1);
_delay_ms(delay);
I2C_Stop();
}
void LCD_Flash_RTC_Error_Message(void)
{
int delay = 1000;
I2C_Start();
I2C_Send_Device_Address(LCD_module,1);
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Clear_String_With_Delay(0);
LCD_Command_Send_String_With_Delay("G.E.C.K. error!", 0);
LCD_Command_Send_String_With_Delay("check RTC", 1);
_delay_ms(delay);
I2C_Stop();
}
void LCD_Flash_System_Time_Updated_Message(void)
{
int delay = 500;
I2C_Start();
I2C_Send_Device_Address(LCD_module,1);
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Clear_String_With_Delay(0);
LCD_Command_Send_String_With_Delay("G.E.C.K.", 0);
LCD_Command_Send_String_With_Delay("Time updated", 1);
_delay_ms(delay);
I2C_Stop();
Flash_time_string = true;
}
void LCD_Flash_System_Date_Updated_Message(void)
{
int delay = 500;
I2C_Start();
I2C_Send_Device_Address(LCD_module,1);
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Clear_String_With_Delay(0);
LCD_Command_Send_String_With_Delay("G.E.C.K.", 0);
LCD_Command_Send_String_With_Delay("Date updated", 1);
_delay_ms(delay);
I2C_Stop();
Flash_time_string = true;
}
void LCD_Flash_Ch_Info_Message(Channel *channel)
{
int delay = 500;
char Enable_Data[17];
char Disable_Data[17];
char State_Data[17];
char AE_Data[17];
char AD_Data[17];
char Cycle_Data[17];
char Cycle_Start_Day_Data[17];
Channel_State_String(State_Data, channel);
Channel_AE_String(AE_Data, channel);
Channel_AD_String(AD_Data, channel);
if (channel->Water == 1)
{
Water_Channel_Enable_String(Enable_Data, channel);
Water_Channel_Disable_String(Disable_Data, channel);
Channel_Cycle_String(Cycle_Data, channel);
Channel_Cycle_Start_Day_String(Cycle_Start_Day_Data, channel);
}
else
{
Light_Channel_Enable_String(Enable_Data, channel);
Light_Channel_Disable_String(Disable_Data, channel);
}
I2C_Start();
I2C_Send_Device_Address(LCD_module,1);
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Clear_String_With_Delay(0);
LCD_Command_Send_String_With_Delay(channel->Name, 0);
LCD_Command_Send_String_With_Delay(State_Data, 1);
_delay_ms(delay);
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Send_String_With_Delay(AE_Data, 1);
_delay_ms(delay);
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Send_String_With_Delay(Enable_Data, 1);
_delay_ms(delay);
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Send_String_With_Delay(AD_Data, 1);
_delay_ms(delay);
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Send_String_With_Delay(Disable_Data, 1);
_delay_ms(delay);
if (channel->Water == 1)
{
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Send_String_With_Delay(Cycle_Data, 1);
_delay_ms(delay);
if (channel->Cycle>0)
{
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Send_String_With_Delay(Cycle_Start_Day_Data, 1);
_delay_ms(delay);
}
}
I2C_Stop();
Flash_time_string = true;
}
void LCD_Flash_Ch_ET_Set_Message(Channel *channel)
{
int delay = 500;
char Enable_Data[17];
if (channel->Water == 1)
{
Water_Channel_Enable_String(Enable_Data, channel);
}
else
{
Light_Channel_Enable_String(Enable_Data, channel);
}
I2C_Start();
I2C_Send_Device_Address(LCD_module,1);
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Clear_String_With_Delay(0);
LCD_Command_Send_String_With_Delay(channel->Name, 0);
LCD_Command_Send_String_With_Delay(Enable_Data, 1);
_delay_ms(delay);
I2C_Stop();
Flash_time_string = true;
}
void LCD_Flash_Ch_AE_Message(Channel *channel)
{
int delay = 500;
char Data[17];
if (channel->Auto_Enable == 1)
{
strcpy(Data,"Auto enable ON");
}
else
{
strcpy(Data,"Auto enable OFF");
}
I2C_Start();
I2C_Send_Device_Address(LCD_module,1);
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Clear_String_With_Delay(0);
LCD_Command_Send_String_With_Delay(channel->Name, 0);
LCD_Command_Send_String_With_Delay(Data, 1);
_delay_ms(delay);
I2C_Stop();
Flash_time_string = true;
}
void LCD_Flash_Ch_DT_Set_Message(Channel *channel)
{
int delay = 500;
char Enable_Data[17];
char Disable_Data[17];
if (channel->Water == 1)
{
Water_Channel_Disable_String(Disable_Data, channel);
}
else
{
Light_Channel_Disable_String(Disable_Data, channel);
}
I2C_Start();
I2C_Send_Device_Address(LCD_module,1);
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Clear_String_With_Delay(0);
LCD_Command_Send_String_With_Delay(channel->Name, 0);
LCD_Command_Send_String_With_Delay(Disable_Data, 1);
_delay_ms(delay);
I2C_Stop();
Flash_time_string = true;
}
void LCD_Flash_Ch_AD_Message(Channel *channel)
{
int delay = 500;
char Data[17];
if (channel->Auto_Disable == 1)
{
strcpy(Data,"Auto disable ON");
}
else
{
strcpy(Data,"Auto disable OFF");
}
I2C_Start();
I2C_Send_Device_Address(LCD_module,1);
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Clear_String_With_Delay(0);
LCD_Command_Send_String_With_Delay(channel->Name, 0);
LCD_Command_Send_String_With_Delay(Data, 1);
_delay_ms(delay);
I2C_Stop();
Flash_time_string = true;
}
void LCD_Flash_Ch_State_Message(Channel *channel)
{
int delay = 500;
char Data[17];
Channel_State_String(Data, channel);
I2C_Start();
I2C_Send_Device_Address(LCD_module,1);
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Clear_String_With_Delay(0);
LCD_Command_Send_String_With_Delay(channel->Name, 0);
LCD_Command_Send_String_With_Delay(Data, 1);
_delay_ms(delay);
I2C_Stop();
Flash_time_string = true;
}
void LCD_Flash_Ch_Cycle_Message(Channel *channel)
{
int delay = 500;
char cycle_data[17];
char cyc_st_day_data[17];
Channel_Cycle_String(cycle_data, channel);
Channel_Cycle_Start_Day_String(cyc_st_day_data, channel);
I2C_Start();
I2C_Send_Device_Address(LCD_module,1);
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Clear_String_With_Delay(0);
LCD_Command_Send_String_With_Delay(channel->Name, 0);
LCD_Command_Send_String_With_Delay(cycle_data, 1);
_delay_ms(delay);
if (channel->Cycle>0)
{
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Send_String_With_Delay(cyc_st_day_data, 1);
_delay_ms(delay);
}
I2C_Stop();
Flash_time_string = true;
}
void LCD_Flash_System_Info_Message(void)
{
int delay = 500;
I2C_Start();
I2C_Send_Device_Address(LCD_module,1);
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Clear_String_With_Delay(0);
LCD_Command_Send_String_With_Delay(Device_type, 0);
LCD_Command_Send_String_With_Delay(Firmware_version, 1);
_delay_ms(delay);
I2C_Stop();
Flash_time_string = true;
}
void LCD_Show_Time(void)
{
int delay = 500;
char Date_Time_Caption[] = {"Date & time: "};
char Date_Time_Data[17];
DATE_TIME_to_STRING(Date_Time_Data, &System_date, &System_time, false, true);
I2C_Start();
I2C_Send_Device_Address(LCD_module,1);
if (Flash_time_string == true)
{
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Clear_String_With_Delay(0);
LCD_Command_Send_String_With_Delay(Date_Time_Caption, 0);
LCD_Command_Send_String_With_Delay(Date_Time_Data, 1);
Flash_time_string = false;
}
else
{
LCD_Command_Send_String(Date_Time_Caption, 0);
LCD_Command_Send_String(Date_Time_Data, 1);
}
I2C_Stop();
}
void LCD_Show_Watering_Message(void)
{
char watering_caption[] = {"Watering..."};
I2C_Start();
I2C_Send_Device_Address(LCD_module,1);
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Clear_String_With_Delay(0);
LCD_Command_Send_String_With_Delay(watering_caption, 0);
I2C_Stop();
Flash_time_string = true;
}
void LCD_Show_Timer(Time *stop_time)
{
char timer_caption [] = {"Time: "};
char timer_time [9];
char timer[17];
int interval_s = 0;
int start = 3600*System_time.HH+60*System_time.MM+System_time.SS;
int stop = 3600*stop_time->HH+60*stop_time->MM+stop_time->SS;
if (stop>=start)
{
interval_s = stop-start;
}
else
{
interval_s = 86400 - start + stop;
}
I2C_Start();
I2C_Send_Device_Address(LCD_module,1);
while (interval_s > 0)
{
int HH = interval_s/3600;
int MM = (interval_s - HH*3600)/60;
int SS = interval_s - HH*3600 - MM*60;
Time interval = {HH,MM,SS};
TIME_to_STRING(timer_time, &interval, true, false);
uint8_t tsi = 0;
for (uint8_t i=0; i<strlen(timer_caption); i++)
{
timer[tsi] = timer_caption[i];
tsi++;
}
for (uint8_t i=0; i<strlen(timer_time); i++)
{
timer[tsi] = timer_time[i];
tsi++;
}
timer[tsi]=String_end_symbol;
LCD_Command_Send_String_With_Delay(timer, 1);
int start = 3600*System_time.HH+60*System_time.MM+System_time.SS;
if (stop>=start)
{
interval_s = stop-start;
}
else
{
interval_s = 86400 - start + stop;
}
}
I2C_Stop();
}
void LCD_Close_Watering_Message(void)
{
I2C_Start();
I2C_Send_Device_Address(LCD_module,1);
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Send_String_With_Delay("Finished",1);
_delay_ms(500);
LCD_Command_Clear_String_With_Delay(1);
LCD_Command_Clear_String_With_Delay(0);
I2C_Stop();
}
//===ОБРАБОТКА ВХОДНОЙ КОМАНДЫ
void Command_GET(char *command_string, char *input_command)
{
for (uint8_t i=0; i<3; i++)
{
command_string[i]=input_command[i];
}
}
void Channel_GET(char *channel_string, char *input_command)
{
for (uint8_t i=3; i<5; i++)
{
channel_string[i-3]=input_command[i];
}
}
void State_GET(uint8_t *state, char *input_command)
{
if (input_command[5]=='1')
{
(*state) = 1;
}
else
{
(*state) = 0;
}
}
void Cycle_GET(uint8_t *cycle, uint8_t *cycle_start_day, char *input_command)
{
uint8_t cycle_result;
char cycle_string[3];
for (uint8_t i=5; i<7; i++)
{
cycle_string[i-5]=input_command[i];
}
cycle_string[2]=String_end_symbol;
cycle_result = atoi(cycle_string);
uint8_t day_result;
char day_string[3];
for (uint8_t i=7; i<9; i++)
{
day_string[i-7]=input_command[i];
}
day_string[2]=String_end_symbol;
day_result = atoi(day_string);
if (day_result > 27)
{
day_result = 27;
}
if (day_result == 0)
{
day_result = 1;
}
if (cycle_result > 27)
{
cycle_result = 27;
}
(*cycle) = cycle_result;
(*cycle_start_day) = day_result;
}
uint8_t Time_HH_GET(char *input_command)
{
uint8_t result;
char HH[3];
for (int i=6; i<8; i++)
{
HH[i-6]=input_command[i];
}
HH[2]=String_end_symbol;
result = atoi(HH);
if (result > 24)
{
return 0;
}
else
{
return result;
}
}
uint8_t Time_MM_GET(char *input_command)
{
uint8_t result;
char MM[3];
for (int i=8; i<10; i++)
{
MM[i-8]=input_command[i];
}
MM[2]=String_end_symbol;
result = atoi(MM);
if (result > 59)
{
return 0;
}
else
{
return result;
}
}
uint8_t Time_SS_GET(char *input_command)
{
uint8_t result;
char SS[3];
for (int i=10; i<12; i++)
{
SS[i-10]=input_command[i];
}
SS[2]=String_end_symbol;
result = atoi(SS);
if (result > 59)
{
return 0;
}
else
{
return result;
}
}
void Time_GET(Time *time, char *input_command)
{
time->HH = Time_HH_GET(input_command);
time->MM = Time_MM_GET(input_command);
time->SS = Time_SS_GET(input_command);
}
uint8_t Date_DD_GET(char *input_command)
{
uint8_t result;
char DD[3];
for (int i=6; i<8; i++)
{
DD[i-6]=input_command[i];
}
DD[2]=String_end_symbol;
result = atoi(DD);
if (result > 31 || result == 0)
{
return 1;
}
else
{
return result;
}
}
uint8_t Date_MM_GET(char *input_command)
{
uint8_t result;
char MM[3];
for (int i=8; i<10; i++)
{
MM[i-8]=input_command[i];
}
MM[2]=String_end_symbol;
result = atoi(MM);
if (result > 12 || result == 0)
{
return 1;
}
else
{
return result;
}
}
uint8_t Date_YY_GET(char *input_command)
{
char YY[3];
for (int i=10; i<12; i++)
{
YY[i-10]=input_command[i];
}
YY[2]=String_end_symbol;
return atoi(YY);
}
void Date_GET(Date *date, char *input_command)
{
date->DD = Date_DD_GET(input_command);
date->MM = Date_MM_GET(input_command);
date->YY = Date_YY_GET(input_command);
}
void Channel_Auto_Enable_SET(Channel *channel, uint8_t *state)
{
channel->Auto_Enable = (*state);
uint8_t *eeprom_AE = channel->EEPROM_AE;
eeprom_write_byte(eeprom_AE, (*state));
}
void Channel_Auto_Disable_SET(Channel *channel, uint8_t *state)
{
channel->Auto_Disable = (*state);
uint8_t *eeprom_AD = channel->EEPROM_AD;
eeprom_write_byte(eeprom_AD, (*state));
}
void Channel_Enable_Time_SET(Channel *channel, Time *time)
{
channel->Enable_Time.HH = time->HH;
channel->Enable_Time.MM = time->MM;
channel->Enable_Time.SS = time->SS;
uint8_t *eeprom_ET_HH = channel->EEPROM_ET_HH;
uint8_t *eeprom_ET_MM = channel->EEPROM_ET_MM;
uint8_t *eeprom_ET_SS = channel->EEPROM_ET_SS;
eeprom_write_byte(eeprom_ET_HH, time->HH);
eeprom_write_byte(eeprom_ET_MM, time->MM);
eeprom_write_byte(eeprom_ET_SS, time->SS);
}
void Channel_Disable_Time_SET(Channel *channel, Time *time)
{
channel->Disable_Time.HH = time->HH;
channel->Disable_Time.MM = time->MM;
channel->Disable_Time.SS = time->SS;
uint8_t *eeprom_DT_HH = channel->EEPROM_DT_HH;
uint8_t *eeprom_DT_MM = channel->EEPROM_DT_MM;
uint8_t *eeprom_DT_SS = channel->EEPROM_DT_SS;
eeprom_write_byte(eeprom_DT_HH, time->HH);
eeprom_write_byte(eeprom_DT_MM, time->MM);
eeprom_write_byte(eeprom_DT_SS, time->SS);
}
void Channel_Cycle_SET(Channel *channel, uint8_t *cycle, uint8_t *cycle_start_day)
{
channel->Cycle = (*cycle);
channel->Cycle_Start_Day = (*cycle_start_day);
uint8_t *eeprom_CYCLE = channel->EEPROM_CYCLE;
uint8_t *eeprom_CSD = channel->EEPROM_CSD;
eeprom_write_byte(eeprom_CYCLE, (*cycle));
eeprom_write_byte(eeprom_CSD, (*cycle_start_day));
}
//===ЛОГИКА ВЫХОДНЫХ КАНАЛОВ===
void Channel_ENABLE(Channel *channel, bool force_enable = false)
{
channel->State = 1;
if (force_enable == true)
{
channel->Force_Enable = 1;
}
}
void Channel_DISABLE(Channel *channel, bool force_disable = false)
{
channel->State = 0;
channel->Force_Enable = 0;
if (force_disable == true)
{
Channel_Auto_Enable_SET(channel, 0);
}
}
void Outputs_SET(void)
{
PORTD = White_light.State<<PORTD5|Grow_light.State<<PORTD6| Water_pump.State<<PORTD7;
}
void Light_Channel_Logick(Channel *channel)
{
if (channel->Auto_Enable == 1)
{
if (channel->Enable_Time.HH == System_time.HH)
{
if (channel->Enable_Time.MM == System_time.MM)
{
Channel_ENABLE(channel);
}
}
}
if (channel->Auto_Disable == 1)
{
if (channel->Disable_Time.HH == System_time.HH)
{
if (channel->Disable_Time.MM == System_time.MM)
{
Channel_DISABLE(channel);
}
}
}
Outputs_SET();
}
void Water_Channel_Timer_ON (Channel *channel)
{
Time disable_time;
if (channel->Force_Enable == 1)
{
disable_time = {System_time.HH, System_time.MM, System_time.SS};
Time_Add(&disable_time, &WP_manual_time);
}
else
{
disable_time = {channel->Disable_Time.HH, channel->Disable_Time.MM, channel->Disable_Time.SS};
}
LCD_Show_Watering_Message();
LCD_Show_Timer(&disable_time);
Channel_DISABLE(channel);
Outputs_SET();
LCD_Close_Watering_Message();
}
void Water_Channel_Logick(Channel *channel)
{
bool start_timer = false;
if (((channel->Cycle > 0 && channel->Cycle_Start_Day == System_date.DD)||(channel->Cycle ==0))&&(channel->Auto_Enable == 1 && channel->Auto_Disable == 1))
{
if (channel->Enable_Time.HH == System_time.HH)
{
if (channel->Enable_Time.MM == System_time.MM)
{
if (channel->Enable_Time.SS == System_time.SS)
{
Channel_ENABLE(channel);
WP_ON_command = true;
}
}
}
}
}
void Cycle_Start_Day_Update(Channel *channel)
{
if (channel->Cycle >0)
{
Date cycle_start_date = {channel->Cycle_Start_Day, System_date.MM, System_date.YY};
while (System_date.DD>cycle_start_date.DD && System_date.MM==cycle_start_date.MM)
{
Date_Add(&cycle_start_date, channel->Cycle+1);
}
uint8_t cycle_start_day = cycle_start_date.DD;
uint8_t cycle = channel->Cycle;
Channel_Cycle_SET(channel, &cycle, &cycle_start_day);
}
}
void Output_Logick_Execute(void)
{
Light_Channel_Logick(&White_light);
Light_Channel_Logick(&Grow_light);
Water_Channel_Logick(&Water_pump);
}
//ВЫПОЛНЕНИЕ ПОЛЬЗОВАТЕЛЬСКИХ КОММАНД
void IC_Set_System_Date(char *input_command)
{
Date_GET(&t_date, input_command);
SSD_command = true;
}
void IC_Set_System_Time(char *input_command)
{
Time_GET(&t_time, input_command);
SST_command = true;
}
void IC_Set_Ch_Enable_Time(char *input_command)
{
char channel_type[2];
Channel_GET(channel_type, input_command);
Time time = {0,0,0};
Time_GET(&time, input_command);
SET_command = true;
if (String_Compare(channel_type, "wl", 0, 0, 2) == true)
{
Channel_Enable_Time_SET(&White_light, &time);
t_channel = &White_light;
}
if (String_Compare(channel_type, "gl", 0, 0, 2) == true)
{
Channel_Enable_Time_SET(&Grow_light, &time);
t_channel = &Grow_light;
}
if (String_Compare(channel_type, "wp", 0, 0, 2) == true)
{
Channel_Enable_Time_SET(&Water_pump, &time);
t_channel = &Water_pump;
}
}
void IC_Set_Ch_Auto_Enable_State(char *input_command)
{
char channel_type[2];
Channel_GET(channel_type, input_command);
uint8_t state = 0;
State_GET(&state, input_command);
SAE_command = true;
if (String_Compare(channel_type, "wl", 0, 0, 2) == true)
{
Channel_Auto_Enable_SET(&White_light, &state);
t_channel = &White_light;
}
if (String_Compare(channel_type, "gl", 0, 0, 2) == true)
{
Channel_Auto_Enable_SET(&Grow_light, &state);
t_channel = &Grow_light;
}
if (String_Compare(channel_type, "wp", 0, 0, 2) == true)
{
Channel_Auto_Enable_SET(&Water_pump, &state);
t_channel = &Water_pump;
}
}
void IC_Set_Ch_Disable_Time(char *input_command)
{
char channel_type[2];
Channel_GET(channel_type, input_command);
Time time = {0,0,0};
Time_GET(&time, input_command);
SDT_command = true;
if (String_Compare(channel_type, "wl", 0, 0, 2) == true)
{
Channel_Disable_Time_SET(&White_light, &time);
t_channel = &White_light;
}
if (String_Compare(channel_type, "gl", 0, 0, 2) == true)
{
Channel_Disable_Time_SET(&Grow_light, &time);
t_channel = &Grow_light;
}
if (String_Compare(channel_type, "wp", 0, 0, 2) == true)
{
Channel_Disable_Time_SET(&Water_pump, &time);
t_channel = &Water_pump;
}
}
void IC_Set_Ch_Auto_Disable_State(char *input_command)
{
char channel_type[2];
Channel_GET(channel_type, input_command);
uint8_t state = 0;
State_GET(&state, input_command);
SAD_command = true;
if (String_Compare(channel_type, "wl", 0, 0, 2) == true)
{
Channel_Auto_Disable_SET(&White_light, &state);
t_channel = &White_light;
}
if (String_Compare(channel_type, "gl", 0, 0, 2) == true)
{
Channel_Auto_Disable_SET(&Grow_light, &state);
t_channel = &Grow_light;
}
if (String_Compare(channel_type, "wp", 0, 0, 2) == true)
{
Channel_Auto_Disable_SET(&Water_pump, &state);
t_channel = &Water_pump;
}
}
void IC_Set_Ch_State(char *input_command)
{
char channel_type[2];
Channel_GET(channel_type, input_command);
uint8_t state = 0;
State_GET(&state, input_command);
SCS_command =true;
if (String_Compare(channel_type, "wl", 0, 0, 2) == true)
{
if (state == 0)
{
Channel_DISABLE(&White_light, true);
}
else
{
Channel_ENABLE(&White_light, true);
}
Outputs_SET();
t_channel = &White_light;
}
if (String_Compare(channel_type, "gl", 0, 0, 2) == true)
{
if (state == 0)
{
Channel_DISABLE(&Grow_light, true);
}
else
{
Channel_ENABLE(&Grow_light, true);
}
Outputs_SET();
t_channel = &Grow_light;
}
if (String_Compare(channel_type, "wp", 0, 0, 2) == true)
{
if (state == 0)
{
Channel_DISABLE(&Water_pump, true);
}
else
{
Channel_ENABLE(&Water_pump, true);
WP_ON_command = true;
}
t_channel = &Water_pump;
}
}
void IC_Set_Ch_Cycle(char *input_command)
{
char channel_type[2];
Channel_GET(channel_type, input_command);
uint8_t cycle = 0;
uint8_t cycle_start_day = 1;
Cycle_GET(&cycle, &cycle_start_day, input_command);
SCC_command =true;
if (String_Compare(channel_type, "wp", 0, 0, 2) == true)
{
Channel_Cycle_SET(&Water_pump, &cycle, &cycle_start_day);
t_channel = &Water_pump;
}
}
void IC_Load_Defaults(void)
{
eeprom_write_byte(&System_first_run, 1);
LDS_command = true;
}
void IC_Report_Ch_Settings(char *input_command)
{
char channel_type[2];
Channel_GET(channel_type, input_command);
RCS_command = true;
if (String_Compare(channel_type, "wl", 0, 0, 2) == true)
{
t_channel = &White_light;
}
if (String_Compare(channel_type, "gl", 0, 0, 2) == true)
{
t_channel = &Grow_light;
}
if (String_Compare(channel_type, "wp", 0, 0, 2) == true)
{
t_channel = &Water_pump;
}
}
void IC_Report_System_Info()
{
UART_Send_String(Device_type);
UART_Send_String("\n\r");
UART_Send_String(Firmware_version);
UART_Send_String("\n\r");
RSI_command = true;
}
void Input_Command_Execute(char *input_command)
{
char command_type[3];
Command_GET(command_type, input_command);
if (String_Compare(command_type, "ssd", 0, 0, 3) == true) //Установка системной даты
{
IC_Set_System_Date(input_command);
}
if (String_Compare(command_type, "sst", 0, 0, 3) == true) //Установка системного времени
{
IC_Set_System_Time(input_command);
}
if (String_Compare(command_type, "set", 0, 0, 3) == true) //Установка времени автоматического включения
{
IC_Set_Ch_Enable_Time(input_command);
}
if (String_Compare(command_type, "sae", 0, 0, 3) == true) //Разрешения автоматического включения
{
IC_Set_Ch_Auto_Enable_State(input_command);
}
if (String_Compare(command_type, "sdt", 0, 0, 3) == true) //Установка времени автоматического выключения
{
IC_Set_Ch_Disable_Time(input_command);
}
if (String_Compare(command_type, "sad", 0, 0, 3) == true) //Разрешения автоматического выключения
{
IC_Set_Ch_Auto_Disable_State(input_command);
}
if (String_Compare(command_type, "scs", 0, 0, 3) == true) //Включение или выключение канала вручную
{
IC_Set_Ch_State(input_command);
}
if (String_Compare(command_type, "scc", 0, 0, 3) == true) //Цикличность включения канала
{
IC_Set_Ch_Cycle(input_command);
}
if (String_Compare(command_type, "rsi", 0, 0, 3) == true) //Запрос состояния системы
{
IC_Report_System_Info();
}
if (String_Compare(command_type, "lds", 0, 0, 3) == true) //Сброс настроек на умолчание
{
IC_Load_Defaults();
}
if (String_Compare(command_type, "rcs", 0, 0, 3) == true) //Запрос настроек канала
{
IC_Report_Ch_Settings(input_command);
}
}
//ОБРАБОТКА ПАКЕТОВ ОТ ВНУТРЕННИХ УСТРОЙСТВ
//===ПРЕРЫВАНИЯ===
ISR(USART_RX_vect)
{
char UART_symbol = UDR0;
if (UART_user_control == true)
{
if (UART_symbol == UART_Stop_symbol)
{
UART_stop_symbol_detected = true;
Input_command[IC_c]=String_end_symbol;
}
if(UART_start_symbol_detected == true && UART_stop_symbol_detected == false)
{
Input_command[IC_c]=UART_symbol;
IC_c++;
}
if (UART_symbol == UART_Start_symbol)
{
UART_start_symbol_detected = true;
UART_stop_symbol_detected = false;
IC_c = 0;
}
if (UART_start_symbol_detected == true && UART_stop_symbol_detected == true)
{
Input_Command_Execute(Input_command);
UART_start_symbol_detected = false;
UART_stop_symbol_detected = false;
}
if (IC_c == Input_command_size)
{
IC_c = 0;
UART_start_symbol_detected = false;
UART_stop_symbol_detected = false;
}
}
else
{
}
}
ISR(TIMER1_OVF_vect)
{
TCNT1 = 65536-31250;
uint8_t I2C_reurn_device = I2C_last_device;
bool I2C_return_write_mode = I2C_last_write_mode;
I2C_Stop();
RTC_Get_System_Date_Time();
Output_Logick_Execute();
I2C_Start();
I2C_Send_Device_Address(I2C_reurn_device,I2C_return_write_mode);
}
ISR(TWI_vect)
{
}
//===ОСНОВНАЯ ПРОГРАММА===
int main(void)
{
//Инициализация
TC1_Init();
I2C_Init();
UART_Init();
LCD_Init();
IO_Init();
EEPROM_Init();
//Если выполняется первый запуск
LCD_Flash_First_Run_Message();
//Чтение из EEPROM
EEPROM_Read_Data();
//Отображение приветствия на LCD
LCD_Flash_Start_Message();
sei();
while (RTC_error == true)
{
LCD_Flash_RTC_Error_Message();
cli();
}
while (RTC_error != true)
{
//Отображение информации
LCD_Show_Time();
//Обновление цикла включения
Cycle_Start_Day_Update(&Water_pump);
if (LDS_command == true)
{
LCD_Flash_Reset_Message();
Reset();
}
if (SSD_command == true)
{
RTC_Set_System_Date (&t_date);
LCD_Flash_System_Date_Updated_Message();
SSD_command = false;
}
if (SST_command == true)
{
RTC_Set_System_Time (&t_time);
LCD_Flash_System_Time_Updated_Message();
SST_command = false;
}
if (SET_command == true)
{
LCD_Flash_Ch_ET_Set_Message(t_channel);
SET_command = false;
}
if (SDT_command == true)
{
LCD_Flash_Ch_DT_Set_Message(t_channel);
SDT_command = false;
}
if (RCS_command == true)
{
LCD_Flash_Ch_Info_Message(t_channel);
RCS_command = false;
}
if (SAE_command == true)
{
LCD_Flash_Ch_AE_Message(t_channel);
SAE_command = false;
}
if (SAD_command == true)
{
LCD_Flash_Ch_AD_Message(t_channel);
SAD_command = false;
}
if (SCS_command == true)
{
LCD_Flash_Ch_State_Message(t_channel);
SCS_command = false;
}
if (SCC_command == true)
{
LCD_Flash_Ch_Cycle_Message(t_channel);
SCC_command = false;
}
if (RSI_command == true)
{
LCD_Flash_System_Info_Message();
RSI_command = false;
}
if (WP_ON_command == true)
{
Water_Channel_Timer_ON(&Water_pump);
WP_ON_command = false;
}
}
}