icon

Title: Uncharted Expedition

0 276 Easy

Captain Jackson and Lieutenant Kim found themselves stranded on an uncharted planet after their shuttle malfunctioned during atmospheric entry. With the crash, their vital tricorder was rendered inoperable, leaving them devoid of essential data for survival.

 

Facing this predicament, they decided to utilize their ingenuity. Remembering a recent briefing on innovative exploration tools, they recalled the UNIHIKER device and the I2C BME280 environmental sensor. Without hesitation, they salvaged what they could and set out to construct a makeshift tricorder.

HARDWARE LIST
1 UNIHIKER
1 I2C BME280 Environmental Sensor

With determination, they connected the Unihiker device with the BME280 sensor, cobbling together a functional unit. To interface with the device and process the data, Lieutenant Kim utilized her programming skills, developing a simple Python Tkinter application.

 

Project Structure

 

Background image

 

 

Content of main.py

CODE
from pinpong.board import Board, Pin
from pinpong.extension.unihiker import accelerometer, button_a, button_b, buzzer
from pinpong.libs.dfrobot_bme280 import BME280
from tkinter import Tk, PhotoImage, Canvas, Label
from tkinter.font import Font
from os.path import dirname, join
from time import strftime


SCREEN_WIDTH: int = 240
SCREEN_HEIGHT: int = 320
BACKGROUND_PICTURE: str = 'img/lcars.png'
FONT_NAME: str = 'Helvetica'


class LCARS(Tk):
    """
    Tkinter class to create main window in LCARS design
    """

    __COLOR_SCHEME: dict = {'background': 'black',
                           'laying_down': 'white',
                           'tilted': 'orange',
                           'top': 'lightskyblue',
                           'bottom': 'aqua'}
    __ACCELEROMETER_MIN_X: float = 0.25

    def __init__(self, width: int, height: int, picture: str, font: str):
        """
        Tkinter main window constructor
        :param width: display width in px
        :param height: display height in px
        :param picture: background image path from current file
        :param font: fontname
        """
        super().__init__()

        self.geometry(f'{int(width)}x{int(height)}+0+0')
        self.resizable(False, False)
        self.configure(bg=self.__COLOR_SCHEME['background'])

        current_dir = dirname(__file__)
        file_path = join(current_dir, str(picture))

        self.__bg_image = PhotoImage(file=file_path)

        self.__bg_canvas = Canvas(self)
        self.__bg_canvas.pack(fill='both', expand=True)
        self.__bg_canvas.create_image(0, 0, anchor='nw', image=self.__bg_image)

        self.__rectangle_top = self.__bg_canvas.create_rectangle(90, 25, 215, 30, fill=self.__COLOR_SCHEME['top'])

        self.__time_label = Label(self.__bg_canvas,
                                  font=(str(font), "22", "bold"),
                                  fg=self.__COLOR_SCHEME['top'],
                                  bg=self.__COLOR_SCHEME['background'])
        self.__time_label.place(x=90, y=35)

        self.__date_label = Label(self.__bg_canvas,
                                  font=(str(font), "12"),
                                  fg=self.__COLOR_SCHEME['top'],
                                  bg=self.__COLOR_SCHEME['background'])
        self.__date_label.place(x=125, y=75)

        self.__sensor_font = Font(family=str(font), size=16)

        self.__rectangle_a = self.__bg_canvas.create_rectangle(100, 140, 225, 145, fill=self.__COLOR_SCHEME['tilted'])

        self.__temperature_label = Label(self.__bg_canvas,
                                         font=self.__sensor_font,
                                         fg=self.__COLOR_SCHEME['bottom'],
                                         bg=self.__COLOR_SCHEME['background'])
        self.__temperature_label.place(x=100, y=150)

        self.__humidity_label = Label(self.__bg_canvas,
                                      font=self.__sensor_font,
                                      fg=self.__COLOR_SCHEME['bottom'],
                                      bg=self.__COLOR_SCHEME['background'])
        self.__humidity_label.place(x=100, y=175)

        self.__rectangle_b = self.__bg_canvas.create_rectangle(100, 215, 225, 220, fill=self.__COLOR_SCHEME['tilted'])
        self.__rectangle_c = self.__bg_canvas.create_rectangle(100, 225, 225, 240, fill=self.__COLOR_SCHEME['tilted'])

        self.__pressure_label = Label(self.__bg_canvas,
                                      font=self.__sensor_font,
                                      fg=self.__COLOR_SCHEME['bottom'],
                                      bg=self.__COLOR_SCHEME['background'])
        self.__pressure_label.place(x=100, y=250)

        self.__altitude_label = Label(self.__bg_canvas,
                                      font=self.__sensor_font,
                                      fg=self.__COLOR_SCHEME['bottom'],
                                      bg=self.__COLOR_SCHEME['background'])
        self.__altitude_label.place(x=100, y=275)

    def _update_colors(self, milliseconds: int = 500) -> None:
        """
        Updates the color continuously by milliseconds and accelerometer value x
        :param milliseconds: number in milliseconds
        :return: None
        """
        accelerometer_x = accelerometer.get_x()

        if accelerometer_x > self.__ACCELEROMETER_MIN_X:
            self.__bg_canvas.itemconfig(self.__rectangle_top, fill=self.__COLOR_SCHEME['top'])
            self.__bg_canvas.itemconfig(self.__rectangle_a, fill=self.__COLOR_SCHEME['tilted'])
            self.__bg_canvas.itemconfig(self.__rectangle_b, fill=self.__COLOR_SCHEME['tilted'])
            self.__bg_canvas.itemconfig(self.__rectangle_c, fill=self.__COLOR_SCHEME['tilted'])

            self.__time_label.configure(fg=self.__COLOR_SCHEME['top'])
            self.__date_label.configure(fg=self.__COLOR_SCHEME['top'])
            self.__temperature_label.configure(fg=self.__COLOR_SCHEME['bottom'])
            self.__humidity_label.configure(fg=self.__COLOR_SCHEME['bottom'])
            self.__pressure_label.configure(fg=self.__COLOR_SCHEME['bottom'])
            self.__altitude_label.configure(fg=self.__COLOR_SCHEME['bottom'])
        else:
            self.__bg_canvas.itemconfig(self.__rectangle_top, fill=self.__COLOR_SCHEME['laying_down'])
            self.__bg_canvas.itemconfig(self.__rectangle_a, fill=self.__COLOR_SCHEME['laying_down'])
            self.__bg_canvas.itemconfig(self.__rectangle_b, fill=self.__COLOR_SCHEME['laying_down'])
            self.__bg_canvas.itemconfig(self.__rectangle_c, fill=self.__COLOR_SCHEME['laying_down'])

            self.__time_label.configure(fg=self.__COLOR_SCHEME['laying_down'])
            self.__date_label.configure(fg=self.__COLOR_SCHEME['laying_down'])
            self.__temperature_label.configure(fg=self.__COLOR_SCHEME['laying_down'])
            self.__humidity_label.configure(fg=self.__COLOR_SCHEME['laying_down'])
            self.__pressure_label.configure(fg=self.__COLOR_SCHEME['laying_down'])
            self.__altitude_label.configure(fg=self.__COLOR_SCHEME['laying_down'])

        self.after(milliseconds, self._update_colors)

    def _update_app_time(self, milliseconds: int = 1000) -> None:
        """
        Updates the app time data in Labels continuously by milliseconds
        :param milliseconds: number in milliseconds
        :return: None
        """
        self.__time_label.configure(text=f'{strftime("%H:%M:%S")}')

        self.after(milliseconds, self._update_app_time)

    def _update_app_date(self, milliseconds: int = 900000) -> None:
        """
        Updates the app date data in Labels continuously by milliseconds
        :param milliseconds: number in milliseconds
        :return: None
        """
        self.__date_label.configure(text=f'{strftime("%Y-%m-%d")}')

        self.after(milliseconds, self._update_app_date)

    def _update_sensor_data(self, milliseconds: int = 60000) -> None:
        """
        Updates the app sensor data in Labels continuously by milliseconds
        :param milliseconds: number in milliseconds
        :return: None
        """
        self.__temperature_label.configure(text=f'{sensor.temp_c()} °C')
        self.__humidity_label.configure(text=f'{sensor.humidity()} %RH')
        self.__pressure_label.configure(text=f'{sensor.press_pa()} Pa')
        self.__altitude_label.configure(text=f'{sensor.cal_altitudu()} m')

        self.after(milliseconds, self._update_sensor_data)

    def get_sensor_data(self) -> None:
        self._update_colors()
        self._update_app_time()
        self._update_app_date()
        self._update_sensor_data()


def btn_a_raising_handler(pin) -> None:
    """
    Interrupt event callback function for button A rising edge
    :param pin: pin instance of the button
    :return: None
    """
    _ = pin
    buzzer.stop()
    buzzer.play(buzzer.JUMP_UP, buzzer.OnceInBackground)


def btn_b_raising_handler(pin) -> None:
    """
    Interrupt event callback function for button B rising edge
    :param pin: pin instance of the button
    :return: None
    """
    _ = pin
    buzzer.stop()
    buzzer.play(buzzer.JUMP_DOWN, buzzer.OnceInBackground)


Board().begin()
button_a.irq(trigger=Pin.IRQ_RISING, handler=btn_a_raising_handler)
button_b.irq(trigger=Pin.IRQ_RISING, handler=btn_b_raising_handler)
sensor = BME280()

if __name__ == '__main__':
    app = LCARS(width=SCREEN_WIDTH, height=SCREEN_HEIGHT, picture=BACKGROUND_PICTURE, font=FONT_NAME)
    app.get_sensor_data()
    app.mainloop()

File upload to UNIHIKER

 

$ scp -r LCAR/ root@10.1.2.3:/root/

 

Note: If you don't know how to upload files to Unihiker, have a look in the Wiki!

As they delved deeper into their exploration, Captain Jackson and Lieutenant Kim encountered a puzzling discrepancy in their data readings. After some investigation, they realized that the Unihiker device was not properly synchronized with the local time zone, leading to inaccuracies in their observations.

 

Recognizing the importance of precise temporal data for their expedition, they quickly set about configuring the Unihiker device to match the planet's time zone. With this adjustment made, their readings became more reliable, allowing them to navigate the terrain with greater confidence and accuracy.

Change timezone in UNIHIKER via SSH

 

# ssh into UNIHIKER

$ ssh root@10.1.2.3

 

# show current system time information

$ timedatectl

 

# search for time zone (optional)

$ timedatectl list-timezones | egrep "Europe/*"

 

# set new system time zone

$ timedatectl set-timezone "Europe/Zurich"

With their improvised tricorder in hand, they embarked on their exploration of the unknown terrain. The sensor provided them with crucial environmental data, while the UNIHIKER device facilitated navigation through the rugged landscape.

 

 

Through their resourcefulness and teamwork, Captain Jackson and Lieutenant Kim navigated the challenges of the alien planet, uncovering its mysteries one step at a time. Their journey exemplified the spirit of Starfleet exploration, where innovation and determination triumph over adversity.

License
All Rights
Reserved
licensBg
0