Лекция 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 >

Класс, реализующий вектор из двух компонент.