Лекция 5
Иерархия классов
Пример
Опишем простой пример для демонстрации общих принцпов построения программ с использованием API для С nxtOSEK. Текст примера предоставил студент математико- механического факультета Михаил Липкович. В этом примере реализована управляющая программа для робота, движущегося вдоль стенки.
Прежде всего рассмотрим файл описания OSEK Implementation Language (OIL). Подробную справку по синтаксису OIL-файла можно найти на сайте концерна VXD/OSEK.
/* wall_osek.oil*/#include "implementation.oil" CPU ATMEL_AT91SAM7S256{ OS LEJOS_OSEK { STATUS = EXTENDED; STARTUPHOOK = FALSE; ERRORHOOK = FALSE; SHUTDOWNHOOK = FALSE; PRETASKHOOK = FALSE; POSTTASKHOOK = FALSE; USEGETSERVICEID = FALSE; USEPARAMETERACCESS = FALSE; USERESSCHEDULER = FALSE; }; APPMODE appmode1{}; TASK Motion //определение свойств задачи Motion { AUTOSTART = FALSE; //не запускаться самой при запуске //программыPRIORITY = 2; //приоритет. чем больше число, тем //выше приоритетACTIVATION = 1; //максимально число одновременно //работающих задач MotionSCHEDULE = FULL; //возможность вытеснять эту задачу //задачами более высокого приоритета STACKSIZE = 512; //размер стека }; ALARM cyclic_alarm1 //определение будильника (генератора //событий запуска задачи) { COUNTER = SysTimerCnt; //счетчик SysTimerCnt ACTION = ACTIVATETASK //при запуске будильника вызвать //задачу Motion { TASK = Motion; }; AUTOSTART = TRUE //автоазапуск будильника { ALARMTIME = 1; //время запуска будильника впервый //раз CYCLETIME = 50; //период последующих запусков APPMODE = appmode1; }; }; COUNTER SysTimerCnt //определение счетчика { MINCYCLE = 1; //минимально возможное число тиков //счетчика для использования //будильником MAXALLOWEDVALUE = 10000; //максимально//возможноезначение счетчика TICKSPERBASE = 1; //размер тика (в миллисекундах) };};Сам текст программы находится в файле wall_osek.c. Точкой входа этой программы (места с которого начинается выполнение программы) является задача task(Motion), как следует из файла wall_osek.oil, эта задача вызывается раз в 50 миллисекунд. Не следует забывать, что необходимо реализовать еще три процедуры ecrobot_device_initialize, ecrobot_device_terminate,user_1ms_isr_type2, которые формально нигде не используются, но система вызывает их автоматически.
/* wall_osek.c*/ #include "kernel.h"#include "kernel_id.h"#include "ecrobot_interface.h" //определение констант#define MOTOR_R NXT_PORT_C#define MOTOR_L NXT_PORT_A #define SONAR NXT_PORT_S1#define K 1.2 //коэффициент //пропорционального регулятора#define D 20 //расстояние до стены DeclareTask(Motion);DeclareCounter(SysTimerCnt); //инициализация моторов и ультразвукового датчика //(выполняется перед всеми задачами)void ecrobot_device_initialize() { ecrobot_set_motor_speed(MOTOR_R, 0); ecrobot_set_motor_speed(MOTOR_L, 0); ecrobot_init_sonar_sensor(SONAR);}//выполняется после завершения всех задачvoid ecrobot_device_terminate() { ecrobot_set_motor_speed(MOTOR_R, 0); ecrobot_set_motor_speed(MOTOR_L, 0); ecrobot_term_sonar_sensor(SONAR);} //процедура обработки прерываний. необходима для получения //доступа к датчикам и сервомоторамvoid user_1ms_isr_type2(void) {(void)SignalCounter(SysTimerCnt); //увеличить счетчик //SysTimerCnt для вызова периодических задач} TASK(Motion) //задача, реализующая движение { S8 base_speed = 25, u = 0; u = (ecrobot_get_sonar_sensor(SONAR)-D)*K; ecrobot_set_motor_speed(MOTOR_L, (base_speed + u)%100); ecrobot_set_motor_speed(MOTOR_R, (base_speed - u)%100); TerminateTask(); //завершение задачи}Конечно, текст самой задачи, реализующей логику работы регулятора, существенно меньше описания технической части программы. С одной стороны, это делает даже маленькую по содержанию программу объемной, но с другой, дает пространство для тонкой настройки параметров. Эта настройка, по сути, шаблонная и ее легко скопировать из другой задачи.
7.10. nxtOSEK C++
Более удобный программный интерфейс реализован для C++. Каждый датчик и мотор является экземпляром соответствующего класса, а это перекладывает работу по инициализации и завершения работы переферийных устройств на конструкторы и деструкторы соответствующих классов, инкапсуирует методы, деля синтаксии интуитивно понятным. Хоть необходимость использования процедур ecrobot_device_initialize, ecrobot_device_terminate пропадает, тем не менее, для того что бы согласовать обектно ориентированный подход с функционалом ОС РВ nxtOSEK и предоставлять классам взаимодействие с процедурами обработки прерываний, все же необходимо использовать процедуру user_1ms_isr_type2 и описать событие ОС РВ.
Как правило, в процедуре user_1ms_isr_type2 достаточно вызывать одну функцию SleeperMonitor() которая необходима для корректной работы класса Clock и корректного взаимодействия с устройвами через I2C интерфейс.
Так же необходимо указать в описании основной задачи в OIL файле события EventSleepI2C и EventSleep. Это может выглядеть, например, так:
//событие EventSleepI2CEVENT EventSleepI2C{ MASK = AUTO;};//событие EventSleepIEVENT EventSleep{ MASK = AUTO;};//описание основной задачи с названием, например, TaskMainTASK TaskMain{ AUTOSTART = TRUE { APPMODE = appmode1; }; PRIORITY = 1; ACTIVATION = 1; SCHEDULE = FULL; STACKSIZE = 512; EVENT = EventSleepI2C; //добавили событие EventSleepI2C EVENT = EventSleep; //добавили событие EventSleepI2C};Надо помнить, что так как объектам 18ти классов (датчикам, соединениям, моторам) требуется инициализация и корректноезавершение работы, их необходимо определять как глобальные объекты. В противном случае на дисплее появится сообщение об ошибке и для корректной работы устройство надо будет перезапустить. Глобальными должны быть экземпляры следующих классов:AccelSensor, Bluetooth, Camera, ColorSensor, CompassSensor, SonarSensor, IrSeeker, LegoLight, Motor, NxtColorSensor, PSPNx, Rs485, GyroSensor, LightSensor, RcxLightSensor, SoundSensor, TouchSensor.
В этом параграфе приведен список классов в алавитном порядке с учетом наследования. Многие методы классов созвучны функциям С интерфейса, поэтому подробно их описывать здесь не будем.
Все классы находятся в пространстве имен (namespace) "ecrobot", что бы использовать классы без приставки ecrobot::необходимо указасть в начале программы using namespace ecrobot. Так же, что бы генерировался корректный машинный код, необходимо сделать указание компановщику (linker) компановать программу в стиле С, т.е. код программы должен быть заключен между extern "C"{ …код программы… }(см. пример в начале главы).
· ecrobot::AccelSensor
Клаcс работы с датчиком ускорения HiTechnic.
· ecrobot::Bluetooth
Класс работы с Bluetooth.
· ecrobot::BTConnection
Устанавливает соединение через Bluetooth.
· ecrobot::Camera
Класс работы с камерой NXTCamv2.
· ecrobot::Clock
Класс работы с системными часами.
· ecrobot::ColorSensor
Класс работы с датчиком цвета NXT.
· ecrobot::CompassSensor
Класс работы с компасом HiTechnic
· ecrobot::Daq
Класс для отправки внутренних данных NXT программе NXT GamePad.
· ecrobot::GamePad
Класс для дистанционного управления с помощью джойстика GamePad.
· ecrobot::I2c
· ecrobot::SonarSensor
Класс работы с ультразвуковым датчиком.
· ecrobot::IrSeeker
Класс работы с инфракрасным датчиком.
· ecrobot::Lcd
Класс работы с дисплеем устройства NXT.
· ecrobot::LegoLight
Класс работы с датчиком освещенности NXT.
· ecrobot::Motor
Класс работы с серводвигателями NXT.
· ecrobot::Nxt
Класс работы с внутренними функциями устройства NXT (работа с кнопками, получение уровня заряда батареи).
· ecrobot::NxtColorSensor
Класс работы с датчиком цвета NXT.
· ecrobot::PSPNx
Класс работы с портом расширения для Sony Play Station.
· ecrobot::Camera::Rectangle_T
Вспомогательный класс для работы с камерой NXTCamv2.
· ecrobot::Rs485
Класс работы с интрфейсом RS485.
· ecrobot::Sensor
· ecrobot::GyroSensor
Класс работы с гироскопом.
· ecrobot::LightSensor
Класс работы с датчиком освещенности.
· ecrobot::RcxLightSensor
Класс работы с датчиком освещенности RCX.
· ecrobot::SoundSensor
Класс работы со звуковым датчиком.
· ecrobot::TouchSensor
Класс работы с датчиком касания.
· ecrobot::Speaker
Класс работы с воспроизведением звука.
· ecrobot::Usb
Класс работы с USB.
· ecrobot::VectorT < T >
Класс, реализующий вектор из двух компонент.