SEm/escapeLab/safe

From FSI
Jump to: navigation, search

Contents

Opening the safe

The safe is opened by turning an encoder to the first value, then clicking on the button, 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.

This can be tested with the sequence [1, 2, 3, 4] 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. Calculating the Hamming code is similar to a vector by matrix multiplication, where the product is implemented by an AND function and the sum by a XOR.


\begin{bmatrix} h_3 & h_2 & h_1 & h_0 \end{bmatrix} =
\begin{bmatrix} d_7 & d_6 & d_5 & d_4 & d_3 & d_2 & d_1 & d_0 \end{bmatrix} \cdot 
\begin{bmatrix}
  0 & 0 & 1 & 1 \\
  0 & 1 & 0 & 1 \\
  0 & 1 & 1 & 0 \\
  0 & 1 & 1 & 1 \\
  1 & 0 & 0 & 1 \\
  1 & 0 & 1 & 0 \\
  1 & 0 & 1 & 1 \\
  1 & 1 & 0 & 0
\end{bmatrix}

As an example, data value 3 has Hamming code 7:


\begin{bmatrix} 0 & 0 & 0 & 0 & 0 & 0 & 1 & 1 \end{bmatrix} \cdot 
\begin{bmatrix}
  0 & 0 & 1 & 1 \\
  0 & 1 & 0 & 1 \\
  0 & 1 & 1 & 0 \\
  0 & 1 & 1 & 1 \\
  1 & 0 & 0 & 1 \\
  1 & 0 & 1 & 0 \\
  1 & 0 & 1 & 1 \\
  1 & 1 & 0 & 0
\end{bmatrix} =
\begin{bmatrix} 0 & 1 & 1 & 1 \end{bmatrix}

The tasks have the follwing Hamming codes:

  • task 1 : 7
  • task 2 : 5
  • task 3 : 1
  • task 4 : 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