powered by TinkerSpace.in
Join free
TinkerPy Tutorial ๐Ÿ“˜ Part 2 ยท Coder ยท Chapter 22 of 24

Motion, Time & Weather Sensors

Your board can feel when it is tilted, shaken or dropped, know the real time and date even after it was switched off, and measure the air pressure to tell how high you have climbed. Meet three clever I2C sensors!

๐Ÿ“–Key words

MPU6050

A tiny motion sensor: an accelerometer (feels gravity and pushes) plus a gyroscope (feels turning). Tick MPU6050 in Circuit Connections: import mpu6050.

RTC

Real-Time Clock module (DS3231 or DS1307) with its own small battery, so it keeps the time and date even when the board is off. import rtc.

BMP280

An air-pressure sensor. It gives the pressure in hPa, the temperature and your altitude (height above the sea). import bmp280.

hPa

Hectopascal, the unit of air pressure. About 1013 hPa at sea level and less as you go higher.

I2C address

Each I2C part on o7/o8 has a number. Two parts with the same address canโ€™t be on one board: the RTC and the MPU6050 are both 0x68.

๐ŸŽฌSee it work

Tilt the board

Drag the slider to tilt the front edge of the MPU6050 and see what tilt_x() and tilt_direction() give.

Three sensors, three superpowers

Switch between the sensors and see what each one measures.

๐Ÿง How it works

MPU6050: tilt, shake and fall

  • tilt_x(): how much the front edge (the X arrow) is tilted, โˆ’90 to 90 degrees (up = +). tilt_y(): leaning sideways (right side down = +).
  • tilt_direction() gives "F" (front down), "B", "L", "R" or "N" (flat, less than 15ยฐ). Compare in quotes: if d == "F":
  • motion_level(): 0 (still) to 100 (lots of movement). shake_detected() and fall_detected() give 1 once after a shake or a free fall, then 0.
  • Keep the board still for the first second after it switches on.

MPU6050: turns, steps and raw numbers

  • reset_turn() then turn_angle(): degrees turned flat since the reset, right = +. It drifts slowly, so reset it just before each turn โ€” a robot can spin until turn_angle() >= 90.
  • step_count() counts walking steps since reset_steps().
  • For older students: accel_x(), accel_y(), accel_z() in 1/100 g (accel_z is about 100 lying flat, about โˆ’100 upside down) and gyro_x(), gyro_y(), gyro_z() in degrees per second.
  • mpu_temperature(): the chipโ€™s temperature in ยฐC โ€” a little warmer than the room.

RTC: a clock that keeps time

  • rtc_hour() 0โ€“23, rtc_minute(), rtc_second(), rtc_day() 1โ€“31, rtc_month() 1โ€“12, rtc_year() like 2026, rtc_weekday() 1 Monday โ€ฆ 7 Sunday.
  • Set it in setup: with rtc_set_time(8, 59, 50) and rtc_set_date(19, 10, 2026). The board sets the clock once, when this new code arrives โ€” not again at every power-on.
  • Unlike chapter 8โ€™s clock_start(), the RTC remembers the time with its battery. Use a 3.3 V DS3231 board; the โ€œTiny RTCโ€ DS1307 boards need 5 V.

BMP280: pressure and altitude

  • pressure(): air pressure in hPa. bmp_temperature(): ยฐC. altitude(): metres above the sea, worked out from the pressure.
  • Weather changes the pressure a little, so altitude() moves a little too. To measure a climb, save start = altitude() and subtract.
  • All three sensors sit on o7 (SDA) and o8 (SCL) with the OLED. The RTC and BMP280 need board firmware 2.27 or newer; the MPU6050 works on older firmware too. All work on Mega and Mini.

๐Ÿ’ปCode

# Add the libraries you need
import oled_display
import buzzer
import mpu6050

# Give your pins easy-to-remember names
o1 = set_name("siren")
o2 = set_name("front_led")
o3 = set_name("back_led")

# ===== Toy fall alarm =====

# This code block executes only once
setup:
    oled_begin()  # starts the OLED
    o7 = set_function(SDA)  # cannot be changed
    o8 = set_function(SCL)  # cannot be changed
    siren = set_output(buzzer)
    front_led = set_output(led)
    back_led = set_output(led)

# This code block executes forever
loop:
    oled_write(1, left, small, regular, "Tilt X " + tilt_x())  # write "Tilt X " + tilt_x() on OLED line 1 (small, from the left)
    oled_write(2, left, small, regular, "Tilt Y " + tilt_y())  # write "Tilt Y " + tilt_y() on OLED line 2 (small, from the left)
    d = tilt_direction()  # F, B, L, R or N (flat)
    if d == "F":  # when d == "F"
        front_led = ON  # turn front_led ON
    else:  # otherwise
        front_led = OFF  # turn front_led OFF
    if d == "B":  # when d == "B"
        back_led = ON  # turn back_led ON
    else:  # otherwise
        back_led = OFF  # turn back_led OFF
    if fall_detected() == 1:  # when fall_detected() == 1
        oled_write(3, center, medium, bold, "FALL!")  # write "FALL!" on OLED line 3 (medium bold, centred)
        buzzer_play(siren, "alarm")  # play the "alarm" tone on the buzzer (siren) โ€” the next line waits until it ends
        oled_clear_line(3)  # clear line 3 of the OLED
    wait(200)  # pause here for 200 milliseconds before continuing

A toy fall alarm: the OLED shows both tilts, two LEDs show front-down and back-down, and a fall makes the buzzer sound the alarm tone and shows FALL!

# Add the libraries you need
import oled_display
import mpu6050

# Give your pins easy-to-remember names
i1 = set_name("reset_btn")

# ===== Step counter and shake dice =====

# This code block executes only once
setup:
    oled_begin()  # starts the OLED
    o7 = set_function(SDA)  # cannot be changed
    o8 = set_function(SCL)  # cannot be changed
    reset_btn = set_input(push_button, active_low)
    reset_steps()

# This code block executes forever
loop:
    oled_write(1, left, small, regular, "Steps " + step_count())  # write "Steps " + step_count() on OLED line 1 (small, from the left)
    oled_write(2, left, small, regular, "Moving " + motion_level())  # write "Moving " + motion_level() on OLED line 2 (small, from the left)
    if reset_btn == ON:  # when reset_btn is ON
        reset_steps()
    if shake_detected() == 1:  # when shake_detected() == 1
        dice = random(1, 6)  # dice gets a surprise number from 1 to 6
        oled_write(3, center, large, bold, dice)  # write the value of dice on OLED line 3 (large bold, centred)
    wait(200)  # pause here for 200 milliseconds before continuing

Carry the board while you walk: it counts your steps and shows how much it is moving. Shake it to roll a dice from 1 to 6 (random needs firmware 2.15 or newer).

# Add the libraries you need
import oled_display
import buzzer
import rtc

# Give your pins easy-to-remember names
o1 = set_name("bell")

# ===== RTC school bell =====

# This code block executes only once
setup:
    oled_begin()  # starts the OLED
    o7 = set_function(SDA)  # cannot be changed
    o8 = set_function(SCL)  # cannot be changed
    bell = set_output(buzzer, passive)
    rtc_set_time(8, 59, 50)  # set it to the real time before you upload
    rtc_set_date(19, 10, 2026)  # day, month, year
    rang = 0  # set rang to 0

# This code block executes forever
loop:
    h = rtc_hour()  # set h to rtc_hour()
    m = rtc_minute()  # set m to rtc_minute()
    oled_write(1, center, medium, bold, h + ":" + m + ":" + rtc_second())  # write the value of h + ":" + m + ":" + rtc_second() on OLED line 1 (medium bold, centred)
    oled_write(3, center, small, regular, rtc_day() + "/" + rtc_month() + "/" + rtc_year())  # write the value of rtc_day() + "/" + rtc_month() + "/" + rtc_year() on OLED line 3 (small, centred)
    if rtc_weekday() <= 6 and h == 9 and m == 0 and rang == 0:  # when rtc_weekday() <= 6 and h == 9 and m == 0 and rang == 0
        buzzer_play(bell, "school_bell")  # play the "school_bell" tone on the buzzer (bell) โ€” the next line waits until it ends
        rang = 1  # set rang to 1
    if m != 0:  # when m != 0
        rang = 0  # set rang to 0
    wait(500)  # pause here for 500 milliseconds before continuing

A school bell with an RTC module: it shows the time and date and plays school_bell at 9:00 from Monday (1) to Saturday (6). Change rtc_set_time and rtc_set_date to the real time and date before you upload.

# Add the libraries you need
import oled_display
import bmp280

# Give your pins easy-to-remember names
i1 = set_name("zero_btn")

# ===== Stair-climb altimeter =====

# This code block executes only once
setup:
    oled_begin()  # starts the OLED
    o7 = set_function(SDA)  # cannot be changed
    o8 = set_function(SCL)  # cannot be changed
    zero_btn = set_input(push_button, active_low)
    start = altitude()  # the height where we begin

# This code block executes forever
loop:
    oled_write(1, left, small, regular, "Pressure " + pressure() + " hPa")  # write "Pressure " + pressure() + " hPa" on OLED line 1 (small, from the left)
    oled_write(2, left, small, regular, "Temp " + bmp_temperature() + " C")  # write "Temp " + bmp_temperature() + " C" on OLED line 2 (small, from the left)
    climb = altitude() - start  # set climb to altitude() - start
    oled_write(3, center, medium, bold, climb + " m")  # write the value of climb + " m" on OLED line 3 (medium bold, centred)
    if zero_btn == ON:  # when zero_btn is ON
        start = altitude()  # count from here again
    wait(500)  # pause here for 500 milliseconds before continuing

A stair-climb altimeter with a BMP280: it shows the pressure and temperature and how many metres higher you are than where you started. Press the button to start counting from here.

Open TinkerPy Code

๐ŸŽ‰Fun examples

๐ŸŽฒShake dice

Shake the board and get a number from 1 to 6 โ€” perfect for board games when the real dice rolls under the sofa.

๐Ÿ”๏ธHill station test

Take the BMP280 up a ghat road or a tall building: the pressure drops and altitude() goes up as you climb.

๐ŸšถStep challenge

Who walks the most steps in a school day? Wear the step counter in your pocket and compare at home time.

๐ŸŒWhere itโ€™s used

๐Ÿ› ๏ธProject ideas

Fall alarm for a toy

Fix the MPU6050 and a buzzer inside a soft toy. When the toy falls, sound the alarm and count the falls with a counter shown on the OLED.

๐Ÿงฐ You need: TinkerPy board, MPU6050, buzzer, OLED, soft toy, power bank
School bell with a real-time clock

Set the RTC once and ring school_bell at the start of every period from Monday to Saturday. Use a flag so each bell rings only once.

๐Ÿงฐ You need: TinkerPy board, DS3231 RTC module, passive buzzer, OLED display

โญPoints to remember

  1. MPU6050 = accelerometer + gyroscope: import mpu6050.
  2. tilt_x() and tilt_y() give โˆ’90 to 90 degrees.
  3. tilt_direction() gives "F", "B", "L", "R" or "N" (flat).
  4. shake_detected() and fall_detected() give 1 once, then 0.
  5. motion_level() is 0 (still) to 100.
  6. reset_turn() before a turn; turn_angle() counts degrees, right = +.
  7. step_count() counts steps since reset_steps().
  8. accel_ in 1/100 g, gyro_ in degrees per second.
  9. The RTC keeps time with its own battery: import rtc.
  10. rtc_set_time() and rtc_set_date() in setup: set the clock once per new code.
  11. rtc_weekday(): 1 Monday โ€ฆ 7 Sunday.
  12. BMP280: pressure() in hPa, bmp_temperature() in ยฐC, altitude() in metres.
  13. RTC and MPU6050 both use 0x68 โ€” never both on one board.
  14. RTC and BMP280 need board firmware 2.27 or newer.
๐Ÿคฏ
Did you know?

Your phone has the same kind of tiny accelerometer and gyroscope chip as the MPU6050 โ€” it is how the screen knows to turn when you rotate the phone.

โ“Mini quiz

๐Ÿ”‘
Log in to try the mini quiz

5 quick questions to check yourself โ€” free with your TinkerPy account.

Log in