Headlights

 

The Joy-Car has four LED boards with a total of 8 individually controllable LEDs. Each LED can be controlled independently, making it possible to program different patterns and lighting effects. The LEDs can be used as signals and feedback, e.g. to indicate movements or obstacles, just like a real car.

The LEDs are controlled via PWM (pulse width modulation). If you would like to find out more about PWM technology, you can find a detailed explanation here. You can also find detailed information about the technical operation of LEDs here. These resources will help you to better understand the control and functionality of the LEDs and to achieve optimum results in your projects.

In the following code example, you will learn the different methods with which you can control the headlights of your Joy-Car in a similar way to a real car. You will learn how to use the indicators correctly to indicate turns or lane changes. You will also learn how to activate the hazard warning lights to draw attention to your vehicle in emergency situations. The example also shows you how to switch on the high beam to improve visibility in poor light conditions. You can implement all of these functions easily and intuitively.

Headlights

This controls the headlights. A white light is activated at the front and a red light at the rear.

Indicator

Check the indicators  for one side (left/right) of the Joy-Car. The front and rear headlights on the selected side start to flash yellow.

Hazard lights

Use this to control the warning light. All headlights start to flash yellow.

Brake light

This controls a brighter, red light on the rear headlights of your Joy-Car.

Reversing light

Use this to check the reversing light. This illuminates a white light on the rear headlights.

Code example

In MakeCode, you can find all the functions available for controlling the headlights of the Joy-Car below the menu item LEDs. In the sample code provided, these functions are used to demonstrate the various lighting options of the Joy-Car. You can see how to activate the indicators, turn on the warning light or use the high beam to understand how to control the headlights in practice. These examples will show you how easy it is to use the lights of your Joy-Car in your own code.

let current_time = 0
JoyCar.initJoyCar(RevisionMainboard.OnepThree)
basic.forever(function () {
    JoyCar.light(ToggleSwitch.On)
    basic.pause(5000)
    JoyCar.brakelight(ToggleSwitch.On)
    basic.pause(5000)
    JoyCar.brakelight(ToggleSwitch.Off)
    basic.pause(100)
    JoyCar.reversinglight(ToggleSwitch.On)
    basic.pause(5000)
    JoyCar.reversinglight(ToggleSwitch.Off)
    basic.pause(100)
    current_time = control.millis()
    while (current_time + 5000 > control.millis()) {
        JoyCar.indicator(ToggleSwitch.On, SensorLRSelection.Left)
    }
    JoyCar.indicator(ToggleSwitch.Off, SensorLRSelection.Left)
    basic.pause(100)
    current_time = control.millis()
    while (current_time + 5000 > control.millis()) {
        JoyCar.indicator(ToggleSwitch.On, SensorLRSelection.Right)
    }
    basic.pause(100)
    JoyCar.indicator(ToggleSwitch.Off, SensorLRSelection.Right)
    current_time = control.millis()
    while (current_time + 5000 > control.millis()) {
        JoyCar.hazardlights(ToggleSwitch.On)
    }
    basic.pause(100)
    JoyCar.hazardlights(ToggleSwitch.Off)
})

Definition of the headlights

 

The headlights of the Joy-Car are arranged one behind the other and therefore follow a fixed sequence, numbered from 0 to 7, as each board has two LEDs. The next step is to specify in the code which of these LEDs are to be used as indicators (outer LEDs) and which are responsible for the low beam (inner LEDs).

 .

We then define the colors to be displayed on the headlights by specifying different RGB colors (red, green, blue). This allows us to assign specific color values for the various functions such as indicators and low beam in order to adjust the lights of the Joy-Car accordingly.

# Define values for the lights
# Values which LEDs are to be activated
headlights = (0, 3)
backlights = (5, 6)
indicator_left = (1, 4)
indicator_right = (2, 7)
indicator_warning = (1, 2, 4, 7)

# Values, which color should be displayed on the LEDs
led_white = (60, 60, 60)
led_red = (60, 0, 0)
led_off = (0, 0, 0)
led_red_br = (255, 0, 0)
led_orange = (100, 35, 0)

Low beam

The following method allows us to switch the dipped headlights of the Joy-Car on and off. The variable on decides whether the low beam is activated or deactivated when the method is called. By default, the on variable is set to True, so that the low beam is switched on if no other specification is made.

Within the method, the previously defined LEDs for the low beam are either set to the color white or red to simulate the low beam, or to black to switch the LEDs off, depending on the status. This clearly structures the switching on and off of the low beam in the code and enables flexible control of the Joy-Car's light function.

# method to activate/deactivate lights
def lights(on = True):
    if on:
        for x, y in zip(headlights, backlights):
            # define white for the headlights
            np[x] = led_white
            # define dark red for the backlights
            np[y] = led_red
    else:
        for x, y in zip(headlights, backlights):
            # define black for the headlights and backlights
            np[x] = led_off
            np[y] = led_off
    np.show()

Brake light

The following method works in a similar way to the method for the low beam, but is specifically intended for the outer rear lights of the Joy-Car to simulate a brake light. When the brake lights are activated, the outer rear lights are set to a bright red. The variable on is used again to define whether the brake lights should be switched on or off.

This method offers a simple way of flexibly controlling the brake light and adapting it to the driving conditions of the Joy-Car.

# method to activate/deactivate the breaking lights
def lightsBreak(on = True):
    if on:
        for x in backlights:
            # define bright red for the backlights
            np[x] = led_red_br
    else:
        for x in backlights:
            # define black for the backlights
            np[x] = led_off
    np.show()

Reversing light

The following method works on the same principle as the methods described above for the dipped beam and brake light, but is designed for the reversing light of the Joy-Car. Here, the rear left outer LED is set to a bright white to simulate the reversing light. Control is again via the variable on, which determines whether the reversing light is activated or deactivated.

This method enables precise control of the reversing light and increases safety when reversing.

# Activate/deactivate the light for reversing
def lightsBack(on = True):
    if on:
        # Set left rear light to white
        np[backlights[0]] = led_white
        np.show()
    else:
        # Set left rear light to black
        np[backlights[0]] = led_off
        np.show()

Indicators & hazard warning lights

The following method works in a similar way to the previous ones, but is slightly more complex as it simulates the flashing of the indicators and hazard lights. In order to control the flashing without interrupting the entire program sequence, a time measurement is carried out. This allows the flashing effect to be generated without the program having to stop.

The variable last_ind_act is used for this purpose. It saves the time of the last change of state of the blinker. Each time the blinker is to change its state (on/off), the method checks whether at least 400 milliseconds have passed since the last change. If this is the case, the status of the blinker is switched and last_ind_act is set to the current runtime. As with the other methods, the variable on controls whether the indicators are activated or deactivated.

# Method for activating/deactivating the indicators.
# Variable for the method to compare when the lights were last active.
last_ind_act = running_time()
def lightsIndicator(direction, on = True):
    # to be able to change the global variable
    global last_ind_act
    # Activate garbage collector
    gc.collect()

    # if you want to switch off the indicators
    if on is False:
        # Deactivate LEDs
        for x in direction:
            np[x] = led_off
        np.show()
        # Close the method
        return

    # Activation/deactivation of the indicators after 400 ms
    if running_time() - last_ind_act >= 400:
        # Activate LEDs when the LEDs are off
        if np[direction[0]] == led_off:
            for x in direction:
                np[x] = led_orange
        # Deactivate the LEDs when they are switched on
        else:
            for x in direction:
                np[x] = led_off
        np.show()
        # Set global variable to current runtime
        last_ind_act = running_time()

Code example

In MicroPython, the various functions of the headlights are stored in separate methods so that you can easily integrate them into your code if required. For example, if you want to control the indicators, the hazard light or the high beam, you can simply call the appropriate method. Each function is controlled independently, and by using a Boolean value on, you can switch the respective function on and off without affecting other headlight functions. This enables flexible and modular control of the headlights without conflicts between the different light modes.

# Import necessary libraries
from microbit import *
import neopixel
import gc

# Define your Joy-Car mainboard revision
joycar_rev = 1.3

# Initialization of the I2C interface for the Joy-Car mainboard
i2c.init(freq=400000, sda=pin20, scl=pin19)

# Define object for the lights
np = neopixel.NeoPixel(pin0, 8)

# Define values for the lights
# which LEDs are to be activated
headlights = (0, 3)
backlights = (5, 6)
indicator_left = (1, 4)
indicator_right = (2, 7)
indicator_warning = (1, 2, 4, 7)

# which color should be displayed on the LEDs
led_white = (60, 60, 60)
led_red = (60, 0, 0)
led_off = (0, 0, 0)
led_red_br = (255, 0, 0)
led_orange = (100, 35, 0)

# method to activate/deactivate lights
def lights(on = True):
    if on:
        for x, y in zip(headlights, backlights):
            # define white for the headlights
            np[x] = led_white
            # define dark red for the backlights
            np[y] = led_red
    else:
        for x, y in zip(headlights, backlights):
            # define black for the headlights and backlights
            np[x] = led_off
            np[y] = led_off
    np.show()

# method to activate/deactivate the breaking lights
def lightsBreak(on = True):
    if on:
        for x in backlights:
            # define bright red for the backlights
            np[x] = led_red_br
    else:
        for x in backlights:
            # define black for the backlights
            np[x] = led_off
    np.show()

# Activate/deactivate the light for reversing
def lightsBack(on = True):
    if on:
        # Set left rear light to white
        np[backlights[0]] = led_white
        np.show()
    else:
        # Set left rear light to black
        np[backlights[0]] = led_off
        np.show()

# Method for activating/deactivating the indicators.
# Variable for the method to compare when the lights were last active.
last_ind_act = running_time()
def lightsIndicator(direction, on = True):
    # to be able to change the global variable
    global last_ind_act
    # Activate garbage collector
    gc.collect()

    # if you want to switch off the indicators
    if on is False:
        # Deactivate LEDs
        for x in direction:
            np[x] = led_off
        np.show()
        # Close the method
        return

    # Activation/deactivation of the indicators after 400 ms
    if running_time() - last_ind_act >= 400:
        # Activate LEDs when the LEDs are off
        if np[direction[0]] == led_off:
            for x in direction:
                np[x] = led_orange
        # Deactivate the LEDs when they are switched on
        else:
            for x in direction:
                np[x] = led_off
        np.show()
        # Set global variable to current runtime
        last_ind_act = running_time()

while True:
    # Switch on low beam
    lights()
    sleep(5000)

    # Switch on brake light
    lightsBreak()
    sleep(5000)

    # Switch off brake light and switch on low beam again
    lightsBreak(on = False)
    lights()
    sleep(5000)

    # Switch on reversing light
    lightsBack()
    sleep(5000)

    # Switch off reversing light and switch on low beam again
    lightsBack(on = False)
    lights()

    # Turn the blinker to the right on for 5 seconds
    current_time = running_time()
    while(current_time + 5000 > running_time()):
        lightsIndicator(indicator_right)

    # Switch off turn signal to the right
    lightsIndicator(indicator_right, on = False)

    # Switch the indicators to the left on for 5 seconds
    current_time = running_time()
    while(current_time + 5000 > running_time()):
        lightsIndicator(indicator_left)

    # Switch off turn signal to the left
    lightsIndicator(indicator_left, on = False)

    # Switch on the hazard lights for 5 seconds
    current_time = running_time()
    while(current_time + 5000 > running_time()):
        lightsIndicator(indicator_warning)

    # Switch off all lights
    lightsIndicator(indicator_warning, on = False)
    lights(on = False)
    sleep(5000)