Программирование LEGO NXT роботов на языке NXC - Дополнительная информация о сенсорах — различия между версиями

Материал из roboforum.ru Wiki
Перейти к: навигация, поиск
(Подводим итоги)
 
(не показано 12 промежуточных версий этого же участника)
Строка 2: Строка 2:
  
 
=Дополнительная информация о сенсорах=
 
=Дополнительная информация о сенсорах=
In Chapter V we discussed the basic aspects of using sensors. But there is a lot more you can do with sensors. In
+
В главе 5 мы обсудили простейшие приёмы использования сенсоров, но на самом деле с ними можно делать намного больше. В этой главе мы обсудим отличие между режимом и типом сенсора, увидим как использовать старые RCX-совместимые сенсоры и подключать их к блоку NXT используя кабели "Lego converter cable".
this chapter we will discuss the difference between sensor mode and sensor type, we will see how to use the old
+
 
compatible RCX sensors, attaching them to NXT using Lego converter cables.
 
 
==Режимы и типы сенсоров==
 
==Режимы и типы сенсоров==
The SetSensor() command that we saw before does actually two things: it sets the type of the sensor, and it
+
Команда SetSensor(), которую мы видели ранее, реально делает две вещи: она устанавливает тип сенсора и режим, в котором этот сенсор будет работать. Путём установки режима и типа сенсора отдельными полями вы можете более точно контролировать поведение сенсора, что полезно в различных задачах.
sets the mode in which the sensor operates. By setting the mode and type of a sensor separately, you can control
 
the behavior of the sensor more precisely, which is useful for particular applications.
 
The type of the sensor is set with the command SetSensorType(). There are many different types, but I will
 
report the main ones: SENSOR_TYPE_TOUCH, which is the touch sensor, SENSOR_TYPE_LIGHT_ACTIVE, which
 
is the light sensor (with led on), SENSOR_TYPE_SOUND_DB, which is the sound sensor, and
 
SENSOR_TYPE_LOWSPEED_9V, which is the Ultrasonic sensor. Setting the type sensor is in particular important
 
to indicate whether the sensor needs power (e.g. to light up led in the light sensor), or to indicate NXT that the
 
sensor is digital and needs to be read via I2C serial protocol. It is possible to use old RCX sensor with NXT:
 
SENSOR_TYPE_TEMPERATURE, for the temperature sensor, SENSOR_TYPE_LIGHT for old light sensor,
 
SENSOR_TYPE_ROTATION for RCX rotation sensor (this type will be discussed later).
 
The mode of the sensor is set with the command SetSensorMode(). There are eight different modes. The most
 
important one is SENSOR_MODE_RAW. In this mode, the value you get when checking the sensor is a number
 
between 0 and 1023. It is the raw value produced by the sensor. What it means depends on the actual sensor. For
 
example, for a touch sensor, when the sensor is not pushed the value is close to 1023. When it is fully pushed, it
 
is close to 50. When it is pushed partially the value ranges between 50 and 1000. So if you set a touch sensor to
 
raw mode you can actually find out whether it is touched partially. When the sensor is a light sensor, the value
 
ranges from about 300 (very light) to 800 (very dark). This gives a much more precise value than using the
 
SetSensor() command. For details, see the NXC Programming Guide.
 
The second sensor mode is SENSOR_MODE_BOOL. In this mode the value is 0 or 1. When the raw value is above
 
562 the value is 0, otherwise it is 1. SENSOR_MODE_BOOL is the default mode for a touch sensor, but can be used
 
for other types, discarding analogic informations. The modes SENSOR_MODE_CELSIUS and
 
SENSOR_MODE_FAHRENHEIT are useful with temperature sensors only and give the temperature in the indicated
 
way. SENSOR_MODE_PERCENT turns the raw value into a value between 0 and 100. SENSOR_MODE_PERCENT is
 
the default mode for a light sensor. SENSOR_MODE_ROTATION is used only for the rotation sensor (see below).
 
There are two other interesting modes: SENSOR_MODE_EDGE and SENSOR_MODE_PULSE. They count transitions,
 
that is, changes from a low to a high raw value or opposite. For example, when you touch a touch sensor this
 
causes a transition from high to low raw value. When you release it you get a transition the other direction.
 
When you set the sensor mode to SENSOR_MODE_PULSE, only transitions from low to high are counted. So each
 
touch and release of the touch sensor counts for one. When you set the sensor mode to SENSOR_MODE_EDGE,
 
both transitions are counted. So each touch and release of the touch sensor counts for two. So you can use this to
 
count how often a touch sensor is pushed. Or you can use it in combination with a light sensor to count how
 
often a (strong) lamp is switched on and off. Off course, when you are counting edges or pulses, you should be
 
able to set the counter back to 0. For this you use the command ClearSensor(), that clears the counter for the
 
indicated sensor.
 
Let us look at an example. The following program uses a touch sensor to steer the robot. Connect the touch
 
sensor with a long wire to input one. If touch the sensor quickly twice the robot moves forwards. It you touch it
 
once it stops moving.
 
  
task main()
+
Тип сенсора устанавливается командой SetSensorType(). Существует множество различных типов, но я опишу только основные:
{
+
* SENSOR_TYPE_TOUCH, сенсор касания,
SetSensorType(IN_1, SENSOR_TYPE_TOUCH);
+
* SENSOR_TYPE_LIGHT_ACTIVE, датчик освещенности (с включенным светодиодом, т.е. работающий по отраженному свету),
SetSensorMode(IN_1, SENSOR_MODE_PULSE);
+
* SENSOR_TYPE_SOUND_DB, датчик звука и
while(true)
+
* SENSOR_TYPE_LOWSPEED_9V - ультразвуковой дальномер.
{
+
Установка типа сенсора важна для определения нужно ли подавать питание (включает светодиод в датчике освещенности), или для указания модулю NXT, что сенсор цифровой и надо работать с ним по протоколу I2C. Кроме всего прочего допускается использование с NXT сенсоров из старого набора, поставляемого с модулем RCX:
ClearSensor(IN_1);
+
* SENSOR_TYPE_TEMPERATURE, датчик температуры,
until (SENSOR_1 > 0);
+
* SENSOR_TYPE_LIGHT - старый датчик освещенности,
Wait(500);
+
* SENSOR_TYPE_ROTATION - датчик положения вала (датчик вращения) - этот тип мы обсудим позже.
if (SENSOR_1 == 1) {Off(OUT_AC);}
+
 
if (SENSOR_1 == 2) {OnFwd(OUT_AC, 75);}
+
Режим датчика задаётся командой SetSensorMode(). Существует 8 различных режимов. Наиболее важный - это SENSOR_MODE_RAW. В этом режиме, значение, которое вы получаете от сенсора является числом и лежит в диапазоне 0..1023. Это исходное значение, которое выдаёт датчик. Что оно означает - зависит от того, какой датчик подключен. Например, для датчика касания, когда он не нажат, значение близко к 1023, а когда полностью нажат - близко к 50. При частичном нажатии значение варьируется между 50 и 1000. Так что если вы установите датчик касания в этот режим, вы сможете определять, когда датчик нажат частично. С датчиком освещенности значение варьируется между 300 (очень светло) и 800 (очень темно). Это даёт гораздо значение большей точности, чем при использовании команды
}
+
SetSensor(). Для более подробной информации смотрите инструкцию по программированию к языку NXC.
}
+
 
Note that we first set the type of the sensor and then the mode. It seems that this is essential because changing
+
Второй режим работы сенсоров - SENSOR_MODE_BOOL. В этом режиме возвращаемое значение 0 или 1. Оно получается из исходного значения 0..1023 сравнением, если меньше 565, возвращается 0, иначе 1. SENSOR_MODE_BOOL является режимом по умолчанию для датчика касания, но может быть быть применен к любому другому сенсору, чтобы убрать аналоговую информацию и оставить двоичный ответ. Режимы SENSOR_MODE_CELSIUS и SENSOR_MODE_FAHRENHEIT полезны только для датчиков температуры и дают ответ в соответствующих единицах измерения. SENSOR_MODE_PERCENT превращает исходное значение 0..1023 в значение между 0 и 100, просто деля его на 1023. SENSOR_MODE_PERCENT является режимом по умолчанию для датчика освещенности. SENSOR_MODE_ROTATION используется только для сенсора вращения (см. ниже).
the type also affects the mode.
+
 
 +
Есть еще два интересных режима: SENSOR_MODE_EDGE и SENSOR_MODE_PULSE. Они считают переходы между высоким и низким уровнем сигнала с датчика или наоборот. Например, когда мы нажимаете на датчик касания это вызывает переход с высокого к низкому уровню сигнала. Когда вы отпускаете его это вызывает обратный переход. Когда вы устанавливаете сенсор в режим SENSOR_MODE_PULSE, только переходы с низкого на высокий уровень считаются. Так что каждое нажатие и отпускание сенсора касания считается за 1. А когда вы устанавливаете режим датчика в SENSOR_MODE_EDGE, оба перехода засчитываются, т.е. когда вы нажимаете и отпускаете датчик - счетчик увеличивается на 2. Вы можете использовать этот режим для подсчета того, сколько раз нажимали на датчик касания. Или с датчиком освещенности вы можете посчитать как часто включали/выключали освещение. Разумеется, когда вы считаете количество срабатываний или переходов, у вас должна быть возможность сбросить счетчик в ноль. Для этого используйте команду ClearSensor(), которая сбрасывает счетчик для указанного датчика.
 +
 
 +
Давайте разберем пример. Следующая программа использует датчик касания для управления роботом. Соедините датчик касания длинным проводом со входом 1. Если быстро нажать датчик касания 2 раза - робот поедет вперед, если нажать 1 раз - остановится.
 +
 
 +
task main()
 +
{
 +
  SetSensorType(IN_1, SENSOR_TYPE_TOUCH);
 +
  SetSensorMode(IN_1, SENSOR_MODE_PULSE);
 +
  while(true)
 +
  {
 +
    ClearSensor(IN_1);
 +
    until (SENSOR_1 > 0);
 +
    Wait(500);
 +
    if (SENSOR_1 == 1) {Off(OUT_AC);}
 +
    if (SENSOR_1 == 2) {OnFwd(OUT_AC, 75);}
 +
  }
 +
}
 +
 
 +
Обратите внимание, что мы сначала установили тип, а только потом - режим работы датчика. Это важно, так как установка типа датчика автоматически сбрасывает режим в значение по умолчанию для этого типа датчика.
  
 
==Сенсор вращения==
 
==Сенсор вращения==
The rotation sensor is a very useful type of sensor: it is an optical encoder, almost the same as the one built
+
Сенсор вращения это очень полезный вид датчика, представляющий из себя оптический энкодер, практический такой же, как встроенный в сервомоторы набора NXT. Датчик вращения имеет отверстие, в которое вы можете вставить вал, относительное угловое положение которого он может измеряет. Один полный оборот вала соответствует 16 шагам (или -16, если вращать в другую сторону), т.е. угловое разрешение датчика - 22.5 градуса, достаточно грубо, если сравнивать с разрешением энкодеров сервомоторов в 1 градус. Этот старый датчик вращения можно использовать для отслеживания положения вала без необходимости задействовать для этого сервомотор; кроме того не забывайте, что старый датчик ввиду отсутствия двигателя внутри гораздо легче вращается.
inside NXT servomotors. The rotation sensor contains a hole through which you can put an axle, whose relative
+
 
angular position is measured. One full rotation of the axle counts 16 steps (or –16 if you rotate it the other way),
+
Если вам нужно большее разрешение, чем 16 шагов на оборот - вы всегда можете использовать шестерни, чтобы механически увеличить его.
that means a 22.5 degrees resolution, very rough respect to the 1-degree resolution of the servomotor. This old
+
 
kind of rotation sensor can be still useful to monitor an axle without the need to waste a motor; also consider that
+
Следующий пример унаследован из старого курса для RCX.
using a motor as encoder requires a lot of torque to move it, while old rotation sensor is very easy to rotate.
+
 
If you need finer resolution than 16 steps per turn, you can always use gears to mechanically increase the number
+
Одной из типичных ситуаций является размещение двух датчиков вращения на двух колёсах, которыми вы вращаете с помощью установленных на них же двигателей. Для прямолинейного движения вам нужно, чтобы колёса вращались с одинаково быстро. К сожалению, обычно моторы не вращаются одинаково. Используя датчики вращения вы можете отследить ситуацию, когда один мотор обгоняет другой. Вы можете временно приостановить этот мотор (лучше всего - используя команду Float()), пока оба датчика вращения не выдадут одинаковое значение. Следующая программа реализует этот подход к управлению двигателями. Она просто позволяет роботу ехать строго по прямой. Чтобы проверить её на роботе - подключите датчики вращения к моторам. Подцепите сенсоры на входы 1 и 3.
of ticks per turn.
+
 
Next example is inherited from old tutorial for RCX.
+
task main()
One standard application is to have two rotation sensors connected to the two wheels of the robot that you
+
{
control with the two motors. For a straight movement you want both wheels to turn equally fast. Unfortunately,
+
  SetSensor(IN_1, SENSOR_ROTATION); ClearSensor(IN_1);
the motors normally don't run at exactly the same speed. Using the rotation sensors you can see that one wheel
+
  SetSensor(IN_3, SENSOR_ROTATION); ClearSensor(IN_3);
turns faster. You can then temporarily stop that motor (best using Float()) until both sensors give the same
+
  while (true)
value again. The following program does this. It simply lets the robot drive in a straight line. To use it, change
+
  {
your robot by connecting the two rotation sensors to the two wheels. Connect the sensors to input 1 and 3.
+
    if (SENSOR_1 < SENSOR_3)
task main()
+
      {OnFwd(OUT_A, 75); Float(OUT_C);}
{
+
    else if (SENSOR_1 > SENSOR_3)
SetSensor(IN_1, SENSOR_ROTATION); ClearSensor(IN_1);
+
      {OnFwd(OUT_C, 75); Float(OUT_A);}
SetSensor(IN_3, SENSOR_ROTATION); ClearSensor(IN_3);
+
    else
while (true)
+
      {OnFwd(OUT_AC, 75);}
{
+
  }
if (SENSOR_1 < SENSOR_3)
+
}
{OnFwd(OUT_A, 75); Float(OUT_C);}
+
 
else if (SENSOR_1 > SENSOR_3)
+
Программа сначала определяет, что оба датчика являются датчиками вращения, после чего сбрасывает их значения в 0. Потом запускается бесконечный цикл. В цикле мы проверяем, если значения датчиков совпадают - просто едем вперед. Если же один больше, чем другой - мы приостанавливаем соответствующий двигатель, пока другой не догонит его и датчики снова не покажут равные значения.
{OnFwd(OUT_C, 75); Float(OUT_A);}
+
 
else
+
На самом деле это очень простая программа. Вы можете расширить её, чтобы робот перемещался на четко заданное расстояние или точно выполнял указанные повороты.
{OnFwd(OUT_AC, 75);}
 
}
 
}
 
The program first indicates that both sensors are rotation sensors, and resets the values to zero. Next it starts an
 
infinite loop. In the loop we check whether the two sensor readings are equal. If they are the robot simply moves
 
forwards. If one is larger, the correct motor is stopped until both readings are again equal.
 
Clearly this is only a very simple program. You can extend this to make the robot drive exact distances, or to let
 
it make very precise turns.
 
  
 
==Подключение нескольких сенсоров к одному входу==
 
==Подключение нескольких сенсоров к одному входу==
A little disclaimer is needed at the top of this section! Due to the new structure of improved NXT sensors and 6-
+
Есть смысл сделать небольшое предупреждение перед тем, как вы приступите к чтению этого раздела! Из-за новой структуры улучшенных датчиков платформы NXT и кабелей на 6 линий, эта возможность стала сложнее, чем с RCX-набором подключать больше чем 1 датчик на порт модуля. По моему мнению единственное имеющее смысл и более менее простое применение указанной ниже информации - сборка разветвителя датчика касания с помощью кабеля конвертера. Альтернатива которому - полноценный цифровой мультиплексор, который может работать по протоколу I2C с модулем NXT, но это однозначно не лучшее решение для начинающих.
wires cables, it is not easy as before (as was for RCX) to connect more sensors to the same port. In my honest
+
 
opinion, the only reliable (and easy to do) application would be to build a touch sensor analog multiplexer to use
+
Модуль NXT имеет 4 входя для подключения датчиков. Когда вы хотите собрать более сложного робота (и купили несколько дополнительных датчиков) этого может оказаться недостаточно для вас. К счастью есть несколько трюков, с помощью которых вы можете подключить два (или даже больше) датчиков к одному входу.
in combination with a converter cable. The alternative is a complex digital multiplexer that can manage I2C
+
 
communication with NXT, but this is not definitely an affordable solution for beginners.
+
Проще всего подключить два датчика касания к одному входу. Когда один (любой) из них нажат (или оба) - значение датчика будет 1, иначе 0. Вы не можете отличить какой датчик сработал, но иногда это и не нужно. Например, когда вы размещаете один датчик спереди, а второй сзади, вы можете понять каким стукнулись о препятствие по тому, куда вы сейчас ехали - вперед или назад. Еще вы можете установить режим сенсора RAW (см. выше). Теперь вы сможете получать больше информации. Если вам повезёт - значения нажатого и не нажатого сенсора будет разным для обоих сенсоров. Тогда вы сможете отличать какой из них нажат. А если нажаты сразу оба - вы получите намного меньшее значение (около 30) и тоже сможете это обнаружить.
The NXT has four inputs to connect sensors. When you want to make more complicated robots (and you bought
+
 
some extra sensors) this might not be enough for you. Fortunately, with some tricks, you can connect two (or
+
Вы можете так же соединить датчик касания и датчик освещенности с одним входом (только для датчиков из набора RCX). Установите при этом тип сенсора "датчик света" (иначе датчик света не будет работать). Установите режим RAW. В этом случае, если нажат датчик касания - вы получите значение ниже 100. Если же он не нажат - вы получите значение датчика освещенности, которое никогда не бывает ниже 100.
even more) sensors to one input.
+
 
The easiest is to connect two touch sensors to one input. If one of them (or both) is touched the value is 1,
+
Следующая программа использует этот подход. Робот должен быть снабжён датчиком освещенности, направленным вниз и датчиком касания выставленным в качестве бампера вперед. Соедините оба датчика ко входу 1. Робот будет ездить случайным образом по освещенной территории, отъезжая от препятствий. Когда датчик освещенности (значение с датчика > 750) попадает на тёмное место робот немного отъезжает назад. Когда что-то нажимает датчик касания (значение < 100) он делает то же самое. Вот текст это программы:
otherwise it is 0. You cannot distinguish the two but sometimes this is not necessary. For example, when you put
+
 
one touch sensor at the front and one at the back of the robot, you know which one is touched based on the
+
mutex moveMutex;
direction the robot is driving in. But you can also set the mode of the input to raw (see above). Now you can get
+
int ttt,tt2;
a lot more information. If you are lucky, the value when the sensor is pressed is not the same for both sensors. If
+
this is the case you can actually distinguish between the two sensors. And when both are pressed you get a much
+
task moverandom()
lower value (around 30) so you can also detect this.
+
{
You can also connect a touch sensor and a light sensor to one input (RCX sensors only). Set the type to light
+
  while (true)
(otherwise the light sensor won't work). Set the mode to raw. In this case, when the touch sensor is pushed you
+
  {
get a raw value below 100. If it is not pushed you get the value of the light sensor, which is never below 100.
+
    ttt = Random(500) + 40;
The following program uses this idea. The robot must be equipped with a light sensor pointing down, and a
+
    tt2 = Random();
bumper at the front connected to a touch sensor. Connect both of them to input 1. The robot will drive around
+
    Acquire(moveMutex);
randomly within a light area. When the light sensor sees a dark line (raw value > 750) it goes back a bit. When
+
    if (tt2 > 0)
the touch sensor touches something (raw value below 100) it does the same. Here is the program:
+
      { OnRev(OUT_A, 75); OnFwd(OUT_C, 75); Wait(ttt); }
 +
    else
 +
      { OnRev(OUT_C, 75); OnFwd(OUT_A, 75); Wait(ttt); }
 +
    ttt = Random(1500) + 50;
 +
    OnFwd(OUT_AC, 75); Wait(ttt);
 +
    Release(moveMutex);
 +
  }
 +
}
 +
 +
task submain()
 +
{
 +
  SetSensorType(IN_1, SENSOR_TYPE_LIGHT);
 +
  SetSensorMode(IN_1, SENSOR_MODE_RAW);
 +
  while (true)
 +
  {
 +
    if ((SENSOR_1 < 100) || (SENSOR_1 > 750))
 +
    {
 +
      Acquire(moveMutex);
 +
      OnRev(OUT_AC, 75); Wait(300);
 +
      Release(moveMutex);
 +
    }
 +
  }
 +
}
 +
 +
task main()
 +
{
 +
  Precedes(moverandom, submain);
 +
}
  
mutex moveMutex;
+
Я надеюсь программа получилась понятная. В ней есть две задачи. Задача "moverandom" заставляет робота случайным образом блуждать. Главная задача запускает "moverandom", потом переходит в своё продолжение "submain" чтобы запустилась "moverandom", настраивает сенсоры и ждет пока что-нибудь случится. Если значения сенсоров будут слишком малы (касание) или слишком велики (выехали из освещенного района) она остановит случайные блуждания, отъедет немного назад и затем снова продолжит случайные движения.
int ttt,tt2;
 
task moverandom()
 
{
 
while (true)
 
{
 
ttt = Random(500) + 40;
 
tt2 = Random();
 
Acquire(moveMutex);
 
if (tt2 > 0)
 
{ OnRev(OUT_A, 75); OnFwd(OUT_C, 75); Wait(ttt); }
 
else
 
{ OnRev(OUT_C, 75); OnFwd(OUT_A, 75); Wait(ttt); }
 
ttt = Random(1500) + 50;
 
OnFwd(OUT_AC, 75); Wait(ttt);
 
Release(moveMutex);
 
}
 
}
 
task submain()
 
{
 
SetSensorType(IN_1, SENSOR_TYPE_LIGHT);
 
SetSensorMode(IN_1, SENSOR_MODE_RAW);
 
while (true)
 
{
 
if ((SENSOR_1 < 100) || (SENSOR_1 > 750))
 
{
 
Acquire(moveMutex);
 
OnRev(OUT_AC, 75); Wait(300);
 
Release(moveMutex);
 
}
 
}
 
}
 
task main()
 
{
 
Precedes(moverandom, submain);
 
}
 
I hope the program is clear. There are two tasks. Task moverandom makes the robot move around in a random
 
way. The main task first starts moverandom, sets the sensor and then waits for something to happen. If the
 
sensor reading gets too low (touching) or too high (out of the white area) it stops the random moves, backs up a
 
little, and start the random moves again.
 
  
 
==Подводим итоги==
 
==Подводим итоги==
In this chapter we have seen a number of additional issues about sensors. We saw how to separately set the type
+
В этой главе вы познакомились с некоторым количеством дополнительных возможностей сенсоров. Мы увидели, как отдельно устанавливать тип и режим работы датчиков, как эти режимы могут быть использованы для получения дополнительной информации. Мы научились использовать датчик вращения и увидели, как несколько датчиков можно подключить к одному входу NXT. Все эти трюки очень полезны при сборке достаточно сложных роботов, в которых сенсоры имеют огромное значение.
and mode of a sensor and how this could be used to get additions information. We learned how to use the
 
rotation sensor. And we saw how multiple sensors can be connected to one input of the NXT. All these tricks are
 
extremely useful when constructing more complicated robots. Sensors always play a crucial role there.
 

Текущая версия на 07:06, 20 мая 2009

Автор: Daniele Benedettelli

Перевод: © Ботов Антон aka =DeaD=, 2009

Эксклюзивно для www.roboforum.ru
копирование на другие ресурсы и публикация перевода
без разрешения его автора запрещены

Дополнительная информация о сенсорах

В главе 5 мы обсудили простейшие приёмы использования сенсоров, но на самом деле с ними можно делать намного больше. В этой главе мы обсудим отличие между режимом и типом сенсора, увидим как использовать старые RCX-совместимые сенсоры и подключать их к блоку NXT используя кабели "Lego converter cable".

Режимы и типы сенсоров

Команда SetSensor(), которую мы видели ранее, реально делает две вещи: она устанавливает тип сенсора и режим, в котором этот сенсор будет работать. Путём установки режима и типа сенсора отдельными полями вы можете более точно контролировать поведение сенсора, что полезно в различных задачах.

Тип сенсора устанавливается командой SetSensorType(). Существует множество различных типов, но я опишу только основные:

  • SENSOR_TYPE_TOUCH, сенсор касания,
  • SENSOR_TYPE_LIGHT_ACTIVE, датчик освещенности (с включенным светодиодом, т.е. работающий по отраженному свету),
  • SENSOR_TYPE_SOUND_DB, датчик звука и
  • SENSOR_TYPE_LOWSPEED_9V - ультразвуковой дальномер.

Установка типа сенсора важна для определения нужно ли подавать питание (включает светодиод в датчике освещенности), или для указания модулю NXT, что сенсор цифровой и надо работать с ним по протоколу I2C. Кроме всего прочего допускается использование с NXT сенсоров из старого набора, поставляемого с модулем RCX:

  • SENSOR_TYPE_TEMPERATURE, датчик температуры,
  • SENSOR_TYPE_LIGHT - старый датчик освещенности,
  • SENSOR_TYPE_ROTATION - датчик положения вала (датчик вращения) - этот тип мы обсудим позже.

Режим датчика задаётся командой SetSensorMode(). Существует 8 различных режимов. Наиболее важный - это SENSOR_MODE_RAW. В этом режиме, значение, которое вы получаете от сенсора является числом и лежит в диапазоне 0..1023. Это исходное значение, которое выдаёт датчик. Что оно означает - зависит от того, какой датчик подключен. Например, для датчика касания, когда он не нажат, значение близко к 1023, а когда полностью нажат - близко к 50. При частичном нажатии значение варьируется между 50 и 1000. Так что если вы установите датчик касания в этот режим, вы сможете определять, когда датчик нажат частично. С датчиком освещенности значение варьируется между 300 (очень светло) и 800 (очень темно). Это даёт гораздо значение большей точности, чем при использовании команды SetSensor(). Для более подробной информации смотрите инструкцию по программированию к языку NXC.

Второй режим работы сенсоров - SENSOR_MODE_BOOL. В этом режиме возвращаемое значение 0 или 1. Оно получается из исходного значения 0..1023 сравнением, если меньше 565, возвращается 0, иначе 1. SENSOR_MODE_BOOL является режимом по умолчанию для датчика касания, но может быть быть применен к любому другому сенсору, чтобы убрать аналоговую информацию и оставить двоичный ответ. Режимы SENSOR_MODE_CELSIUS и SENSOR_MODE_FAHRENHEIT полезны только для датчиков температуры и дают ответ в соответствующих единицах измерения. SENSOR_MODE_PERCENT превращает исходное значение 0..1023 в значение между 0 и 100, просто деля его на 1023. SENSOR_MODE_PERCENT является режимом по умолчанию для датчика освещенности. SENSOR_MODE_ROTATION используется только для сенсора вращения (см. ниже).

Есть еще два интересных режима: SENSOR_MODE_EDGE и SENSOR_MODE_PULSE. Они считают переходы между высоким и низким уровнем сигнала с датчика или наоборот. Например, когда мы нажимаете на датчик касания это вызывает переход с высокого к низкому уровню сигнала. Когда вы отпускаете его это вызывает обратный переход. Когда вы устанавливаете сенсор в режим SENSOR_MODE_PULSE, только переходы с низкого на высокий уровень считаются. Так что каждое нажатие и отпускание сенсора касания считается за 1. А когда вы устанавливаете режим датчика в SENSOR_MODE_EDGE, оба перехода засчитываются, т.е. когда вы нажимаете и отпускаете датчик - счетчик увеличивается на 2. Вы можете использовать этот режим для подсчета того, сколько раз нажимали на датчик касания. Или с датчиком освещенности вы можете посчитать как часто включали/выключали освещение. Разумеется, когда вы считаете количество срабатываний или переходов, у вас должна быть возможность сбросить счетчик в ноль. Для этого используйте команду ClearSensor(), которая сбрасывает счетчик для указанного датчика.

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

task main()
{
  SetSensorType(IN_1, SENSOR_TYPE_TOUCH);
  SetSensorMode(IN_1, SENSOR_MODE_PULSE);
  while(true)
  {
    ClearSensor(IN_1);
    until (SENSOR_1 > 0);
    Wait(500);
    if (SENSOR_1 == 1) {Off(OUT_AC);}
    if (SENSOR_1 == 2) {OnFwd(OUT_AC, 75);}
  }
}

Обратите внимание, что мы сначала установили тип, а только потом - режим работы датчика. Это важно, так как установка типа датчика автоматически сбрасывает режим в значение по умолчанию для этого типа датчика.

Сенсор вращения

Сенсор вращения это очень полезный вид датчика, представляющий из себя оптический энкодер, практический такой же, как встроенный в сервомоторы набора NXT. Датчик вращения имеет отверстие, в которое вы можете вставить вал, относительное угловое положение которого он может измеряет. Один полный оборот вала соответствует 16 шагам (или -16, если вращать в другую сторону), т.е. угловое разрешение датчика - 22.5 градуса, достаточно грубо, если сравнивать с разрешением энкодеров сервомоторов в 1 градус. Этот старый датчик вращения можно использовать для отслеживания положения вала без необходимости задействовать для этого сервомотор; кроме того не забывайте, что старый датчик ввиду отсутствия двигателя внутри гораздо легче вращается.

Если вам нужно большее разрешение, чем 16 шагов на оборот - вы всегда можете использовать шестерни, чтобы механически увеличить его.

Следующий пример унаследован из старого курса для RCX.

Одной из типичных ситуаций является размещение двух датчиков вращения на двух колёсах, которыми вы вращаете с помощью установленных на них же двигателей. Для прямолинейного движения вам нужно, чтобы колёса вращались с одинаково быстро. К сожалению, обычно моторы не вращаются одинаково. Используя датчики вращения вы можете отследить ситуацию, когда один мотор обгоняет другой. Вы можете временно приостановить этот мотор (лучше всего - используя команду Float()), пока оба датчика вращения не выдадут одинаковое значение. Следующая программа реализует этот подход к управлению двигателями. Она просто позволяет роботу ехать строго по прямой. Чтобы проверить её на роботе - подключите датчики вращения к моторам. Подцепите сенсоры на входы 1 и 3.

task main()
{
  SetSensor(IN_1, SENSOR_ROTATION); ClearSensor(IN_1);
  SetSensor(IN_3, SENSOR_ROTATION); ClearSensor(IN_3);
  while (true)
  {
    if (SENSOR_1 < SENSOR_3)
      {OnFwd(OUT_A, 75); Float(OUT_C);}
    else if (SENSOR_1 > SENSOR_3)
      {OnFwd(OUT_C, 75); Float(OUT_A);}
    else
      {OnFwd(OUT_AC, 75);}
  }
}

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

На самом деле это очень простая программа. Вы можете расширить её, чтобы робот перемещался на четко заданное расстояние или точно выполнял указанные повороты.

Подключение нескольких сенсоров к одному входу

Есть смысл сделать небольшое предупреждение перед тем, как вы приступите к чтению этого раздела! Из-за новой структуры улучшенных датчиков платформы NXT и кабелей на 6 линий, эта возможность стала сложнее, чем с RCX-набором подключать больше чем 1 датчик на порт модуля. По моему мнению единственное имеющее смысл и более менее простое применение указанной ниже информации - сборка разветвителя датчика касания с помощью кабеля конвертера. Альтернатива которому - полноценный цифровой мультиплексор, который может работать по протоколу I2C с модулем NXT, но это однозначно не лучшее решение для начинающих.

Модуль NXT имеет 4 входя для подключения датчиков. Когда вы хотите собрать более сложного робота (и купили несколько дополнительных датчиков) этого может оказаться недостаточно для вас. К счастью есть несколько трюков, с помощью которых вы можете подключить два (или даже больше) датчиков к одному входу.

Проще всего подключить два датчика касания к одному входу. Когда один (любой) из них нажат (или оба) - значение датчика будет 1, иначе 0. Вы не можете отличить какой датчик сработал, но иногда это и не нужно. Например, когда вы размещаете один датчик спереди, а второй сзади, вы можете понять каким стукнулись о препятствие по тому, куда вы сейчас ехали - вперед или назад. Еще вы можете установить режим сенсора RAW (см. выше). Теперь вы сможете получать больше информации. Если вам повезёт - значения нажатого и не нажатого сенсора будет разным для обоих сенсоров. Тогда вы сможете отличать какой из них нажат. А если нажаты сразу оба - вы получите намного меньшее значение (около 30) и тоже сможете это обнаружить.

Вы можете так же соединить датчик касания и датчик освещенности с одним входом (только для датчиков из набора RCX). Установите при этом тип сенсора "датчик света" (иначе датчик света не будет работать). Установите режим RAW. В этом случае, если нажат датчик касания - вы получите значение ниже 100. Если же он не нажат - вы получите значение датчика освещенности, которое никогда не бывает ниже 100.

Следующая программа использует этот подход. Робот должен быть снабжён датчиком освещенности, направленным вниз и датчиком касания выставленным в качестве бампера вперед. Соедините оба датчика ко входу 1. Робот будет ездить случайным образом по освещенной территории, отъезжая от препятствий. Когда датчик освещенности (значение с датчика > 750) попадает на тёмное место робот немного отъезжает назад. Когда что-то нажимает датчик касания (значение < 100) он делает то же самое. Вот текст это программы:

mutex moveMutex;
int ttt,tt2;

task moverandom()
{
  while (true)
  {
    ttt = Random(500) + 40;
    tt2 = Random();
    Acquire(moveMutex);
    if (tt2 > 0)
      { OnRev(OUT_A, 75); OnFwd(OUT_C, 75); Wait(ttt); }
    else
      { OnRev(OUT_C, 75); OnFwd(OUT_A, 75); Wait(ttt); }
    ttt = Random(1500) + 50;
    OnFwd(OUT_AC, 75); Wait(ttt);
    Release(moveMutex);
  }
}

task submain()
{
  SetSensorType(IN_1, SENSOR_TYPE_LIGHT);
  SetSensorMode(IN_1, SENSOR_MODE_RAW);
  while (true)
  {
    if ((SENSOR_1 < 100) || (SENSOR_1 > 750))
    {
      Acquire(moveMutex);
      OnRev(OUT_AC, 75); Wait(300);
      Release(moveMutex);
    }
  }
}

task main()
{
  Precedes(moverandom, submain);
}

Я надеюсь программа получилась понятная. В ней есть две задачи. Задача "moverandom" заставляет робота случайным образом блуждать. Главная задача запускает "moverandom", потом переходит в своё продолжение "submain" чтобы запустилась "moverandom", настраивает сенсоры и ждет пока что-нибудь случится. Если значения сенсоров будут слишком малы (касание) или слишком велики (выехали из освещенного района) она остановит случайные блуждания, отъедет немного назад и затем снова продолжит случайные движения.

Подводим итоги

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