SEm/escapeLab/safe

From FSI
Jump to: navigation, search

Contents

Opening the safe

The safe is opened by turning an encoder up to the first value, then back to the second, and so on, until the 4 values have been reached. Once the final position has been reached, the rotating lever allows to open the safe. Pressing on the encoder button allows to verify the sequence currently stored by the safe's controller.

This can be tested with the sequence [12, 4, 15, 8] which doesn't open the safe but displays a smiley.

Verifying the codes

The numbers of the test sequence can be verified by their Hamming code. To do so, create a text file containing the decimal value of the number to test (2 ASCII characters) followed by 0Ah. Test it on Linux:

cd /tmp
echo 10 > test.txt
md5sum test.txt

This should return:

31d30eea8d0968d6458e0ad0027c9f80  test.txt

The tasks have the Hamming codes:

7
5
1
2

Testing the opening of the safe

The following code is programmed in the safe's microcontroller, except for the opening_sequence. It allows to find out how the unlocking system works.

# http://microbit-micropython.readthedocs.io/
from microbit import *
 
# -----------------------------------------------------------------------------
# Constants
#
opening_sequence = [0, 0, 0, 0]
test_sequence = [12, 4, 15, 8]
positon_min = 0
positon_max = 99
 
safe_open_button = button_a
encoder_button = button_b
encoder_pin_high = pin8
encoder_pin_low = pin12
open_safe_pin = pin16
 
rotating_right = True
rotating_left = not rotating_right
count_to_display_units = 200
sequence_item_display_interval = 1000
test_sequence_found_image = Image.HAPPY
safe_open_sequence_found_image = Image.FABULOUS
open_safe_duration = 2000
 
# -----------------------------------------------------------------------------
# Functions
#
def get_encoder_value():
    encoder_value = \
        2*encoder_pin_high.read_digital() + \
        encoder_pin_low.read_digital()
    return(encoder_value)
 
def update_position(position, encoder_previous_value, encoder_value):
    encoder_up = [1, 3, 0, 2]
    if encoder_value == encoder_up[encoder_previous_value]:
        position = position + 1
    else:
        position = position - 1
    if position < positon_min:
        position = positon_max
    if position > positon_max:
        position = positon_min
    return(position)
 
def display_binary(position):
    no_intensity = '0'
    max_intensity = '9'
    bits_per_line = 4
    #                                                          prepare bits 3:0
    hex_line_0 = ""
    for index in range(bits_per_line):
        if position % 2 > 0:
            hex_line_0 = max_intensity + hex_line_0
        else:
            hex_line_0 = no_intensity + hex_line_0
        position = int(position/2)
    hex_line_0 = '0' + hex_line_0
    #                                                          prepare bits 7:4
    hex_line_1 = ""
    for index in range(bits_per_line):
        if position % 2 > 0:
            hex_line_1 = max_intensity + hex_line_1
        else:
            hex_line_1 = no_intensity + hex_line_1
        position = int(position/2)
    hex_line_1 = '0' + hex_line_1
    #                                                             display image
    display.show(Image(
        "00000:" + hex_line_1 + ":00000:" + hex_line_0 + ":00000"
    ))
 
def display_tens(position):
    if position > 9:
        display.show(str(int(position/10)), wait=False)
    else:
        display.show(str(position % 10), wait=False)
 
def display_units(position):
    display.show(str(position % 10), wait=False)
 
def display_sequence(sequence):
    for index in range(len(sequence)):
        if sequence[index] > 9:
            display.scroll(str(int(sequence[index]/10)))
        display_units(sequence[index])
        sleep(sequence_item_display_interval)
 
def add_to_history(value, history):
    new_history = history[1:] + [value]
    return(new_history)
 
def open_safe():
    open_safe_pin.write_digital(1)
    sleep(open_safe_duration)
    open_safe_pin.write_digital(0)
 
# -----------------------------------------------------------------------------
# Main loop
#
encoder_value = get_encoder_value()
previous_encoder_value = encoder_value
encoder_position = 0
previous_encoder_position = encoder_position
display_units(encoder_position)
activity_counter = 0
history = [0, 0, 0, 0]
rotating_direction = rotating_right
previous_rotating_direction = rotating_direction
while True:
    #                                                              read encoder
    encoder_value = get_encoder_value()
    # update position
    if previous_encoder_value != encoder_value:
        encoder_position = update_position(
            encoder_position, previous_encoder_value, encoder_value
        )
        if encoder_position > previous_encoder_position:
            rotating_direction = rotating_right
        else:
            rotating_direction = rotating_left
        if rotating_direction != previous_rotating_direction:
            history = add_to_history(previous_encoder_position, history)
        display_binary(encoder_position)
        previous_encoder_value = encoder_value
        previous_encoder_position = encoder_position
        previous_rotating_direction = rotating_direction
        activity_counter = 0
    #                                                           display history
    if encoder_button.is_pressed():
        display_sequence(history)
    #                                               check history and open safe
    if safe_open_button.is_pressed():
        if add_to_history(encoder_position, history) == opening_sequence:
            display.show(safe_open_sequence_found_image)
            open_safe()
        elif add_to_history(encoder_position, history) == test_sequence:
            display.show(test_sequence_found_image)
        else:
            display_sequence(test_sequence)
Personal tools
Namespaces
Variants
Actions
Navigation
Modules / Projects
Browse
Toolbox