Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Помогите реализовать последовательность действий


Автор: maloicds 10.4.2012, 22:48
Возникла необходимость в своей программе использовать алгоритм, который не могу реализовать  smile Суть его попробую обьяснить на рисунке:
user posted image
Программа выполняет бесконечный цикл. Есть определённые действия.
действие 1 выполняется так: действие длительностью 300мс, простой 300мс, опять действие и так до бесконечности (черные квадраты).
действие 2 выполняется через каждые например 2 минуты длительностью 300мс и не совпадает со временем выполнения других действий (красные квадраты).
действие 3 выполняется через каждые например 10 минут длительностью 300мс и не совпадает со временем выполнения других действий (зелёные квадраты).
и т.д.
Таким образом необходимо выполнять в еденицу времени только одно из действий. Немного запутано, но думаю понятно smile
Была идея сделать таким образом:

Код

 d1: array[1..20] of integer=(1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0);
 d2: array[1..20] of integer=(0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0);
 d3: array[1..20] of integer=(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0);
 d4: array[1..20] of integer=(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1);

procedure TForm1.Timer1Timer(Sender: TObject);
begin
 if d1[k]=1 then .....
 if d2[k]=1 then .....
 if d3[k]=1 then .....
 if d4[k]=1 then .....
 inc(k);
 if k=21 then k:=1;
end;


Интервал у таймера 300мс.

Автор: Чучмек 10.4.2012, 23:08
Период необходимо строго выдерживать?

Автор: DarkProg 10.4.2012, 23:09
А что собственно не получается?
Понял, что у вас не работает... синхронизации нет ни фига...
Для того чтобы таймер работал адекватно, в него нельзя засовывать при срабатывании какие-либо действия, иначе он тратит время на то чтобы выполнить что-тро и следующее действие сработает как бы позже чем надо, хотя с точки зрения таймера всё будет верно.

Я использую POSTMessage для выполнения нужных действий при срабатывании. 

Цитата(maloicds @  10.4.2012,  23:48 Найти цитируемый пост)
действие длительностью 300мс

Кстати весьма странный критерий... 

Автор: Чучмек 10.4.2012, 23:19
Код

const count=4;
var
mp:array[0..count-1]of integer;
mt:array[0..count-1]of integer;


procedure TForm1.Timer1Timer(Sender: TObject);
var i:integer;
begin

for i:=0 to count-1 do
mt[i]:=mt[i]-Timer1.Interval;

for i:=0 to count-1 do
 if  mt[i]<=0 then
  begin
  mt[i]:=mp[i];//mt[i]:=mt[i]+mp[i]
  //
  Здесь обработка i-го события
  //
  break;
  end;


end;

Автор: maloicds 10.4.2012, 23:22
Пишу прогу для работы с 1-wire сетью. Время выполнения любого запроса (измерение температуры, команды к датчикам) занимают в среднем 300мс. В то же время необходимо делать опрос сети на предмет получения значений и показаний. Исходя из этого и был выбран интервал 300мс.

Автор: DarkProg 10.4.2012, 23:37
Цитата(maloicds @  11.4.2012,  00:22 Найти цитируемый пост)
В то же время необходимо делать опрос сети на предмет получения значений и показаний.

Так вам нужна многопоточность....

Автор: northener 11.4.2012, 00:09
Цитата(DarkProg @  10.4.2012,  23:09 Найти цитируемый пост)
Для того чтобы таймер работал адекватно, в него нельзя засовывать при срабатывании какие-либо действия, иначе он тратит время на то чтобы выполнить что-тро и следующее действие сработает как бы позже чем надо, хотя с точки зрения таймера всё будет верно.

Хм. Весьма спорное заявление. Действия в данном случае засовываются не в сам таймер, а в обработчик события OnTimer. Т.е. в обработчик сообщения WM_TIMER окна, которое для данного таймера указано. Удлинять интервал эта обработка может только в том случае, когда эти действия занимают больше времени, чем интервал таймера. Но в таком случае PostMessage довольно плохой помощник, ибо будет происходить накопление в очереди сообщений окна  ваших сообщений.  Что может просто сделать программу неработоспособной. Кстати сообщения WM_TIMER в отличие от ваших пользовательских в очереди окна не накапливаются.

Добавлено через 14 минут и 46 секунд
Цитата(maloicds @  10.4.2012,  23:22 Найти цитируемый пост)
Пишу прогу для работы с 1-wire сетью.

Вот тут стоило бы подробнее сообщить что это за "1-wire сеть". MicroLan от DallasSemiconductors? Тогда я вас разочарую. В ОС Windows вы не сможете работать с этим протоколом. Вам понадобится внешняя нестандартная железяка, которая будет этот протокол выполнять, а ваша программа на ПК будет общаться с ней через стандартный порт ПК. Например через СОМ. 

Автор: northener 11.4.2012, 00:34
И ещё одно дополнение. Если это действительно MicroLan, то по рекомендациям время зарядки внутреннего конденсатора для питания микропроцессора должно быть >= 500мс (если мне не изменяет мой склероз и если не изменились рекомендации).

Автор: maloicds 11.4.2012, 15:39
Цитата(northener @ 11.4.2012,  00:34)
время зарядки внутреннего конденсатора для питания микропроцессора должно быть >= 500мс

Возможно, но я не использую паразитное питание

DarkProg Так вам нужна многопоточность....
Многопоточность здесь не подойдёт

northener
Сеть уже давно работает, сейчас отлаживаю программу....

Чучмек
Из кода я ничего не понял....

Автор: Чучмек 11.4.2012, 16:47
Цитата(maloicds @  11.4.2012,  15:39 Найти цитируемый пост)
Из кода я ничего не понял.... 

count - количество событий
В mp записываешь периоды повторения для каждого события.
В mt хранятся время прошедшее после последней  обработки каждого событя.
С каждым событием таймера mt - обновляется.
Если прошло  времени больше, чем период - обрабатываем соответствующее событие.

Автор: Чучмек 11.4.2012, 17:50
Вот:
Код

type
tEventRec=record
 period:TDateTime;
 EventTime:TDateTime;
 proc:procedure;
 end;
tEvents=class
 m:array of tEventRec;
 count:integer;
 procedure Add(period,starttime:TDateTime;procadr:pointer);
 procedure Update;
 constructor Create;
 destructor Destroy;
end;

{ tEvents }

procedure tEvents.Add(period, starttime: TDateTime; procadr: pointer);
begin
if count>=length(m)then
setlength(m,length(m)+256);
m[count].period:=period;
m[count].EventTime:=starttime;
m[count].proc:=procadr;
inc(count);
end;

constructor tEvents.Create;
begin
count:=0;
end;

destructor tEvents.Destroy;
begin
m:=nil;
end;

procedure tEvents.Update;
var
 curtime:TDateTime;
 i:integer;
begin
curtime:=Date+Time;
for i:=0 to count-1 do
 if m[i].EventTime<=curtime then
  begin
  m[i].EventTime:=m[i].EventTime+m[i].period;
  if m[i].EventTime<curtime then m[i].EventTime:=curtime+m[i].period;
  m[i].proc;
  break;
  end;  
end;

Использование:
Код

procedure p1;
begin
form1.Memo1.Lines.Add('p1');
end;
procedure p2;
begin
form1.Memo1.Lines.Add('p2');
end;
procedure p3;
begin
form1.Memo1.Lines.Add('p3');
end;

var evs:tEvents;

procedure TForm1.FormCreate(Sender: TObject);
begin
evs:=tEvents.Create;
evs.Add(1/86400,Date+Time,@p1);
evs.Add(1.5/86400,Date+Time+0.5/86400,@p2);
evs.Add(2/86400,Date+Time+2/86400,@p3);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
 evs.Update;
end;



Автор: maloicds 11.4.2012, 19:00
Чучмек спасибо за код!
Правильно ли понимаю что 1/86400 - 1с,  1.5/86400 - 1.5с, 2/86400 - 2с и какая взаимосвязь с timer.interval ??

Автор: Чучмек 11.4.2012, 19:55
Цитата(maloicds @  11.4.2012,  19:00 Найти цитируемый пост)
Правильно ли понимаю что 1/86400 - 1с,  1.5/86400 - 1.5с, 2/86400 - 2с

Да.
Цитата(maloicds @  11.4.2012,  19:00 Найти цитируемый пост)
какая взаимосвязь с timer.interval ??

В твоем случае interval=300. 
Необходимо только учесть, что если, например, интервал 1000 и три события с периодом 2с - то третье событие никогда не наступит.   

Автор: maloicds 11.4.2012, 20:44
А что за магическое число 86400? И что если захочу поменять интервал у таймера?

Автор: Чучмек 11.4.2012, 23:38
Цитата(maloicds @  11.4.2012,  20:44 Найти цитируемый пост)
А что за магическое число 86400?

24часа*60минут*60секунд

Автор: northener 12.4.2012, 01:30
Цитата(maloicds @  11.4.2012,  15:39 Найти цитируемый пост)
northener
Сеть уже давно работает, сейчас отлаживаю программу....

Мне всё же интересно узнать что это за сеть.  Если будет время и возможность - сообщите пожалуйста. Можно приватно (в личку).

Автор: maloicds 12.4.2012, 10:34
northener, ответил в личке.

Автор: northener 13.4.2012, 00:34
Цитата(maloicds @  12.4.2012,  10:34 Найти цитируемый пост)
northener, ответил в личке. 

Да отстал я от жизни. 

Ещё раз спасибо. Благодаря тем "названиям" я понял, что упустил скачок в развитии этой технологии. Так что я дезавуирую своё утвердение "Тогда я вас разочарую. В ОС Windows вы не сможете работать с этим протоколом."
Но ведь ещё несколько лет назад для MicroLan были у разработчков только примеры для ДОС! При  том что сам протокол уже лет 20 как существует.
Будут конкретные вопросы по работе с конкретными устройствами - готов помочь.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)