Счетчик-анализатор потребленной электроэнергии

V Международный конкурс научно-исследовательских и творческих работ учащихся
Старт в науке

Счетчик-анализатор потребленной электроэнергии

Овсянников А.П. 1
1МБОУ СОШ №1 им. М.М.Пришвина
Овсянников П.Ю. 1Австриевских Н.М. 2
1 МБУДО "Детский оздоровительно-образовательный центр города Ельца"
2МБОУ «Гимназия №11 г.Ельца»
Автор работы награжден дипломом победителя II степени
Текст работы размещён без изображений и формул.
Полная версия работы доступна во вкладке "Файлы работы" в формате PDF

Введение.

Счётчик электрической энергии (электрический счётчик) — прибор для измерения расхода электроэнергии. По своей конструкции электросчетчик может быть электромеханическим и электронным. В электромеханическом счетчике магнитное поле неподвижных токопроводящих катушек влияет на подвижный элемент из проводящего материала. Подвижный элемент представляет собой диск, по которому протекают токи, индуцированные магнитным полем катушек. Количество оборотов диска в этом случае прямо пропорционально потребленной электроэнергии. Механические счётчики электроэнергии постоянно вытесняются с рынка электронными счетчиками из-за отдельных недостатков: отсутствие дистанционного автоматического снятия показаний, однотарифность, погрешности учёта, плохая защита от краж электроэнергии. Электронным называется электросчетчик, в котором переменный ток и напряжение воздействуют на твердотельные (электронные) элементы для создания на выходе импульсов, число которых пропорционально измеряемой активной энергии. Счетный механизм представляет собой электромеханическое (имеет преимущество в областях с холодным климатом, при условии установки прибора на улице) или электронное устройство, содержащее как запоминающее устройство, так и дисплей.

Важной особенностью электронного счетчика является наличие специального выхода для подключения внешних устройств контроля. Более дорогие модели позволяют получать хранимую в электросчетчике информацию непосредственно с компьютера. Однако большинство бытовых электронных счетчиков имеет обычный импульсный выход, электрически изолированный от измеряемого напряжения.

Как правило, такие выходы остаются без использования, так как без использования дополнительных устройств подключение к этому сигналу не имеет смысла. Необходимо устройство, которое будет производить подсчет передаваемых электросчетчиком импульсов. После продолжительного поиска в сети Интернет нам не удалось обнаружить простых устройств, позволяющих дистанционно считывать показания с электросчетчика.

Было принято решение разработать и изготовить подобное устройство самостоятельно, а дополнительно снабдить его еще несколькими полезными функциями.

Цель работы: разработать и изготовить прибор, позволяющий произвести запись количества потребленной электроэнергии в течение каждого часа и выводящий эту информацию визуально в виде графика, а также использовать его в качестве «удлинителя» циферблата электросчетчика.

Методы:

- теоретический анализ литературы по данной проблеме;

- эксперимент, наблюдение;

- разработка и сборка счетчика-анализатора;

- разработка программного обеспечения.

Задачи:

Изучить устройство и принципы работы электросчетчиков, определить формат передаваемых им данных.

Разработать принципиальную электрическую схему счетчика-анализатора.

Разработать и изготовить печатные платы для счетчика.

Определить способы и формат обмена данными с персональным компьютером.

Разработанное и изготовленное устройство подключается к импульсному выходу бытового электросчетчика и позволяет фиксировать общее количество потребленной энергии с точностью до 0,001 кВт*ч, при том, что точность циферблата на самом счетчике всего 0,1 кВт*ч. Эта функция позволяет использовать прибор в качестве «удлинителя» для электросчетчика, установленного в неудобном месте. Также устройство записывает количество энергии, потребленной в течение каждого часа в энергонезависимую память и способно передавать эти данные в персональный компьютер для дальнейшей обработки и анализа. Дополнительно прибор может отслеживать выход объема потребляемой энергии за указанные границы и подавать сигнал об этом, включая внешние реле.

Устройство прибора удобно рассматривать по его структурной схеме, приведенной на рисунке 1.

Работой прибора управляет центральный процессор, задачей которого является фиксация импульсов, приходящих от электросчетчика, пересчет их в кВт*ч и увеличение общего счетчика энергии в соответствии с пришедшей информацией. Начальное значение счетчика в приборе устанавливается при первом подключении прибора вместе с текущими временем и датой с помощью подключения к компьютеру. Кроме этого, также задается коэффициент, показывающий сколько импульсов передается на 1 кВт*ч, зависящий от модели электросчетчика. Далее электросчетчик и счетчик-анализатор начинают работать параллельно и очень важно, чтобы все импульсы, приходящие от электросчетчика, были учтены. Проблемы могут возникнуть в случае отключения питания прибора и тогда значения на циферблате электросчетчика и дисплее нашего прибора будут различаться. Чтобы этого избежать, каждое изменение количества потребленной энергии ЦПУ сохраняет в ячейках энергонезависимой памяти с быстрым доступом. Для обеспечения сохранности этой информации в схему добавлена встроенная батарея, также использующаяся для питания часов.

Рис. 1. Структурная схема устройства.

При возобновлении питания прибора последние сохраненные данные восстанавливаются из памяти, а работа продолжается без потери данных.

На ЖК-дисплее отображаются текущее значение энергии, дата и время. По окончании каждого часа значение энергии, потраченное за последний час, сохраняется в постоянной энергонезависимой памяти вместе с информацией о дате и времени. Далее эта информация передается в компьютер и может быть использована для изучения и анализа потребления электроэнергии в разрезе часа или суток.

С помощью клавиатуры можно переключать режимы работы устройства.

Принципиальная схема прибора показана на рисунке 2.

Рис. 2. Принципиальная схема счетчика-анализатора.

В качестве ЦПУ используется микроконтроллер IC1 AT89C2051-24PI, работающий на частоте 22,1184 МГц, стабилизированной кварцевым резонатором ZQ1. Такая частота была выбрана для возможности обмена последовательными данными с компьютером на скорости до 115200 бод. Цепь на элементах R1, VD1 и C3 производит сброс микроконтроллера в начальное состояние при подаче питания. Сигнал с электросчетчика подается непосредственно на вывод 6 микроконтроллера.

Микросхема IC3 представляет собой часы реального времени, точность которых стабилизируется кварцевым резонатором ZQ2, а за счет батарейки BAT1 часы будут идти даже при отсутствии основного питания. Кроме часов в микросхеме имеется 48 ячеек быстрой энергонезависимой памяти, которую мы используем для хранения промежуточных результатов.

В качестве постоянной энергонезависимой памяти использована микросхема IC2 объемом 32 килобайта. Такого объема достаточно чтобы хранить без потерь до 1,5 лет информации о потребленной электроэнергии. Далее старые данные будут постепенно затираться более новыми.

Светодиод VD2 добавлен для индикации работы устройства. При каждом импульсе, пришедшем с электросчетчика светодиод меняет свое состояние на противоположное. По частоте мигания VD2 можно визуально оценить частоту приходящих импульсов, а значит, и текущую нагрузку на электросеть.

Многооборотный подстроечный резистор R2 используется для настройки контрастности ЖК-дисплея. Резисторная сборка RP1 используется для подтягивания напряжения на выходах микроконтроллера к источнику питания для получения стабильных логических уровней. Резисторы R8 и R9 добавлены в схему для согласования уровней при подключении преобразователя USB-Serial для осуществления обмена данными с компьютером.

На диодах VD3-VD6 и кнопках SW1-SW4 собрана матричная клавиатура. Сигнал опроса кнопок, появляющийся по очереди на выводах 12-15 микроконтроллера в случае нажатия кнопок подается на вывод 7 и так вычисляется какая из кнопок была нажата.

Транзисторы VT1 и VT2 используются в качестве выходов с открытым коллектором для управления внешними устройствами подачи сигналов при наступлении заранее заданных условий.

Прибор питается от внешнего стабилизированного источника напряжением 5 вольт.

Конструкция. Устройство собрано на печатной плате, разработанной в компьютерной программе Sprint Layout. Рисунок печатной платы был распечатан на лазерном принтере и перенесен на стеклотекстолит с помощью ламинатора (фото 1).

Фото 1. Печатная плата счетчика-анализатора.

Микропроцессор и микросхема IC2 установлены в панели для возможности перепрограммирования или чтения информации при необходимости. Также панель установлена для батарейки BAT1. На фото 2 представлено устройство в сборе.

Фото 2. Счетчик-анализатор потребленной электроэнергии в сборе.

Фото 3. Счетчик-анализатор в корпусе.

Радиодетали для устройства были взяты от старого кассового аппарата, ЖК-дисплей – от копировального аппарата, а панелька под батарейку – со старой материнской платы компьютера. Дисплей соединен с платой шлейфом, отрезанным от старого дисковода.

Конструкция собрана в корпусе из пластика, на переднюю панель вынесены дисплей и светодиод. На боковых сторонах расположены разъемы для подключения кабеля от электросчетчика и разъем для связи с компьютером (фото 3).

Для питания устройства используется зарядное устройство от сотового телефона с USB выходом, подключенное к прибору с помощью кабеля, срезанного со старой компьютерной USB мыши.

Для работы с устройством используется специальное приложение для персонального компьютера, позволяющего установить время в приборе, начальное значение общего счетчика энергии и некоторых настроек.

Рис. 3. Приложение для работы с устройством.

Рис. 4. График потребления электроэнергии в жилом доме посуточно.

Рис. 5. График почасового потребления электроэнергии 11.09.2017.

Также с помощью приложения можно получить данные из постоянной энергонезависимой памяти и построить на их основании графики потребления. Пример загрузки данных из устройства показан на рисунке 3.

Полученные из устройства данные сохраняются на компьютере и работу по изучению и анализу можно проводить не подключаясь к прибору. Для примера рассмотрим записанные устройством данные в жилом доме в течение нескольких суток. Нажатие на кнопку «Построить график» отображает информацию, показанную на рисунке 4.

Щелкнув по любому из зеленых столбцов, можно получить расшифровку суточной информации с разбивкой по каждому часу. На рисунке 5 показан график почасового потребления электроэнергии 11 сентября 2017 года.

Вывод.

В своей работе мы использовали различные источники информации (научная и учебная литература, Интернет). В процессе работы мы изучили устройство и принцип работы электросчетчика и способ передачи данных на внешние устройства, были изучены принципы работы микроконтроллера, способы его программирования и обмена данными. Также был освоен метод разработки и изготовления печатных плат с помощью лазерного принтера и ламинатора.

Описанный счетчик-анализатор электроэнергии может быть использован в быту в качестве «удлинителя» циферблата электросчетчика, часов, а также для изучения количества потребленной электроэнергии с целью экономии и более равномерного распределения нагрузки. Кроме этого, устройство можно использовать на предприятиях, где повышенное и/или пониженное потребление электроэнергии ведет к крупным штрафам. В продаже имеются промышленные электросчетчики, обладающие такими функциями, но их цена в сотни раз превышает стоимость представляемого устройства.

Литература:

 

Иванов Б.С. "Электроника в самоделках",-М.: ДОСААФ, 2001г.

 

Галле К. "Как проектировать электронные схемы" - М.: ДМК Пресс, 2009г.

 

И.В.Левин «Справочник конструктора точных приборов» издание третье, Издательство «Машиностроение», Москва.

 

В.О. Шпаковский, «Для тех, кто любит мастерить», Москва, Просвещение

 

Бродин В.Б., Шагурин И.И. Микроконтроллеры. Архитектура, программирование, интерфейс. – М.: Издательство ЭКОМ, 1999

 

Паронджанов В. Д. "Учись писать, читать и понимать алгоритмы. Алгоритмы для правильного мышления. Основы алгоритмизации." – М.: ДМК Пресс, 2012г.

 

http://www.atmel.com – сайт производителя микроконтроллеров

 

Уитсон Дж. "500 практических схем на ИС": Пер. с англ. - М.: Мир, 1992г.

 

Токхейм Р. "Основы цифровой электроники": Пер. с англ.- М.: Мир, 1988г.

 

http://turbo51.com/

 

Белкин В.Г., Бондаренко В.К. «Справочник радиолюбителя-конструктора» издательство: Москва «Радио и связь».

Приложение 1. Исходный код микропрограммы контроллера на языке Pascal.

program pwmeter;

Uses I2C, LCD;

DEVICE_ID = $2475;

SystemClock = 22118400;

CLOCK_FREQ = 1000; //Hz

RTC_ADDR = $D0; //DS1307

EEPROM_ADDR = $A0; //24C16

EEPROM_SIZE = 32768; //байт

RTC_WATTS_OFFSET = $8;

RTC_TICKS_OFFSET = $10;

RTC_HOUR_OFFSET = $18;

BaudRateSerial = 57600;

STR_BUFFER_SIZE = 12;

BaudRateTimerValue = - SystemClock div 12 div 32 div BaudRateSerial;

ClockTimerValue = - SystemClock div 12 div CLOCK_FREQ;

WattsPerImpulse = 10;

type

TStrBuffer = packed record

Index: Byte;

Len: Byte;

case Byte of

0: (Data: array[0..STR_BUFFER_SIZE-1] of Byte);

1: (Chr: array[0..STR_BUFFER_SIZE-1] of Char);

end;

TStorageHeader = packed record

Complete:Byte;

Day:Byte;

Month:Byte;

Year:Byte;

Counter:TDword;

end;

TStorage = packed record

case Byte of

0: (Header: TStorageHeader);

1: (Dword0,Dword1: TDword);

2: (Bytes: array[0..7] of Byte);

end;

TSerialState = (ssIdle,ssGetDate,ssSetDate,ssGetPower,ssSetPower,ssReadMemory,

ssGetOptions,ssSetOptions,ssResetMemory);

var

//P1.0 - LCD_D4

//P1.1 - LCD_D5

//P1.2 - LCD_D6

//P1.3 - LCD_D7

LCD.LCD_RS: Boolean absolute P1.4;

LCD.LCD_E: Boolean absolute P1.5;

Relay1: Boolean absolute P1.6;

Relay2: Boolean absolute P1.7;

I2C.SDA:Boolean absolute P3.5;

I2C.SCL:Boolean absolute P3.4;

Led: Boolean absolute P3.7;

Input: Boolean absolute P3.2;

Kbd: Boolean absolute P3.3;

CounterChanged: Boolean; volatile;

DataActual:Boolean;

SecondFlag:Boolean;

DataReceived:Boolean;

EE_Dword:TDword;

Day_Dword:TDword;

WattCounter:TDword;

Storage: TStorage absolute $18;

Buffer: TStrBuffer;

TmpBuf: array[0..3] of Byte;

SecCounter:Word;

TickPrescaller:Byte; volatile;

I2C_Device_Addr:Byte;

SerialState:TSerialState;

LastReceivedByte:Byte;

SerialReceiveCounter:Byte;

SerialBuffer: array[0..7] of Byte absolute $10;

SerialMemSendAddr:Word;

EEPROM_BaseAddr:Word absolute EE_Dword.Word1;

PulsesPer10W:Byte absolute EE_Dword.Byte0;

EEPROM_LastHour:Byte absolute EE_Dword.Byte1;

LastHour: Byte absolute Day_Dword.Byte0;

LastDay: Byte absolute Day_Dword.Byte1;

HourWatts: Word absolute Day_Dword.Word1;

function Dword2Str(Data:LongInt;Dot:Byte):Byte;assembler;

asm

mov R7,Buffer.Len

mov R1,#Buffer.Data

mov A,Dot

clr C

rlc A

mov A,#' '

jc @@Clear

mov A,#'0'

@@Clear:

mov @R1,A

inc R1

djnz R7,@@Clear

mov A,Buffer.Len

add A,#Buffer.Data-1

mov R1,A

mov R5,#0

@@Loop2:

clr A

mov R6,#32

@@Skip:

lcall @@Shift

jnz @@Start

djnz R6,@@Skip

ret

@@Loop1:

lcall @@Shift

@@Start:

subb A,#10

jc @@Back

mov R0,#Data

inc @R0

sjmp @@Next

@@Back:

add A,#10

@@Next:

djnz R6,@@Loop1

add A,#30h

mov @R1,A

dec R1

inc R5

mov A,Dot

anl A,#7Fh

xrl A,R5

jnz @@NoDot

mov @R1,#'.'

inc R5

dec R1

@@NoDot:

mov A,#0

mov R0,#Data

mov R7,#4

@@Test:

orl A,@R0

djnz R7,@@Test

jnz @@Loop2

mov A,R5

ret

@@Shift:

mov R0,#Data

mov R7,#4

clr c

@@Shft:

xch a,@R0

rlc a

xch a,@R0

inc R0

djnz R7,@@Shft

rlc a

ret

end;

procedure I2C_ReadByte(Addr:Word;Cnt:Byte;Buff:PByte);

var

i:Byte;

begin

Start_I2C;

Send_I2C_Byte(I2C_Device_Addr and $FE);

if I2C_Device_Addr=EEPROM_ADDR then Send_I2C_Byte(Hi(Addr));

Send_I2C_Byte(Lo(Addr));

Start_I2C;

Send_I2C_Byte(I2C_Device_Addr or $01);

for i:=0 to Cnt-1 do begin

Buff^:=Receive_I2C_Byte;

Inc(Buff);

if iCnt-1 then Send_I2C_Ack;

end;

Send_I2C_ClockPulse;

Stop_I2C;

end;

procedure I2C_WriteByte(Addr:Word;Cnt:Byte;Data: PByte);

var

i:Byte;

begin

Start_I2C;

Send_I2C_Byte(I2C_Device_Addr and $FE);

if I2C_Device_Addr=EEPROM_ADDR then Send_I2C_Byte(Hi(Addr));

Send_I2C_Byte(Lo(Addr));

for i:=0 to Cnt-1 do begin

Send_I2C_Byte(Data^);

Inc(Data);

end;

Stop_I2C;

if I2C_Device_Addr=EEPROM_ADDR then Delay_ms(10);

end;

procedure SerialSendByte(Bt:Byte);

begin

TI:=False;

SBUF:=Bt;

while not TI do ;

end;

procedure Timer_1ms_Handler; Interrupt Timer0; Using 1; { 1 ms interrupt }

begin

TL0 := Lo (ClockTimerValue);

TH0 := Hi (ClockTimerValue);

if DelayTimer 0 then Dec(DelayTimer);

if SecCounter 0 then Dec(SecCounter);

if SecCounter = 0 then begin

SecCounter:=CLOCK_FREQ;

SecondFlag:=True;

end

end;

procedure Int0Handler; Interrupt External0; Using 1; { Input Pulses }

begin

Inc(TickPrescaller,WattsPerImpulse);

Led:=not Led;

if TickPrescaller>=PulsesPer10W then begin

Dec(TickPrescaller,PulsesPer10W);

Inc(WattCounter.Dword);

Inc(HourWatts);

CounterChanged:=True;

end;

end;

function IncBufferIndex:Boolean;

begin

Result:=Buffer.Index(STR_BUFFER_SIZE-1);

if Result then Inc(Buffer.Index);

end;

procedure LCD_SendStr;

var

i:Byte;

begin

for i:=0 to Buffer.Len-1 do LCD_WriteByte(LCD_DATA_BYTE,Buffer.Data[i]);

end;

procedure BCD_To_Str(BCD:Byte);

begin

Buffer.Data[Buffer.Index]:=$30+(BCD shr 4);

IncBufferIndex;

Buffer.Data[Buffer.Index]:=$30+(BCD and $0F);

IncBufferIndex;

end;

procedure BCD_To_Byte(var Data:Byte);

begin

Data:=10*(Data shr 4)+(Data and $0F);

end;

procedure ClearStrBuffer;

var

i:Byte;

begin

Buffer.Index:=0;

for i:=0 to STR_BUFFER_SIZE-1 do Buffer.Data[i]:=0;

end;

function UpdateTime:Boolean;

begin

LCD_WriteByte(LCD_CMD_BYTE,$C0);

ClearStrBuffer;

I2C_Device_Addr:=RTC_ADDR;

I2C_ReadByte(0,3,@TmpBuf);

BCD_To_Str(TmpBuf[2]);

if (TmpBuf[0] and 1)=0 then Buffer.Chr[Buffer.Index]:=':'

else Buffer.Chr[Buffer.Index]:=' ';

IncBufferIndex;

BCD_To_Str(TmpBuf[1]);

Buffer.Len:=5;

LCD_SendStr;

BCD_To_Byte(TmpBuf[2]);

Result:=TmpBuf[2]LastHour;

if Result then LastHour:=TmpBuf[2] else begin

EEPROM_LastHour:=LastHour;

I2C_WriteByte(RTC_TICKS_OFFSET,4,@EE_Dword);

end;

end;

function UpdateDate:Boolean;

begin

LCD_WriteByte(LCD_CMD_BYTE,$C6);

ClearStrBuffer;

I2C_Device_Addr:=RTC_ADDR;

I2C_ReadByte(4,3,@TmpBuf);

BCD_To_Str(TmpBuf[0]);

Buffer.Chr[Buffer.Index]:='.';

IncBufferIndex;

BCD_To_Str(TmpBuf[1]);

Buffer.Chr[Buffer.Index]:='.';

IncBufferIndex;

BCD_To_Str($20);

BCD_To_Str(TmpBuf[2]);

Buffer.Len:=10;

LCD_SendStr;

Storage.Header.Day:=TmpBuf[0];

Storage.Header.Month:=TmpBuf[1];

Storage.Header.Year:=TmpBuf[2];

BCD_To_Byte(TmpBuf[0]);

Result:=TmpBuf[0]LastDay;

LastDay:=TmpBuf[0];

end;

procedure UpdateCounter;

begin

ClearStrBuffer;

LCD_WriteByte(LCD_CMD_BYTE,$80);

Buffer.Len:=11;

Dword2Str(WattCounter.Dword,$3);

LCD_SendStr;

LCD_WriteByte(LCD_DATA_BYTE,ord(' '));

LCD_WriteByte(LCD_DATA_BYTE,ord('k'));

LCD_WriteByte(LCD_DATA_BYTE,ord('W'));

LCD_WriteByte(LCD_DATA_BYTE,ord('*'));

LCD_WriteByte(LCD_DATA_BYTE,ord('h'));

end;

procedure LoadParameters;

begin

I2C_Device_Addr:=RTC_ADDR;

I2C_ReadByte(RTC_WATTS_OFFSET,4,@WattCounter);

I2C_ReadByte(RTC_HOUR_OFFSET,4,@Day_Dword);

I2C_ReadByte(RTC_TICKS_OFFSET,4,@EE_Dword);

I2C_ReadByte(0,1,@TmpBuf);

if TmpBuf[0] and $80 = $80 then begin

PulsesPer10W:=32;

EEPROM_BaseAddr:=0;

I2C_WriteByte(RTC_TICKS_OFFSET,4,@EE_Dword);

WattCounter.Dword:=0;

I2C_WriteByte(RTC_WATTS_OFFSET,4,@WattCounter);

HourWatts:=0;

LastHour:=0;

LastDay:=0;

I2C_WriteByte(RTC_HOUR_OFFSET,4,@Day_Dword);

TmpBuf[0]:=0;

I2C_WriteByte(0,1,@TmpBuf);

end;

DataActual:=True;

end;

procedure SaveStorageHeader;

var

i:Byte;

begin

Storage.Header.Complete:=0;

TmpBuf[0]:=0;

TmpBuf[1]:=0;

TmpBuf[2]:=0;

TmpBuf[3]:=0;

Storage.Header.Counter:=WattCounter;

EEPROM_BaseAddr:=EEPROM_BaseAddr+(SizeOf(TStorageHeader)+48);

if EEPROM_BaseAddr+(SizeOf(TStorageHeader)+48) > EEPROM_SIZE then

EEPROM_BaseAddr:=0;

I2C_Device_Addr:=EEPROM_ADDR;

I2C_WriteByte(EEPROM_BaseAddr,4,@Storage.Dword0);

I2C_WriteByte(EEPROM_BaseAddr+4,4,@Storage.Dword1);

for i:=0 to 11 do I2C_WriteByte((8+4*i)+EEPROM_BaseAddr,4,@TmpBuf);

end;

procedure SaveHourData;

begin

I2C_Device_Addr:=EEPROM_ADDR;

I2C_ReadByte(EEPROM_BaseAddr,1,@TmpBuf);

if TmpBuf[0]>23 then SaveStorageHeader;

TmpBuf[0]:=Lo(HourWatts);

TmpBuf[1]:=Hi(HourWatts);

I2C_WriteByte(EEPROM_BaseAddr+(SizeOf(TStorageHeader)+2*EEPROM_LastHour),2,@TmpBuf);

TmpBuf[0]:=EEPROM_LastHour; //CurrentHour

I2C_WriteByte(EEPROM_BaseAddr,1,@TmpBuf);

end;

procedure SerialPutToBuffer;

begin

if DataReceived then begin

DataReceived:=False;

Dec(SerialReceiveCounter);

SerialBuffer[SerialReceiveCounter]:=LastReceivedByte;

end;

end;

procedure SerialHandler; Interrupt Serial; Using 1; { Serial interrupt }

begin

if RI then begin

LastReceivedByte:=SBUF;

{TI:=False;

SBUF:=LastReceivedByte;

while TI do;

TI:=False;}

RI:=False;

if SerialState=ssIdle then case LastReceivedByte of

ord('D'): begin

SerialState:=ssSetDate;

SerialReceiveCounter:=6;

end;

ord('P'): begin

SerialState:=ssSetPower;

SerialReceiveCounter:=5;

end;

ord('m'): begin

SerialState:=ssReadMemory;

SerialReceiveCounter:=0;

SerialMemSendAddr:=0;

end;

ord('R'): begin

SerialState:=ssResetMemory;

SerialReceiveCounter:=0;

end;

end else DataReceived:=True;

end;

end;

procedure ExecuteSerialCmd;

var

i:Byte;

t:Word;

begin

if SerialReceiveCounter>0 then SerialPutToBuffer else case SerialState of

ssSetDate: begin

I2C_Device_Addr:=RTC_ADDR;

I2C_WriteByte(0,3,@SerialBuffer);

I2C_WriteByte(4,3,@SerialBuffer[3]);

SerialSendByte(1);

UpdateDate;

SerialState:=ssIdle;

end;

ssSetPower: begin

WattCounter.Byte0:=SerialBuffer[3];

WattCounter.Byte1:=SerialBuffer[2];

WattCounter.Byte2:=SerialBuffer[1];

WattCounter.Byte3:=SerialBuffer[0];

PulsesPer10W:=SerialBuffer[4];

CounterChanged:=True;

Day_Dword.Dword:=0;

I2C_Device_Addr:=RTC_ADDR;

I2C_WriteByte(RTC_TICKS_OFFSET,4,@EE_Dword);

I2C_WriteByte(RTC_WATTS_OFFSET,4,@WattCounter);

SerialSendByte(1);

SerialState:=ssIdle;

end;

ssResetMemory: begin

EEPROM_BaseAddr:=0;

I2C_Device_Addr:=RTC_ADDR;

I2C_WriteByte(RTC_TICKS_OFFSET,4,@EE_Dword);

SerialSendByte(1);

SerialState:=ssIdle;

end;

ssReadMemory: begin

t:=EEPROM_BaseAddr+(SizeOf(TStorageHeader)+48);

if SerialMemSendAddr=0 then begin

SerialSendByte(Lo(DEVICE_ID));

SerialSendByte(Hi(DEVICE_ID));

SerialSendByte(Lo(EEPROM_SIZE));

SerialSendByte(Hi(EEPROM_SIZE));

SerialSendByte(Lo(t));

SerialSendByte(Hi(t));

end;

I2C_Device_Addr:=EEPROM_ADDR;

I2C_ReadByte(SerialMemSendAddr,8,@SerialBuffer);

for i:=0 to 7 do SerialSendByte(SerialBuffer[i]);

Inc(SerialMemSendAddr,8);

if SerialMemSendAddr>t then SerialState:=ssIdle;

end;

end;

end;

procedure Init;

begin

P1:=$FF;

P3:=$FF;

TL0 := Lo (ClockTimerValue);

TH0 := Hi (ClockTimerValue);

TL1:=Lo(BaudRateTimerValue);

TH1:=Lo(BaudRateTimerValue);

TickPrescaller:=0;

ClearStrBuffer;

DataActual:=False;

SecCounter:=CLOCK_FREQ;

SecondFlag:=True;

CounterChanged:=True;

SerialState:=ssIdle;

DataReceived:=False;

PCON := $00;

SCON:=SCON_SERIAL_MODE_1+SCON_RECEIVE_ENABLED;

TMOD:=TMOD_TIMER1_MODE_2+TMOD_TIMER0_MODE_1;

TCON:=TCON_TIMER1_ENABLE+TCON_TIMER0_ENABLE+TCON_INT0_PULSE;

IE:=IE_GLOBAL+IE_TIMER0+IE_INT0+IE_UART;

end;

begin

Init;

LCD_Init;

LoadParameters;

UpdateDate;

repeat

if CounterChanged then begin

UpdateCounter;

I2C_Device_Addr:=RTC_ADDR;

I2C_WriteByte(RTC_WATTS_OFFSET,4,@WattCounter);

I2C_WriteByte(RTC_HOUR_OFFSET,4,@Day_Dword);

CounterChanged:=False;

end;

if SecondFlag then begin

if UpdateTime then begin

SaveHourData;

HourWatts:=0;

if UpdateDate then begin

SaveStorageHeader;

end;

I2C_Device_Addr:=RTC_ADDR;

I2C_WriteByte(RTC_HOUR_OFFSET,4,@Day_Dword);

I2C_WriteByte(RTC_TICKS_OFFSET,4,@EE_Dword);

end;

SecondFlag:=False;

end;

ExecuteSerialCmd;

until False;

end.

28

Просмотров работы: 70