Infrared

Class Infrared is a subclass of EV3. You can use it to read values from a single infrared sensor without any knowledge of direct command syntax.

The infrared sensor sends and receives infrared light signals. It is able to calculate distances by analyzing reflected light. It also is able to communicate with the EV3 beacon device. This allows to determine the current position of the beacon and it allows to use the bacon as a remote control.

To use multiple infrared sensors simultaneously, you can create multiple instances of this class.

Asking for the distance from a surface

Class Infrared has an attribute distance, which is of type float and tells, if the the sensor currently sees some surface in front of the sensor and in a distance closer than 1.00 m.

Connect your EV3 device with your local network via WiFi. Replace the MAC-address by the one of your EV3 brick, connect an infrared sensor with PORT 2, then start this program.

import ev3_dc as ev3

with ev3.Infrared(
        ev3.PORT_2,
        protocol=ev3.WIFI,
        host='00:16:53:42:2B:99'
) as my_infrared:
    dist = my_infrared.distance
    if dist:
        print(f'distance: {dist:3.2f} m')
    else:
        print('seen nothing')

Some remarks:

  • You already know, how to change the program for using protocols Bluetooth or USB.
  • Run the program multiple times with different surfaces and distances.
  • Test what happens, when no sensor is connected to PORT 2.
  • Test what happens, when another sensor type is connected to PORT 2.
  • Test with distances larger than 1.00 m.
  • Every time, you refrence attribute distance, you again start a communication between your program and the EV3 device.
  • Switch on verbosity by setting attribute verbosity to value 1 and you will see the communication data.

Asking for a beacon’s position

Class Infrared has an attribute beacon, which returns a named tuple of type Beacon. It tells, if the sensor currently sees an active beacon, which is sending on the requested channel.

Connect your EV3 device with your local network via WiFi. Replace the MAC-address by the one of your EV3 brick. Connect an infrared sensor with PORT 2, place a beacon somewhere in front of the sensor, select channel 3 and switch on the beacon, then start this program.

import ev3_dc as ev3

with ev3.Infrared(
        ev3.PORT_2,
        channel=3,
        protocol=ev3.WIFI,
        host='00:16:53:42:2B:99'
) as my_infrared:
    print(my_infrared)
    print(f'beacon on channel {my_infrared.channel}: {my_infrared.beacon}')

Some remarks:

  • If you prefer protocols Bluetooth or USB, you know how to change the program.
  • The named tuple Beacon has two items, heading and distance, where heading is between -25 and 25, and distance is in meters.
  • The meaning of the heading values:
    • -25: far left
    • 0: straight forwards
    • 25: far right

The output of my program was:

The beacon was positioned left ahead in a distance of 23 cm.

Using up to four beacons

If you need to identify the exact orientation and position of your EV3 device, you can use multiple beacons. Because they send on four different channels, you can simultaneously up to four of them. Attribute beacons allows to ask for their positions at once.

As before, connect your EV3 device with your local network via WiFi. Replace the MAC-address by the one of your EV3 brick. Connect an infrared sensor with PORT 2, place up to four beacons somewhere in front of the sensor, select different channels and switch on the beacons, then start this program.

import ev3_dc as ev3

with ev3.Infrared(
        ev3.PORT_2,
        protocol=ev3.WIFI,
        host='00:16:53:42:2B:99'
) as my_infrared:
    print(f'beacons: {my_infrared.beacons}')

The output of my program run:

beacons: (None, Beacon(heading=5, distance=0.32), None, None)

Some remarks:

  • This was a single beacon, sending on channel 2, which was positioned right ahead in a distance of 32 cm.
  • The returned data is a tuple of four items, one per channel.
  • If no beacon was found, the channel’s item is set to None.
  • If a beacon was found, the channel’s item is of type Beacon.

Using the beacon as a remote control

Class Infrared has an attribute remote, which returns a named tuple of type Remote. It tells, which of the beacon’s buttons currently were pushed.

Connect your EV3 device with your local network via WiFi. Replace the MAC-address by the one of your EV3 brick. Connect an infrared sensor with PORT 2, place a beacon somewhere in front of the sensor, select channel 3 and switch on the beacon, then start this program.

import ev3_dc as ev3
from time import sleep

with ev3.Infrared(
        ev3.PORT_2,
        channel=3,
        protocol=ev3.WIFI,
        host='00:16:53:42:2B:99'
) as my_infrared:
    while True:
        remote_state = my_infrared.remote
        if remote_state is not None:
            break
        sleep(0.1)

    print(f'state of the remote on channel {my_infrared.channel}: {remote_state}')

Some remarks:

  • Every 100 ms, the state of the remote is requested, which means request and reply communication between program and EV3 device ten times per second.
  • The state of the remote control is stored in variable remote_state. This allows to use it to end the loop as well as for the printing.
  • You will easily imagine, how to define different actions for different states of the remote data.

The output of my program’s execution:

state of the remote on channel 3: Remote(permanent=False, red_up=False, red_down=True, blue_up=True, blue_down=False)

This says, someone pushed two of the buttons simultaneously. The communication does not handle triple pushes and double pushes are restricted to the buttons red_up, red_down, blue_up and blue_down. Altogether, we can distinguish 11 different states plus none pushes.

Reading multiple remote control channels simultaneously

If you try to use multiple beacons simultaneously as remote controls, you can do that with attribute remotes, which returns a tuple of four items, one per channel. As you will have expected, each of them may be None or of type Remote.

As before, connect your EV3 device with your local network via WiFi. Replace the MAC-address by the one of your EV3 brick. Connect an infrared sensor with PORT 2, then start the program. After some time push any button of a beacon.

import ev3_dc as ev3
import time

with ev3.Infrared(
        ev3.PORT_2,
        protocol=ev3.WIFI,
        host='00:16:53:42:2B:99'
) as my_infrared:
    print(f'started at {time.strftime("%H:%M:%S", time.localtime())}')

    def any_remote():
        for remote in my_infrared.remotes:
            if remote:
                return remote

    while True:
        the_active_one = any_remote()
        if the_active_one:
            break
        time.sleep(0.1)

    print(the_active_one)
    print(f'stopped at {time.strftime("%H:%M:%S", time.localtime())}')

The output of my program’s execution:

started at 18:32:01
Remote(permanent=False, red_up=False, red_down=True, blue_up=True, blue_down=False)
stopped at 18:32:09

Some remarks:

  • Eight seconds after the program’s start, someone simultaneously pressed two buttons of a beacon. These buttons were red_down and blue_up.
  • This program does not care about channels. Function any_remote loops over all four channels and if it finds one unequal None, this one is returned.
  • May be, your program only supports one beacon as a remote control but you do not trust the user to select the correct channel. This may be the solution: you read all four channels and then select the correct one.
  • May be your program is thought for multiple users and every user has his own beacon. Then any of them can end the program.