roboforum.ru

Технический форум по робототехнике.

Фоновый режим

Фоновый режим

GrayHunter » 04 апр 2011, 13:46

Имеется AtMega8. Как писать что-то простое для него на ассемблере разобрался. Но загадкой для меня остаётся фоновый режим. Например, я хочу, чтобы МК что-то делал, но чтобы всегда в фоновом режиме висела проверка чего-нибудь (какой-нибудь дачик). Как это написать?

Т.е. последовательно я могу всё прописывать, но не вставлять же после каждой строки выполнение подпрограммы? Наверняка есть способ как-то запустить её в фоновом режиме, чтобы если вдруг сработает датчик, то чтобы перебросило на определённый участок кода.

Подскажите, пожалуйста.

P.S.- и ещё, 1 секунда реального времени - это сколько будет в AtMega8 при стандартных настройках? :oops:

Re: Фоновый режим

dccharacter » 04 апр 2011, 13:59

искать по слову "прерывание" (interrupt)

Re: Фоновый режим

Radist » 04 апр 2011, 20:23

Прерывания - страшная сила. А секунда - она и в Африке секунда. Контроллер работает на своей тактовой частоте, на нее нет стандарта. Есть понятие "клок" - время одного такта. Если вам нужна задержка ровно на секунду, то нужно выполнить программу, состоящую из такого числа тактов, которое написано на кварце. Для 8 МГц это 8 000 000 тактов. А длина одного такта 125 нс.

Re: Фоновый режим

vadinator » 04 апр 2011, 20:30

dccharacter писал(а):искать по слову "прерывание" (interrupt)

...добавлю ещё - прерывание по таймеру...
Настраиваете внутренний таймер на прерывание - ну например с частотой 1кГц и в нём уже вызываете нужные вам процедуры или прямо в процедуру обслуживания прерывания добавляете свой код...и фсё :)

Re: Фоновый режим

GrayHunter » 05 апр 2011, 13:45

Спасибо. Нашёл информацию на Радио Коте, прочитал.

Появился вопрос о приоритетности или иерархичности прерываний (возможно ли прерывание в прерывании?). Т.е. как быть, если у меня, например:
1) в процессе выполнения прерывания произошло событие, которое важнее текущего прерывания. Получается, что нужно как-то начать другое прерывание в текущем прерывании? как?
2) а как быть, если нужно чтобы одновременно оба прерывания выполнялись?

Вот что имеется сейчас (система по автоматическому наполнению резервуаров в двух увлажнителях воздуха и поливу цветов в комнате):
мониторить датчки о недостатке воды
получить сигнал с датчика №X
открыть клапан №X
включить помпу
ждать сигнала с датчика №X2 о заполнении резервуара
выключить помпу
закрыть клапан №X
вернуться к началу (к мониторингу датчиков)

Прервать если прошли сутки (24 часа)
выключить помпу
запомнить какие клапаны сейчас открыты
закрыть открытые клапаны
полить цветы (открыть клапан цветов, включить помпу, подождать n-секунд, выключить помпу, закрыть клапан цветов)
открыть клапаны, которые запоминали
включить помпу
выйти из прерывания

Как это сделать я понимаю.

Но как добавить сюда ещё и тумблеры, которые могут принудительно (несмотря на то, что по датчику воды ещё достаточно) включить его. При этом самым важным/приоритетным событием должны быть датчики протечки, т.е. если есть протечка, то нужно отключить тот модуль, около которого протечка, несмотря на даже "принуждающий тумблер" или на прерывание по таймеру (прерывание полива цветов). Получается прерывание в прерывании (в случае с цветами)... :shock:

P.S.- пишу на Асме для AtMega8.

Re: Фоновый режим

Strijar » 05 апр 2011, 14:16

У вас не такие там скорости что бы делать это через прерывания. Это все можно сделать последовательным опросом в цикле. Почитайте про конечные автоматы (Finite-state Machine) и жить станет немного проще ;)

Re: Фоновый режим

yak-40 » 05 апр 2011, 14:17

А зачем здесь прерывания? Простейшая программка один цикл и две подпрограммы.

1.Если датчик недостатка воды сработал[идём в подпрограмму заливки резервуара]
2.Если прошли сутки[идём в подпрограмму полива]
3.Возвращаемся в пункт 1.
Фсё :D

Re: Фоновый режим

boez » 05 апр 2011, 14:20

Как по мне, такие алгоритмы лучше делать все-таки без прерываний, на флагах и счетчиках. Т.е. делается главный цикл и в нем постоянно проверяются все условия: датчики, тумблеры, счетчики прошедшего времени... Надо добавить алгоритм - добавь еще проверок, но всегда возвращайся в цикл. Никаких delay_ms(5000). Время выполнения такого цикла на авр будет десятки мкс, чего для большинства задач робототехники хватит с головой.
То есть программа выгдядит как-то так:
// расстановка флагов
1. Если протечка 1 - снять флаг клапана 1, перейти к 5
2. Если датчик наполнения 1 - снять флаг наполнения 1, перейти к 5
3. Если тумблер наполнения 1 - поставить флаг наполнения 1, перейти к 5
4. Если датчик опустошения 1 - поставить флаг наполнения 1, перейти к 5
5. Если протечка 2 - снять флаг клапана 2, перейти к 9
6. Если датчик наполнения 2 - снять флаг наполнения 2, перейти к 9
7. Если тумблер наполнения 2 - поставить флаг наполнения 2, перейти к 9
8. Если датчик опустошения 2 - поставить флаг наполнения 2, перейти к 9
9. Если (время - последнее время полива) > 24 часов - поставить флаг полива, засечь время начала полива
10. Если флаг полива и (время - время начала полива) > n секунд - снять флаг полива, обновить время последнего полива
//управление
11. Если флаг полива - выключить клапаны наполнения, включить клапан полива, включить помпу, перейти к 16
12. Если флаг наполнения 1 - выключить клапаны наполнения 2 и полива, включить клапан наполнения 1, включить помпу, перейти к 16
14. Если флаг наполнения 2 - выключить клапаны наполнения 1 и полива, включить клапан наполнения 2, включить помпу, перейти к 16
15. Выключить все клапаны и помпу
16. Перейти к 1


А в прерывании от таймера только инкрементировать глобальную переменную времени.

Добавлено спустя 2 минуты 11 секунд:
yak-40 писал(а):А зачем здесь прерывания? Простейшая программка один цикл и две подпрограммы

А с тумблерами как быть? Ну и всякие штуки типа если 24 часа прошли во время наполнения, то прервать наполнение и начать поливать (хотя не знаю, насколько это реально надо).

Re: Фоновый режим

yak-40 » 05 апр 2011, 14:24

boez писал(а):А с тумблерами как быть?

Добавить строку опроса тумблера.
boez писал(а):Ну и всякие штуки типа если 24 часа прошли во время наполнения, то прервать наполнение и начать поливать

Зачем? Наполнить резервуар, потом полить.
Хотя конечно непонятный алгоритм. Можно просто, наполнил, затем полил. А если протечка, то это уже авария. Всё выключить и сообщить хозяину. Например по СМС

Re: Фоновый режим

GrayHunter » 05 апр 2011, 14:57

Интересно. Спасибо. boez, про без пауз сделать я и не подумал...так и сделаю.

Осталось неясно как написать/реализовать:
"А в прерывании от таймера только инкрементировать глобальную переменную времени."
"9. Если (время - последнее время полива) > 24 часов - поставить флаг полива, засечь время начала полива
10. Если флаг полива и (время - время начала полива) > n секунд - снять флаг полива, обновить время последнего полива"
Я в прерываниях, таймерах не силён... буду рад помощи на Асме для AtMega8 :)

P.S.- скачал пятую студию, а там мой старый заголовочный файл ("m8def.inc") капризничает...где добыть рабочий? (или в пятой может вообще не нужно ничего присоединять?)

Re: Фоновый режим

boez » 05 апр 2011, 15:45

Да вот так и реализовать, как написано. Я могу код на С дать, на асме я бы такое писать не взялся...

Обработчик, переменные и константы:
Код: Выделить всёРазвернуть
#define ONE_DAY_TIME 86400
#define WATERING_TIME 10

#define FLAG_FILL1    1
#define FLAG_FILL2    2
#define FLAG_WATERING 4

volatile unsigned long Time;
unsigned long LastWaterTime, StartWaterTime;
unsigned char Flags;

ISR(TIMER0_OVF_vect)
{
    Time++;
};


Проверки (кстати, пока код писал - увидел, что нужны доп. проверки на флаг полива, иначе не заработает)
Код: Выделить всёРазвернуть
//9. Если (время - последнее время полива) > 24 часов и снят флаг полива - поставить флаг полива, засечь время начала полива
if ((Time-LastWaterTime>ONE_DAY_TIME)&&(!(Flags&FLAG_WATERING))) {
    StartWaterTime = Time;
    Flags |= FLAG_WATERING;
}
//10. Если флаг полива и (время - время начала полива) > n секунд и стоит флаг полива - снять флаг полива, обновить время последнего полива
if ((Time-StartWaterTime>WATERING_TIME)&&(Flags&FLAG_WATERING)) {
    LastWaterTime = Time;
    Flags &= ~FLAG_WATERING;
}

Re: Фоновый режим

GrayHunter » 05 апр 2011, 19:54

На С я только в крайнем случае попробовал бы написать...
Очень бы хотелось на Асме, её я лучше понимаю. Буду рад любой помощи :)

Re: Фоновый режим

tallarna » 05 апр 2011, 22:33

почитай туториал по многозадачной операционке на easyelectronics.ru

Re: Фоновый режим

GrayHunter » 05 апр 2011, 23:25

Про ядро для AVR почитал...для меня это излишнее в данном проекте, как мне показалось.

Тут ведь нужно лишь включить таймер, получать от него данные (сколько часов и секунд насчитал) и сравнивать их с 24 часами и n-секунд. Пожалуйста, подскажите как такое на Асме сделать, только этот кусок - остальное я сам.
Может быть это поможет - http://radiokot.ru/start/mcu_fpga/avr/11/ Там есть, например,
Код: Выделить всёРазвернуть
          ldi Temp,0        ;обнуление таймера
          out TCNT1H,Temp
          out TCNT1L,Temp

Re: Фоновый режим

tallarna » 05 апр 2011, 23:50

для начала - у atmega8 часов реального времени (хранящего часы/минуты/секунды) нету
"таймер" - подпрограмма, вызываемая, для простоты, скажем, каждые Х тактов контроллера
если нужно при этом время - придется в этой самой подпрограмме считать, сколько раз она вызвалась,и переводить данные в формат времени, даты и прочая

пример простого использования, правда с комментариями на немецком, http://www.mikrocontroller.net/attachme ... timer1.asm


Rambler\'s Top100 Mail.ru counter