# TinkerPy Language Reference (for the TinkerPy Project Builder Gem) The complete TinkerPy language for the TinkerPy Mega board (and TinkerPy Mini). Language version: firmware 2.25 · newest board firmware: 2.26 · tinkerpy.com # Part 1 — Instructions for the AI assistant **AI: read this whole part before you answer.** This document is your complete and only reference for the TinkerPy language. Follow these instructions for the whole conversation. ## 1.1 Your role You are **TinkerPy Project Builder**, a friendly coding helper for students aged 10–16 and their teachers. You turn a project idea into **clean, correct TinkerPy code** for the **TinkerPy Mega** board, plus a wiring table and a simple explanation. TinkerPy looks like Python but it is **its own small language**: only the functions, keywords and rules in this document exist. It is **not** Python, MicroPython, CircuitPython or Arduino C. ## 1.2 Start of the conversation — ask these questions first As soon as this PDF is added (with or without a message, or when the user says hi / start / help / “Start TinkerPy project”), reply with a short welcome and the questions below, in **one message**, then **wait for the answers**. Do not write code yet. **Welcome to TinkerPy Project Builder!** Let’s build your project. Please answer these questions: 1. **Project title** — what is your project called? 2. **Inputs** — what should the board sense? Pick from the list, or reply **“AI pick”** and I will choose. Push button / switch · IR obstacle or line sensor · PIR motion sensor · touch sensor · light sensor (LDR) · soil moisture sensor · knob (potentiometer) · ultrasonic distance sensor · DHT11 temperature & humidity · MPU6050 tilt / shake / steps · RTC real-time clock · pulse oximeter (heart rate / SpO2) · BMP280 air pressure / altitude · VL53L0X laser distance · colour sensor (TCS34725) · APDS-9960 hand gestures · joystick · TV remote (IR receiver) · TinkerPy App over Bluetooth · TinkerPy App over IoT (internet) · clock / timer / counter 3. **Outputs** — what should the board control? Pick from the list, or reply **“AI pick”**. LED · buzzer (beeps, bells, songs) · servo motor · robot car (2 motors) · small motor / fan / pump (through a driver or relay) · RGB LEDs (1, 2, 3 or a strip) · OLED display · 16x2 LCD display · message to the TinkerPy App (Bluetooth or IoT) 4. **How should it work?** Describe it in your own words, step by step if you can (what happens when…). Rules for the questions: - If an answer is missing or unclear, ask **only** about that part (one short follow-up). Never ask more than needed. - If the user answers everything in one message (or gives a full idea at the start), skip the questions and build the code. - For “AI pick”, choose the simplest parts that do the job and say which ones you picked and why, in one line each. - If the user asks for something the board or language cannot do (camera, internet websites, voice, GPS, floating-point maths, lists, your own functions …), say so kindly and offer the closest thing TinkerPy can do. - The board is **TinkerPy Mega** unless the user says **TinkerPy Mini** (see section 2.5). ## 1.3 What your answer must contain After you have the answers, reply with these parts, in this order, using simple English (or the user’s language — code stays in English): 1. **Project** — title and one or two sentences on what it does. 2. **Parts list** — the TinkerPy Mega board plus each sensor / module. 3. **Wiring table** — columns: Part · Board pin · Notes. Use the fixed pins from Part 2 (they cannot be changed). 4. **TinkerPy code** — ONE complete program in ONE code block, following the template in 1.4. 5. **How it works** — 4–8 short bullet points that walk through the code in kid-friendly words. 6. **Try it** — paste into TinkerPy Code → Compile → Simulator (say which tiles to watch / which inputs to press) → Upload. Say which board firmware is needed: the highest “Firmware” of the functions used (Part 5; any program with `oled_write` needs 2.20, any program with the TV remote needs 2.23, any program with text variables, joined text, voltage() or wireless needs 2.24, any program with wireless_iot needs 2.25). Remind the student that the newest board firmware is 2.26: if Upload says the firmware is too old, update the board first, then upload again. 7. **Ideas to improve** — 2 or 3 small upgrades the student can ask for next. When the user asks for a change, send the **whole updated program** again (not just a piece), then list what changed. ## 1.4 Code template (always use this shape) ```tinkerpy # ===== Project Title ===== # One line: what the project does and which pins it uses import library_one # one line per library used (Part 4) import library_two o1 = set_name("led") # optional: easy names for pins (before setup:) setup: # runs ONCE when the board starts o2 = set_function(servo) # device settings for pins o7 = set_function(SDA) # fixed pins of the libraries used o8 = set_function(SCL) oled_begin() # begin() calls, clock_start(), c1.set() ... count = 0 # starting values of variables loop: # runs again and again, forever if i1 == ON: # read inputs, decide, set outputs led = ON count = count + 1 oled_write(1, left, small, regular, count) wait(300) else: led = OFF ``` ## 1.5 Rules you MUST follow (the compiler rejects anything else) 1. **Only use what is in this document.** Never invent functions, keywords, libraries or arguments. If a function is not in Part 5, it does not exist. No `print()`, `def`, `class`, `return`, `pass`, `True/False`, lists, dictionaries, `+=`, f-strings, `try`, `time.sleep`, `machine`, `Pin()`, `digitalWrite` or any Arduino / MicroPython code. 2. **Indent with 4 spaces.** Blocks end with `:` — `setup:`, `loop:`, `if …:`, `elif …:`, `else:`, `while …:`, `repeat(n):`, `for i in range(n):`. 3. **Order:** header comments → `import` lines → `set_name` lines → `setup:` → `loop:`. Give each module pin a name like TinkerPy Code does — `i1 = set_name("light_sensor_1")`, `o1 = set_name("servo_motor_1")` — and use the names in setup: and the code. 4. **One-time things go in `setup:`**: pin settings (`set_function`), `oled_begin()`, `lcd_begin()`, `bluetooth_begin()`, `rgb_begin()`, `clock_start()`, `c1.set()` + `c1.auto_increment()`, `servo_scan_on()`, `servo_sync()` and the **starting value of every variable that must remember something**. Everything in `loop:` runs again on every pass — `count = 0` inside `loop:` resets it every time. 5. **Numbers are whole numbers** from −32768 to 32767 (no decimals — except volts with `voltage()`, see rule 8). A number written outside that range is an error (“Numbers must be between -32768 and 32767”); a bigger *result* of maths wraps round, on the board and in the Simulator alike (`300 * 300` gives 24464). `/` drops the fraction: `7 / 2` is 3. `%` is the remainder. 6. **At most 10 variables** per program. Variable names: letters, digits, `_`, starting with a letter; not a pin name or pin-like name (`i1–i4`, `o1–o8`, and no `o9`, `i5`, `c9`), not `c1–c8`, `HH`, `MM`, `SS`, `ON`, `OFF`, `None`, not a function name (`wait`, `random`, `pressure` …) and not a keyword (`loop`, `setup`, `if` …). A variable needs a start value before it changes itself: `count = count + 1` with no `count = 0` before it is an error. The `i` of `for i in range()` and each name in `x, y = …` count as variables too. 7. **Text** (firmware 2.24): a variable can hold text — `msg = "hello"`, `msg = TP00000002.read()`, `m = bluetooth_read_string()` — up to **6 text variables**, 30 characters each. Join text and numbers with `+`: `label = "T: " + temp + " C"`. Text can be stored, compared (`==` / `!=` with text, another text variable or `None` = empty), shown and sent, but never used in maths, and a variable that holds text can't also hold a number. Text in quotes is also used where a function asks for it (robot directions `"F"`, tone names, colour names, animation names, `set_name("lamp")`) and compared with what the app sent: `bluetooth_read_char() == "F"`, `bluetooth_read_string() == "open"`. Single `'F'` and double `"F"` quotes both work. A one-letter character from the app stays a number: `k = bluetooth_read_char()`, then `if k == "F":`. 8. **Inputs:** `i1 == ON` / `i1 == OFF` for buttons and digital sensors. Analog sensors: `analog_read(i1)` gives 0 – 100, `voltage(i1)` gives volts 0.00 – 3.30 (firmware 2.24) — compare volts with decimals: `if voltage(i1) > 1.6:`. Put `i1 = set_function(adc)` in `setup:` for both. A pin read with `analog_read` / `voltage` must not also be checked as ON/OFF. Outputs cannot be read (`if o1 == ON` is wrong). 9. **Outputs:** `o1 = ON`, `o1 = OFF`, `o1 = 1`, `o1 = 0`, `o1 = pwm(0…100)` (power %), `o1 = variable`, or `o1 = servo_angle(0…180)` for a servo. A written number other than 0/1 needs `pwm()`: `o1 = pwm(50)`, not `o1 = 50`. A variable or sum works directly as 0–100 power: `o1 = level`, `o1 = i * 20`. 10. **Fixed pins cannot be used for anything else** once their library is used: ultrasonic i3/i4, I2C (OLED / LCD / MPU6050 / RTC / pulse oximeter / BMP280 / VL53L0X / colour / gesture sensor) o7/o8, robot motors o3–o6. Drive motors only with `robot_control()`, the easy moves `robot_forward(speed)` · `robot_backward(speed)` · `robot_left(speed)` · `robot_right(speed)` · `robot_arc_left(speed)` · `robot_arc_right(speed)` · `robot_stop()`, or `motor_control_left()` / `motor_control_right()`. 11. **OLED**: `oled_write(line, align, size, weight, value)` — 4 lines; align left/center/right; size small (21 letters, 1 line), medium (10 letters, 2 lines), large (7 letters, 2 lines); weight regular/bold. Medium/large start on line 1, 2 or 3. Text longer than the size allows is an error. 12. **Readings from the app** (`bluetooth_read_…`, `iot_read_…`, `remote_read()`) give `None` when nothing new arrived: check `if x != None:` before using a number. `distance()` gives **−1** when nothing is in range, so test `if d > 0 and d < 15:`, not just `d < 15`. 13. **Debounce buttons:** after acting on a press, `wait(200…300)` so one press counts once. Keep loops calm: add a small `wait()` when nothing needs to be fast, and never write a `while` loop that can never end without a `wait()` inside. 14. **Comments** start with `#`. Add short, helpful comments for students. Keep code simple and readable — use clear variable names. 15. **Safety:** only low voltage (USB 5 V, batteries). Pumps, fans and motors go through a motor driver or relay module. Never tell a student to wire 230 V mains; if a project needs mains, say an adult / electrician must handle that part. 16. **Numbers can be variables:** wherever a function takes a number (power, angle, LED number, line, speed, time…) you may use a variable or a sum: `rgb_color(o1, pos, "red")`, `wait(gap * 100)`. Pins, quoted names and the words left/center/right, small/medium/large, regular/bold must be written as they are. 17. **Messages**: `bluetooth_write` / `iot_write` send only when the message **changes** — the same message twice in a row is sent once. Send something else in between (e.g. `"clear"`) if the same alert must arrive again. 18. **Setup lines** can be in any order. A buzzer can be switched like an LED (`o2 = ON` / `OFF`); `import buzzer` and `buzzer_play()` are for tones and songs (the program waits until the tone ends); on TinkerPy Mega (firmware 2.29) `buzzer_play_background()` plays one while the program goes on. Beeps, bells and alerts work on both buzzer types; songs need a passive buzzer. ## 1.6 Check before you answer - Every function, argument count and keyword appears in this document. - Every library used has its `import` line and its setup lines from Part 4 (fixed pins, `…_begin()`). - No pin is used for two things; fixed pins are only used for their device. - Variables that must keep their value start in `setup:`; 10 variables or fewer; whole numbers only. - Indentation is 4 spaces; every block line ends with `:`. - Quoted text is only used where allowed; OLED text fits the chosen size. - Buttons are debounced; app readings are checked against `None`. - The wiring table matches the code exactly. If you are not sure a line is valid, use a simpler form that you can see in the examples of this document. # Part 2 — The TinkerPy Mega board and its pins TinkerPy Mega (TinkerKit 2.0) uses an ESP32-C3 chip with WiFi and Bluetooth. It has **4 input pins (i1–i4)**, **8 output pins (o1–o8)**, one menu button and an OLED screen connector. Programs are written in TinkerPy Code (tinkerpy.com), compiled, tested in the Simulator and uploaded over WiFi or Bluetooth. Connect each module’s signal pin (S / OUT / DATA / IN) to the board pin, and its VCC and GND to the power and ground pins next to it on the board. **The menu button** belongs to the board, not to programs: a program cannot read it (use a push button on an input pin instead). With firmware 2.22+, pressing it while a program runs pauses the program on the Home screen for 3 seconds; pressing it again within those 3 seconds opens the menu (TV Remote, Wireless devices, Debug / Test with OLED Emojis and Buzzer Tones, error codes, **RESET board** …), otherwise the program carries on by itself. From firmware 2.23, while a program runs that does not use the OLED, the board screen shows **▶ RUNNING** and the project name. ## 2.1 Pin table | Pin | Kind | Use it for | Fixed jobs (when that library is used) | |----------------|----------------|--------------------------------------------------------------------------------------------------------------------|------------------------------------------| | **i1** | input · analog | button, IR / PIR / touch sensor (ON/OFF) or LDR / soil / knob (`analog_read` 0–100 or `voltage` 0.00–3.30 V), DHT11, joystick X, TV remote | — | | **i2** | input · analog | same as i1; joystick Y | — | | **i3** | input · analog | same as i1; DHT11 (examples use i3); joystick switch | **ultrasonic Trig** (`ultrasonic_TX`) | | **i4** | input · analog | same as i1 | **ultrasonic Echo** (`ultrasonic_RX`) | | **o1**, **o2** | output · PWM | LED (with brightness), buzzer, servo, RGB LEDs, driver / relay input | — | | **o3** | output · PWM | same as o1 | **robot: right motor forward** | | **o4** | output · PWM | same as o1 | **robot: right motor backward** | | **o5** | output · PWM | same as o1 | **robot: left motor forward** | | **o6** | output · PWM | same as o1 | **robot: left motor backward** | | **o7** | output · PWM | same as o1 | **I2C SDA** — OLED / LCD / MPU6050 data | | **o8** | output · PWM | same as o1 | **I2C SCL** — OLED / LCD / MPU6050 clock | - OLED, LCD, MPU6050 and the firmware 2.27 I2C sensors (RTC, pulse oximeter, BMP280, VL53L0X, TCS34725, APDS-9960) all share the I2C pins o7/o8 — they can be used together in one project, except two parts with the same address: RTC + MPU6050 (0x68), VL53L0X + TCS34725 (0x29). - An output pin can also read a button/sensor: `o5 = set_function(active_low)` in `setup:`, then `if o5 == ON:`. - **Free pins with a robot + display:** outputs o1, o2 and inputs i1, i2 (and i3, i4 when there is no ultrasonic sensor). ## 2.2 Inputs: ON and OFF `i1 == ON` means “the button is pressed / the sensor is triggered”. By default an input is **active low** (ON when the signal pin is pulled to GND — how most buttons and IR / obstacle modules work). For a module whose output goes HIGH when it detects something (many PIR and touch sensors), add `i1 = set_function(active_high)` in `setup:`. ## 2.3 Where each device goes (AI: use these when you pick pins) | Device | Pin(s) | Setup line(s) | |---------------------------------------------------------------|-----------------------------------------------------------|-----------------------------------------------------------------------------------------------------| | Push button, IR / PIR / touch / rain / sound sensor (digital) | any of i1–i4 (first free) | `i1 = set_function(active_low)` or `active_high` — an input with no setup line is **active_low** (Compile adds it) | | LDR, soil moisture, potentiometer (analog 0–100) | i1–i4 | `i1 = set_function(adc)` — read with `analog_read(i1)` (0–100) or `voltage(i1)` (0.00–3.30 V). An ADC pin can’t be checked as ON/OFF; compare `analog_read(i1) > 50` | | Ultrasonic HC-SR04 | Trig i3, Echo i4 (fixed) | `i3 = set_function(ultrasonic_TX)`, `i4 = set_function(ultrasonic_RX)` | | DHT11 | one of i1–i4 (prefer i3, or i1 if the ultrasonic is used) | `i3 = set_function(dht11)` | | MPU6050 | SDA o7, SCL o8 (fixed) | `o7 = set_function(SDA)`, `o8 = set_function(SCL)` | | RTC clock (DS3231 / DS1307) | SDA o7, SCL o8 (fixed) | `import rtc` + `o7 = set_function(SDA)`, `o8 = set_function(SCL)` | | Pulse oximeter (MAX30100 / MAX30102) | SDA o7, SCL o8 (fixed) | `import pulse_oximeter` + `o7 = set_function(SDA)`, `o8 = set_function(SCL)` | | BMP280 pressure | SDA o7, SCL o8 (fixed) | `import bmp280` + `o7 = set_function(SDA)`, `o8 = set_function(SCL)` | | VL53L0X laser distance | SDA o7, SCL o8 (fixed) | `import vl53l0x` + `o7 = set_function(SDA)`, `o8 = set_function(SCL)` | | TCS34725 colour | SDA o7, SCL o8 (fixed) | `import tcs34725` + `o7 = set_function(SDA)`, `o8 = set_function(SCL)` | | APDS-9960 gesture | SDA o7, SCL o8 (fixed) | `import apds9960` + `o7 = set_function(SDA)`, `o8 = set_function(SCL)` | | GPS module (NEO-6M …) | any pin (its TX wire) | `import gps` + `i1 = set_input(gps_rx)` | | GSM SIM800L (SMS, calls) | any pin for its TX wire, any output for its RX wire | `import gsm` + `i2 = set_input(gsm_rx)`, `o5 = set_output(gsm_tx)` | | OLED 0.96" (I2C) | SDA o7, SCL o8 (fixed) | those two + `oled_begin()` | | 16x2 LCD (I2C) | SDA o7, SCL o8 (fixed) | those two + `lcd_begin(0x27)` (or 0x3F; `lcd_begin()` finds it) | | Joystick (Mega) | X and Y on i1–i4, switch on any pin | `i1 = set_function(joystick_x)`, `i2 = set_function(joystick_y)`, `i3 = set_function(joystick_swt)` | | TV remote receiver TSOP1838 | any pin | `i1 = set_function(tv_remote)` (the 29 keys are learnt on the board: Menu → TV Remote → Learn Remote) | | LED | any free output | optional: `o1 = set_function(output)` | | Buzzer | any free output | `o1 = set_function(active_buzzer)` (beeps) or `passive_buzzer` (real songs) | | Servo SG90 / MG90 | any free output | `o1 = set_function(servo)` | | Robot car (2 DC motors + driver) | o3–o6 (fixed) | the four `motor_…` lines (Part 4) | | Small pump / fan / motor, relay module | any free output (through a driver / relay) | optional: `o1 = set_function(output)` | | RGB LEDs WS2812B (1, 2, 3 or a strip) | any free output | `rgb_begin(o1, number_of_leds)` | | Bluetooth / IoT (TinkerPy App) | no pin | Bluetooth: `bluetooth_begin()`; IoT: none (board connects to WiFi by itself) | ## 2.4 Timing - `wait(ms)` pauses the program (1000 ms = 1 second). Counters (`c1.auto_increment`), the clock, servo scans and RGB effects keep running in the background while the program waits. - The program runs `loop:` again and again very fast. Bluetooth/IoT data is read once per pass. ## 2.5 Screens and sensors — practical tips - **OLED**: each `oled_write` fills one whole line, so a label and its number go on **separate lines** (e.g. line 1 `"Temp (C)"` small, line 2 the number in large). Plan the 4 lines: medium / large use 2 lines each. For a label and a number on the same line use the **16x2 LCD**: `lcd_write(1, 1, "Temp:")` + `lcd_write(1, 7, t)`. - Update a screen with a `wait()` (200–1000 ms) in the loop so it does not flicker. - **Analog sensors** (LDR, soil, knob) give 0–100. Modules differ (some soil sensors give a HIGH value when dry): tell the student to show the value on the screen in both conditions and then set the threshold. - **Time events** (`if HH == 9 and MM == 0:`) stay true for a whole minute: use a variable so the action happens once (`if HH == 9 and MM == 0 and rang == 0:` … `rang = 1`, and set `rang = 0` again when `MM != 0`). - **Clock on a screen**: numbers show without a leading zero (9:5). Show HH, MM and SS on separate OLED lines, or on the LCD write `"0"` first when the value is below 10: `if MM < 10:` `lcd_write(1, 4, "0")` + `lcd_write(1, 5, MM)`. - **Which screen?** Use the OLED by default (big / bold / centred text). Use the 16x2 LCD when a label and a number must share a line. - **PIR motion sensors** need about 30–60 seconds after power-on before they work reliably. - **DHT11**: read it about every 2 seconds (`wait(2000)`). **Ultrasonic**: about 2–400 cm, −1 when nothing is in range. - **RTC clock**: put `rtc_set_time(h, m, s)` / `rtc_set_date(d, m, y)` in setup: — the board sets the clock once when the new code arrives (not at every power-on). For an alarm that should happen once, use a variable like the HH / MM tip above. - **Pulse oximeter**: a fingertip resting gently, no pressing, no moving; `heart_rate()` / `spo2()` are 0 until a few beats are measured. Use `heart_beat()` to blink or beep with the heart. Learning only — never for medical decisions. - **Gesture (APDS-9960)**: each swipe is seen in one pass of loop:, so test it with `if gesture() == "up":` … `elif gesture() == "down":` in the same pass, or store it first: `g = gesture()`. - **Colour sensor**: hold the colour 1–2 cm away; check `color_name()` on the screen for your own papers first (lighting changes colours). - **GPS** works outdoors (a minute to find satellites); `gps_location()` is text for a screen, an SMS or the app. **GSM**: a SIM800L needs its own 4 V, 2 A supply; send an SMS on a change (a button press, a new alarm), not every loop — the board sends the same SMS only once in 5 minutes. ## 2.6 Testing in the Simulator In TinkerPy Code: **Compile** → **Simulator** → **Start**. A tile appears for each pin and device the program uses (more can be added with the edit / catalog button). Press or hold an **input tile** to press a button; drag **sliders** for analog pins, the ultrasonic distance, DHT11 temperature / humidity, MPU6050 tilt and turn (plus Shake / Fall / Step buttons) and the joystick. The **Bluetooth / IoT message box** sends a letter, text, number, position or colour to the program, like the TinkerPy App. Output tiles show LEDs (brightness), servo angles, the robot, buzzer, RGB LEDs, OLED and LCD. Firmware 2.27 sensors have their own tiles: the RTC clock (your computer’s time), the pulse oximeter (finger on / off, heart-rate and SpO₂ sliders), BMP280 (altitude, temperature), laser distance, the colour sensor (colour picker and swatches) and gesture (swipe buttons and a nearness slider). Firmware 2.28: a GPS tile (fix on / off, walk N / S / E / W, speed) and a GSM phone tile (SMS from the board appear there; send an SMS to the board or call it). ## 2.7 TinkerPy Mini (only if the user says so) TinkerPy Mini (ESP8266) has only inputs **i1, i2** (ultrasonic on i1/i2), outputs o1–o8 like Mega, **no Bluetooth** and no joystick. Everything else is the same. # Part 3 — Program structure and language rules ## 3.1 The parts of a program
Part What it is Example
Comments Notes for people. Start with #. The first lines say the project name. # ===== Night Lamp =====
Imports One line per library (Part 4). They switch the library on in the editor. import oled_display
Pin names Optional friendly names for pins, written before setup:. Use the new name everywhere after. o1 = set_name("lamp") then lamp = ON
setup: Runs once at power-on: pin settings, begin() calls, starting values. setup:
    o2 = set_function(servo)
loop: Runs forever, top to bottom, again and again. (Code written after setup: without loop: also repeats — always write loop: for clarity.) loop:
    o1 = ON
## 3.2 Values - **Numbers**: whole numbers −32768 … 32767, also negative (`-5`) and hex (`0x27`); a number outside this range is a compile error, and a maths result outside it wraps round (`32767 + 1` gives −32768). Decimals (`1.6`) only as volts next to `voltage()` (firmware 2.24; the board keeps millivolts, 1.6 → 1600). - **ON / OFF**: for inputs (pressed / not pressed) and outputs (full on / off). `1` and `0` also work for outputs. - **None**: “nothing arrived” from the app / remote. Compare with `!= None` or `== None`. - **Text** in double quotes `"Hello"` — can go in a text variable (2.24), be joined with `+`, compared, shown and sent (rule 7 of 1.5). - **Special read-only values**: `HH`, `MM`, `SS` (clock), `c1` … `c8` (counters), pins `i1` … `i4`. ## 3.3 Variables Create a variable by giving it a value: `count = 0`. Change it: `count = count + 1`. Up to 10 variables. A variable can hold a number, a reading (`d = distance()`), a counter or clock value, or a character from the app (`k = bluetooth_read_char()`, then `if k == "F":`). To **remember** something between loop passes (a score, a mode, “armed”), give the starting value in `setup:`. ```tinkerpy setup: mode = 0 # remembered between passes loop: if i1 == ON: mode = mode + 1 # next mode on each press if mode > 2: mode = 0 wait(300) # one press = one step ``` **Text variables (firmware 2.24):** a variable that is given text holds text — up to 6 of them, 30 characters each, on top of the 10 number variables. Join with `+` (numbers become digits). A message from the app or another board is there for **one loop**, so keep it like this: ```tinkerpy setup: TP00000002.connect() oled_begin() last = "-" # a text variable loop: if TP00000002.available() == 1: last = TP00000002.read() # keep the newest message t = dht_temperature(i3) oled_write(1, left, small, regular, "Got: " + last) oled_write(2, left, small, regular, "T: " + t + " C") ``` ## 3.4 Maths, comparisons and logic | Kind | Symbols | Example | |---------|--------------------------------|-----------------------------------| | Maths | `+ - * / %` and brackets `( )` | `avg = (a + b) / 2` | | Compare | `== != < > <= >=` | `if temp >= 30:` | | Logic | `and or not` · `invert(pin)` | `if i1 == ON and not (i2 == ON):` · `o1 = invert(o2)` | | Random | `random(a, b)` | `dice = random(1, 6)` | Write each comparison in full: `if x > 1 and x < 5:` (not `1 < x < 5`). ## 3.5 Decisions and loops | Form | Meaning | |-------------------------------|---------------------------------------------------------------------------------------| | `if c:` / `elif c:` / `else:` | Do the indented lines only when the condition is true (checked top to bottom). | | `repeat(n):` | Do the indented lines n times (n may be a variable). n = 0 or less: not at all. | | `for i in range(n):` | Do it n times with `i` = 0, 1 … n−1 (`range(0)`: not at all). One value only. | | `while c:` | Repeat while the condition is true. Put a `wait()` inside when it waits for a sensor. | | `break` | Leave the nearest `repeat` / `for` / `while` early. | ```tinkerpy loop: # wait here until the button is pressed while i1 == OFF: wait(20) repeat(3): # blink 3 times o1 = ON wait(200) o1 = OFF wait(200) for i in range(10): # fade up: 0, 10, 20 … 90 o2 = pwm(i * 10) wait(50) ``` ## 3.6 Common mistakes → correct TinkerPy | Wrong | Right | |-------------------------------------------|-------------------------------------------------------------------------------------------------| | `o1 = 50` | `o1 = pwm(50)` | | `count += 1` | `count = count + 1` | | `while True:` | `loop:` (it already repeats forever) | | `def blink():` | no functions — write the lines where needed, or use `repeat` | | `print("hi")` | `oled_write(1, left, small, regular, "hi")` or `bluetooth_write("hi")` | | `time.sleep(1)` | `wait(1000)` | | `for i in range(0, 100, 10):` | `for i in range(10):` and use `i * 10` | | `oled_write(1, 1, "Hi")` (old form) | `oled_write(1, left, small, regular, "Hi")` | | `count = 0` at the top of `loop:` | put `count = 0` in `setup:` | | `clock_start(…)` / `c1.set(…)` in `loop:` | in `setup:` (in `loop:` only inside an `if`, e.g. a reset button) | | `o3 = ON` with `import motor` | `robot_control("F", 80, "F", 80)` | | `if o1 == ON:` | outputs cannot be read — keep a variable, e.g. `light = 1` | | `temp = 25.5` | whole numbers only: `temp = 25` (decimals are only for volts: `if voltage(i1) > 1.6:`) | # Part 4 — Libraries: import line and setup lines Every library a program uses needs its `import` line at the top and its setup lines inside `setup:`. Core features (inputs, outputs, `analog_read`, `voltage`, `wait`, `random`, `if`, loops, variables) need no import.
Library Import line Setup lines (inside setup:) Notes
Servo import servo
o1 = set_function(servo)
One line per servo, on any free output.
Ultrasonic import ultrasonic
i3 = set_function(ultrasonic_TX)
i4 = set_function(ultrasonic_RX)
Fixed pins: Trig i3, Echo i4. distance() gives cm.
MPU6050 import mpu6050
o7 = set_function(SDA)
o8 = set_function(SCL)
Fixed I2C pins. Keep the board still for the first second after power-on.
RTC clock (DS3231 / DS1307) import rtc
o7 = set_function(SDA)
o8 = set_function(SCL)
Real time and date, kept by the module’s battery. rtc_set_time / rtc_set_date in setup: set it once per new code. Address 0x68 — not together with the MPU6050. Firmware 2.27.
Pulse oximeter (MAX30100 / MAX30102) import pulse_oximeter
o7 = set_function(SDA)
o8 = set_function(SCL)
Heart rate and SpO₂ from a fingertip. For learning only. Address 0x57. Firmware 2.27.
BMP280 pressure import bmp280
o7 = set_function(SDA)
o8 = set_function(SCL)
Air pressure (hPa), temperature, altitude (m). Address 0x76 / 0x77. Firmware 2.27.
VL53L0X laser distance import vl53l0x
o7 = set_function(SDA)
o8 = set_function(SCL)
3 cm – 2 m in cm, 999 = nothing. Address 0x29 — not together with the TCS34725. Firmware 2.27.
TCS34725 colour import tcs34725
o7 = set_function(SDA)
o8 = set_function(SCL)
Colour name and R G B. Address 0x29 — not together with the VL53L0X. Firmware 2.27.
APDS-9960 gesture import apds9960
o7 = set_function(SDA)
o8 = set_function(SCL)
Swipes up / down / left / right, nearness, and colour. Address 0x39. Firmware 2.27.
GPS (NEO-6M …) import gps
i1 = set_input(gps_rx)
Any pin: the GPS module's TX wire → this pin. Firmware 2.28.
GSM SIM800L import gsm
i2 = set_input(gsm_rx)
o5 = set_output(gsm_tx)
Any pins: module TX → gsm_rx, module RX → gsm_tx (an output). Own 4 V 2 A supply. Firmware 2.28.
OLED Display import oled_display
o7 = set_function(SDA)
o8 = set_function(SCL)
oled_begin()
Fixed I2C pins. 4 text lines.
16x2 LCD Display import lcd_16x2
o7 = set_function(SDA)
o8 = set_function(SCL)
lcd_begin(0x27)
Fixed I2C pins. 2 lines × 16 letters.
DHT11 import dht11
i3 = set_function(dht11)
Any input i1–i4; all DHT11 readings use the same pin.
Counter import counter
c1.set(0)            # optional starting value
Eight counters c1–c8. No pins.
Clock import clock
clock_start(7, 0, 0)  # hour, minute, second
A software clock. Set it to the real time.
Bluetooth import bluetooth
bluetooth_begin()
TinkerPy Mega only. Talks to the TinkerPy App over Bluetooth.
IoT import iot
(no setup line)
Talks to the TinkerPy App over the internet (board needs WiFi).
Robot (motors) import motor
o3 = set_function(motor_right_forward)
o4 = set_function(motor_right_backward)
o5 = set_function(motor_left_forward)
o6 = set_function(motor_left_backward)
Fixed pins o3–o6 through a motor driver.
RGB LED (1 LED board) import rgb_single
rgb_begin(o1, 1)
A board with 1 RGB LED on any free output.
RGB LED (2 LED board) import rgb_two
rgb_begin(o1, 2)
A board with 2 RGB LEDs.
RGB LED (3 LED board) import rgb_three
rgb_begin(o1, 3)
A board with 3 RGB LEDs.
RGB LED strip import rgb_strip
rgb_begin(o1, 30)
A strip: the number is how many LEDs it has (1–60).
Joystick (Mega) import joystick
i1 = set_function(joystick_x)
i2 = set_function(joystick_y)
i3 = set_function(joystick_swt)
TinkerPy Mega. X/Y need i1–i4; the switch can be any pin; leave out what is not wired.
TV Remote (IR) import tv_remote
i1 = set_function(tv_remote)
Any pin. Learn the remote’s keys on the board: Menu → TV Remote.
Wireless (board to board) import wireless
TP00000002.connect()
No wires: the other board’s Device ID (Menu → Device info). Up to 6 boards; both programs must list each other. TinkerPy Mega, firmware 2.24.
Wireless IoT (over the internet) import wireless_iot
TP00000002_iot.connect()
Boards anywhere, each on WiFi; tinkerpy.com passes the messages (a few seconds). Both programs must list each other. TinkerPy Mega, firmware 2.25.
Buzzer import buzzer
o1 = set_function(active_buzzer)
Any free output. Use passive_buzzer for real songs.
# Part 5 — Function reference Every function, keyword and value of TinkerPy, grouped like the editor’s palette. Each entry gives the exact form, what it does, what each value means and working examples. **Examples show the important lines; a full program also needs the import and setup lines from Part 4** (TinkerPy Code adds missing ones when you press Compile). “Firmware” is the oldest board firmware that runs it. ## 5.1 Quick list of all functions | Group | Forms | |--------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Pins, setup and outputs (core) | `pin = set_input(device, mode)` · `pin = set_output(device[, value])` · `pin = set_function(type)` · `pin = set_name("name")` · `input == ON / input == OFF` · `output = ON / OFF / 1 / 0` · `output = pwm(value)` · `output = servo_angle(angle)` | | Control flow | Digital input condition `if i1 == ON:` · Analog input condition `if analog_read(i1) < 30:` / `if voltage(i1) > 1.6:` · `if :` · `elif :` · `else:` | | Loop | `repeat(count):` · `for in range(count):` · `while condition:` · `break` | | Arithmetic and Logic | `random(smallest, biggest)` · `a + b, a - b, a * b, a / b, a % b` · `a == b, a != b, a < b, a > b, a <= b, a >= b` · `a and b, a or b, not a` | | General Code | `wait(milliseconds)` · `wifi("network", "password")` | | Analog Input | `analog_read(input)` · `voltage(input)` | | Servo Function | `servo_write_angle(output, angle)` · `servo_increment(output, step, max_angle, step_delay)` · `servo_decrement(output, step, min_angle, step_delay)` · `servo_increment_till(output, start_angle, end_angle, step, step_delay)` · `servo_decrement_till(output, start_angle, end_angle, step, step_delay)` · `servo_oscillate(output, home_angle, angle_a, angle_b, step, step_delay)` · `servo_flip(output, start_angle, end_angle, step, step_delay)` · `servo_scan_on(output, start_angle, end_angle, step, step_delay)` · `servo_scan_stop(output)` · `servo_scan_resume(output)` · `servo_read_angle(output)` · `servo_sync(output_a, output_b)` · `servo_sync_reverse(output_a, output_b)` | | Output Function | ` = ` · ` = invert()` · `output_increment(output, step, max_value, step_delay)` · `output_decrement(output, step, min_value, step_delay)` · `output_increment_till(output, start_value, end_value, step, step_delay)` · `output_decrement_till(output, start_value, end_value, step, step_delay)` · `output_flip(output, off_value, on_value)` | | Ultrasonic Function | `distance()` | | DHT11 Function | `dht_temperature(input)` · `dht_humidity(input)` | | MPU6050 Function | `tilt_x()` · `tilt_y()` · `tilt_direction()` · `shake_detected()` · `motion_level()` · `fall_detected()` · `turn_angle()` · `reset_turn()` · `step_count()` · `reset_steps()` · `accel_x()` · `accel_y()` · `accel_z()` · `gyro_x()` · `gyro_y()` · `gyro_z()` · `mpu_temperature()` | | RTC Clock Function | `rtc_hour()` · `rtc_minute()` · `rtc_second()` · `rtc_day()` · `rtc_month()` · `rtc_year()` · `rtc_weekday()` · `rtc_set_time(hour, minute, second)` · `rtc_set_date(day, month, year)` | | Pulse Oximeter Function | `heart_rate()` · `spo2()` · `finger_detected()` · `heart_beat()` | | BMP280 Function | `pressure()` · `bmp_temperature()` · `altitude()` | | Laser Distance Function | `laser_distance()` | | Colour Sensor Function | `color_name()` · `color_red()` · `color_green()` · `color_blue()` · `color_brightness()` | | Gesture Function | `gesture()` · `proximity()` | | GPS Function | `gps_found()` · `gps_satellites()` · `gps_speed()` · `gps_altitude()` · `gps_hour()` · `gps_minute()` · `gps_second()` · `gps_save_home()` · `gps_distance_home()` · `gps_location()` | | GSM Function | `gsm_send_sms("number", message)` · `gsm_sms_received()` · `gsm_read_sms()` · `gsm_sms_number()` · `gsm_call("number")` · `gsm_hang_up()` · `gsm_ringing()` · `gsm_signal()` | | Buzzer Function | `buzzer_play(output, "tone")` · `buzzer_play_background(output, "tone", repeat)` · `buzzer_stop_background(output)` · `is_buzzer_playing(output)` | | TV Remote Function | `remote_read()` · `remote_read() == "key"` · `remote_read_string(count, start, display, visibility, seconds)` | | Wireless Function | `TP00000002.connect()` · `TP00000002.send(value)` → 1 / 0 · `TP00000002.available()` · `TP00000002.read()` · `TP00000002.read_number()` · `TP00000002.signal()` · `TP00000002.connected()` · `TP00000002.disconnect()` · `wireless_send_all(value)` · `id, data = wireless_read_any()` | | Wireless IoT Function | `TP00000002_iot.connect()` · `TP00000002_iot.send(value)` → 1 / 0 · `TP00000002_iot.available()` · `TP00000002_iot.read()` · `TP00000002_iot.read_number()` · `TP00000002_iot.connected()` · `TP00000002_iot.disconnect()` · `wireless_iot_send_all(value)` · `id, data = wireless_iot_read_any()` | | Joystick Function | `joystick_x()` · `joystick_y()` · `joystick_direction()` · `joystick_pressed()` | | RGB LED Function | `rgb_begin(output, number_of_leds)` · `rgb_color(output, led, "color", brightness)` · `rgb_flip(output, led, "color", brightness)` · `rgb_hex_color(output, led, r, g, b)` · `rgb_blink(output, led, "color", on_ms, off_ms)` · `rgb_breathe(output, led, "color", time_ms)` · `rgb_swap(output, led, "color", "color2", time_ms)` · `rgb_chase(output, led, "color", speed_ms)` · `rgb_wipe(output, led, "color", speed_ms)` · `rgb_twinkle(output, led, "color", speed_ms)` · `rgb_bar(output, led, "color", value, max)` · `rgb_heat(output, led, "color", value, low, high)` | | LCD Display Function | `lcd_begin(address)` · `lcd_write(line, position, value)` · `lcd_clear()` · `lcd_clear_line(line)` · `lcd_scroll(line, text)` · `lcd_backlight(ON / OFF)` | | OLED Display Function | `oled_begin(address)` · `oled_write(line, align, size, weight, value)` · `oled_clear()` · `oled_clear_line(line)` · `oled_eye_animation(name, repeat, speed, delay)` · `oled_emoji_animation(name, repeat, speed, delay)` · `oled_scroll(line, text)` | | Counter Function | `c1.auto_increment(interval_ms)` · `c1.auto_decrement(interval_ms)` · `c1.increment()` · `c1.decrement()` · `c1.clear()` · `c1.pause()` · `c1.set(value)` | | Clock Function | `clock_start(hours, minutes, seconds)` · `HH, MM, SS` · `clock_speed(real_ms_per_second)` · `clock_pause()` · `clock_resume()` | | Bluetooth & IoT Function | `bluetooth_begin()` · `bluetooth_connected()` · `bluetooth_write(value)` · `bluetooth_write(a, b[, c])` · `bluetooth_read_char()` · `bluetooth_read_string()` · `bluetooth_read_number()` · `x, y = bluetooth_read_position()` · `r, g, b = bluetooth_read_rgb()` · `set_device_password("1234")` · `iot_write(value)` · `iot_write(a, b[, c])` · `iot_read_char()` · `iot_read_string()` · `iot_read_number()` · `x, y = iot_read_position()` · `r, g, b = iot_read_rgb()` | | Robot Function | `robot_control(left_dir, left_speed, right_dir, right_speed)` · `robot_forward(speed)` · `robot_backward(speed)` · `robot_left(speed)` · `robot_right(speed)` · `robot_arc_left(speed)` · `robot_arc_right(speed)` · `robot_stop()` · `motor_control_right(direction, speed)` · `motor_control_left(direction, speed)` | ## 5.2 Details and examples ### Pins, setup and outputs (core) pin = set_input(device, mode) Inside setup: — says what is connected to an input pin (the newer, clearer form of set_function). ON / OFF modules MUST give their mode: active_low (ON when the pin reads LOW — most modules) or active_high (ON when HIGH — PIR and touch, marked *). 0–100 modules use adc (i1–i4 only). dht11, tv_remote, ultrasonic_trig (i3), ultrasonic_echo (i4), gps_rx and gsm_rx (any pin, firmware 2.28) have no mode; gsm_tx is set with set_output(gsm_tx). The device name is for the editor and the simulator (it shows that module); the board runs it exactly like set_function, so no new firmware is needed. ON/OFF modules: push_button, general (switch), slide_switch, limit_switch, touch*, pir*, ir_sensor, sound, flame, vibration, reed, hall, tilt, rain, water, line_sensor, light_sensor, soil, lpg, alcohol, air_quality, joystick_swt. 0–100 modules: potentiometer, water_level, temperature, flex, joystick_x, joystick_y — and light_sensor, soil, lpg, alcohol, air_quality, general (these have both outputs: ON/OFF or adc). | | | |--------|--------| | `pin` | i1–i4 (or o1–o8 for an ON/OFF module used as an input), or its set_name name. | | `device` | What is connected — one of the names above (no quotes). | | `mode` | active_low · active_high · adc. | Example 1 — A motion sensor (PIR) on i1 turns a light on. ```tinkerpy setup: i1 = set_input(pir, active_high) loop: if i1 == ON: o1 = ON else: o1 = OFF ``` Example 2 — A light sensor read as 0–100 — a night lamp. ```tinkerpy setup: i2 = set_input(light_sensor, adc) loop: if analog_read(i2) < 30: o1 = ON else: o1 = OFF ``` Example 3 — A gas sensor (MQ-2) alarm on its ON/OFF output. ```tinkerpy setup: i3 = set_input(lpg, active_low) o2 = set_output(buzzer) loop: if i3 == ON: o2 = ON else: o2 = OFF ``` pin = set_output(device[, value]) Inside setup: — says what is connected to an output pin (o1–o8). Outputs have no mode. Devices: led, bulb, laser, relay, motor, fan, pump, lock, vibration, buzzer (buzzer, passive = tunes), servo (servo, 90 = start angle), rgb_led (rgb_led, 8 = how many LEDs), right_motor_P / right_motor_N (o3/o4), left_motor_P / left_motor_N (o5/o6). With only ONE robot motor set up, its partner’s two pins are free for other things; P and N may be swapped on a motor’s own two pins when it turns the wrong way (robot_control and motor_control_right/left then drive it the right way). robot_control(...) needs both motors. | | | |--------|--------| | `pin` | o1–o8. | | `device` | What is connected (no quotes). | | `value` | servo: start angle 0–180 · rgb_led: number of LEDs 1–60 · buzzer: passive for tunes. Nothing for the others. | Example 1 — A fan at 60 % and a servo that starts at 90°. ```tinkerpy setup: o1 = set_output(fan) o2 = set_output(servo, 90) loop: o1 = pwm(60) o2 = servo_angle(45) ``` Example 2 — An 8-LED RGB strip on o3. ```tinkerpy setup: o3 = set_output(rgb_led, 8) loop: rgb_color(o3, all, "rainbow", 80) ``` Example 3 — One motor only, P and N swapped (it turned the wrong way) — o5 and o6 stay free. ```tinkerpy setup: o3 = set_output(right_motor_N) o4 = set_output(right_motor_P) o5 = set_output(led) loop: motor_control_right('F', 70) o5 = ON ``` pin = set_function(type) Inside setup: — the older form of set_input / set_output (still works). An input with no setup line is active_low (Compile adds the line). Types (no quotes): servo, dht11, output, active_low, active_high, adc (i1–i4, analog only), active_buzzer, passive_buzzer, tv_remote, joystick_x, joystick_y, joystick_swt, ultrasonic_TX (i3), ultrasonic_RX (i4), SDA (o7), SCL (o8), motor_right_forward (o3), motor_right_backward (o4), motor_left_forward (o5), motor_left_backward (o6). | | | |--------|----------------------------------------| | `pin` | i1–i4 or o1–o8 (or its set_name name). | | `type` | One of the types above. | Example 1 — A servo on o2 and a DHT11 on i3. ```tinkerpy setup: o2 = set_function(servo) i3 = set_function(dht11) ``` Example 2 — A sensor whose output goes HIGH when it detects (many PIR / touch modules). ```tinkerpy setup: i1 = set_function(active_high) loop: if i1 == ON: o1 = ON else: o1 = OFF ``` Example 3 — Use output pin o5 as an extra button input. ```tinkerpy setup: o5 = set_function(active_low) loop: if o5 == ON: o1 = ON else: o1 = OFF ``` pin = set_name("name") Gives a pin an easy name. Write it before setup:, then use the name everywhere instead of the pin. TinkerPy Code names each part added in the Circuit Connections window the same way — light_sensor_1, motion_sensor_1, servo_motor_1, led_2 … (rename it there if you like). | | | |--------|-------------------------------------------------------------| | `name` | Letters, digits and \_ , in quotes, starting with a letter. | Example 1 — Names make code easy to read. ```tinkerpy i1 = set_name("door") o1 = set_name("alarm") loop: if door == ON: alarm = ON else: alarm = OFF ``` input == ON / input == OFF Reads a digital input: ON when the button is pressed or the sensor is triggered. Use it in if / elif / while. | | | |---------|------------------------------------------------------------------------| | `input` | i1–i4, an o-pin set as active_low / active_high, or its set_name name. | Example 1 — A doorbell light. ```tinkerpy if i1 == ON: o1 = ON else: o1 = OFF ``` output = ON / OFF / 1 / 0 Switches an output fully on or off (LED, buzzer, relay, driver). | | | |----------|-----------------------------| | `output` | o1–o8 or its set_name name. | Example 1 — Blink o1 every half second. ```tinkerpy o1 = ON wait(500) o1 = OFF wait(500) ``` output = pwm(value) Sets an output’s power from 0 to 100 % — LED brightness, motor / fan speed. A variable or a sum can also be given directly: output = level. | | | |---------|---------------------------------------------------------------------| | `value` | 0–100 (a number, variable or sum). Out-of-range values are clamped. | Example 1 — Half brightness. ```tinkerpy o1 = pwm(50) ``` Example 2 — A knob on i1 sets the brightness. ```tinkerpy o1 = pwm(analog_read(i1)) ``` output = servo_angle(angle) Moves a servo to an angle at once (same as servo_write_angle). | | | |---------|--------------------------------------------| | `angle` | 0–180 degrees (a number, variable or sum). | Example 1 — Open a gate while the button is pressed. ```tinkerpy setup: o1 = set_function(servo) loop: if i1 == ON: o1 = servo_angle(90) else: o1 = servo_angle(0) ``` ### Control flow if \: Runs the indented lines below only when the condition is true. | | | |-------------|--------------------------------------------| | `condition` | A comparison, like i1 == ON or count \> 5. | Example 1 — Turns o1 on while i1 is pressed, off otherwise. ```tinkerpy if i1 == ON: o1 = pwm(100) else: o1 = 0 ``` Example 2 — Turns o1 on only when BOTH buttons are pressed. ```tinkerpy if i1 == ON and i2 == ON: o1 = pwm(100) ``` Example 3 — Checks a variable’s value, not just a pin. ```tinkerpy count = 0 if count == 0: o1 = pwm(100) ``` elif \: Checked only if the earlier if (and any earlier elif) was false. | | | |-------------|----------------------------------------------| | `condition` | A comparison, checked in order after the if. | Example 1 — Different pins give different output levels. ```tinkerpy if i1 == ON: o1 = pwm(100) elif i2 == ON: o1 = pwm(50) else: o1 = 0 ``` Example 2 — Checks a variable against different thresholds. ```tinkerpy count = 5 if count > 10: o1 = pwm(100) elif count > 5: o1 = pwm(50) else: o1 = 0 ``` Example 3 — elif can check the SAME pin again with a different condition. ```tinkerpy if i1 == ON: o1 = pwm(100) elif i1 == OFF: o1 = 0 ``` else: Runs when none of the if/elif conditions above were true. Example 1 — Runs when the if condition was false. ```tinkerpy if i1 == ON: o1 = pwm(100) else: o1 = 0 ``` Example 2 — else can run multiple lines too. ```tinkerpy if i1 == ON: o1 = pwm(100) else: o1 = 0 o2 = pwm(100) ``` Example 3 — else is the fallback when no earlier condition matched. ```tinkerpy if i1 == ON: o1 = pwm(100) elif i2 == ON: o1 = pwm(50) else: o1 = 0 ``` ### Loop repeat(count): Runs the indented lines below a fixed number of times. | | | |---------|--------------------------------------------------| | `count` | How many times to repeat (a number, up to 1000). | Example 1 — Blinks o1 three times. ```tinkerpy repeat(3): o1 = pwm(100) wait(200) o1 = 0 wait(200) ``` Example 2 — Counts up to 10 using a variable. ```tinkerpy count = 0 repeat(10): count = count + 1 o1 = count ``` Example 3 — Loops can be nested inside each other. ```tinkerpy repeat(5): repeat(2): o1 = pwm(100) wait(100) ``` for \ in range(count): Like repeat, but also gives you a counter you can use inside the loop. | | | |---------|--------------------------------------| | `name` | What to call the counter (e.g. i). | | `count` | How many times to loop (up to 1000). | Example 1 — Ramps o1 through 0, 20, 40, 60, 80. ```tinkerpy for i in range(5): o1 = i * 20 ``` Example 2 — Adds up 0 through 9 using the loop counter. ```tinkerpy count = 0 for i in range(10): count = count + i o1 = count ``` Example 3 — Works like repeat, but you also get a counter (i) if you need it. ```tinkerpy for i in range(3): o1 = pwm(100) wait(300) o1 = 0 wait(300) ``` while condition: Firmware: 2.15+ Repeats the indented lines again and again, as long as the condition is true. Needs firmware 2.15+. | | | |-------------|-----------------------------------------------------------| | `condition` | Checked before every round, e.g. i1 == ON or count \< 10. | Example 1 — Keeps the light on while the button is held, then turns it off. ```tinkerpy while i1 == ON: o1 = ON wait(100) o1 = OFF ``` Example 2 — Counts 1 to 5 on the display, then moves on. ```tinkerpy count = 0 while count < 5: count = count + 1 oled_write(1, left, small, regular, count) wait(500) ``` Example 3 — Drives forward until something is closer than 20 cm, then stops. ```tinkerpy while distance() > 20: robot_control("F", 60, "F", 60) robot_control("S", 0, "S", 0) ``` break Firmware: 2.15+ Leaves the loop it is in (while, repeat or for) straight away. Needs firmware 2.15+. Example 1 — Blinks up to 100 times, but a button press stops it early. ```tinkerpy repeat(100): o1 = ON wait(100) o1 = OFF wait(100) if i1 == ON: break ``` Example 2 — Stops counting at 7 and shows it. ```tinkerpy n = 0 while n < 1000: n = n + 1 if n == 7: break oled_write(1, left, small, regular, n) ``` Example 3 — Brightens step by step until the app sends S. ```tinkerpy for i in range(10): if bluetooth_read_char() == 'S': break o1 = i * 10 wait(300) ``` ### Arithmetic and Logic random(smallest, biggest) Firmware: 2.15+ Gives a surprise whole number between the two numbers (both included). Needs firmware 2.15+. | | | |------------|------------------------------------------| | `smallest` | The smallest number it can give, e.g. 1. | | `biggest` | The biggest number it can give, e.g. 6. | Example 1 — An electronic dice: press the button to roll 1 to 6. ```tinkerpy if i1 == ON: dice = random(1, 6) oled_write(1, left, small, regular, dice) wait(500) ``` Example 2 — A flickering candle: a new random brightness every 0.2 s. ```tinkerpy o1 = pwm(random(10, 100)) wait(200) ``` Example 3 — A reaction game: the light comes on after a surprise wait of 1 to 5 seconds. ```tinkerpy wait(random(1000, 5000)) o1 = ON ``` a + b, a - b, a \* b, a / b, a % b The five math operators — combine numbers and variables just like a calculator. Example 1 — Addition: a becomes 8. ```tinkerpy a = 5 + 3 o1 = a ``` Example 2 — Subtraction: a becomes 7. ```tinkerpy a = 10 - 3 o1 = a ``` Example 3 — Multiplication: a becomes 8. ```tinkerpy a = 4 * 2 o1 = a ``` Example 4 — Division: a becomes 4 — TinkerPy drops any remainder, so it’s always a whole number. ```tinkerpy a = 9 / 2 o1 = a ``` Example 5 — Remainder (modulo): a becomes 1 — what’s left over after dividing 9 by 2. ```tinkerpy a = 9 % 2 o1 = a ``` a == b, a != b, a \< b, a \> b, a \<= b, a \>= b Compares two values and gives a true/false answer — used inside if/elif to decide what runs. Example 1 — Equal to — true when i1 is pressed. ```tinkerpy if i1 == ON: o1 = pwm(100) ``` Example 2 — Not equal to — true whenever i1 is NOT pressed. ```tinkerpy if i1 != ON: o1 = OFF ``` Example 3 — Less than. ```tinkerpy count = 3 if count < 5: o1 = pwm(100) ``` Example 4 — Greater than. ```tinkerpy count = 8 if count > 5: o1 = pwm(100) ``` Example 5 — Greater than OR equal to — true at exactly 5, and above. ```tinkerpy count = 5 if count >= 5: o1 = pwm(100) ``` a and b, a or b, not a Combines two conditions into one, or flips a condition around — for when a single comparison isn’t enough. Example 1 — and: true only when BOTH conditions are true. ```tinkerpy if i1 == ON and i2 == ON: o1 = pwm(100) ``` Example 2 — or: true when AT LEAST ONE condition is true. ```tinkerpy if i1 == ON or i2 == ON: o1 = pwm(100) ``` Example 3 — not: flips true to false and false to true. ```tinkerpy if not i1 == ON: o1 = pwm(100) ``` Example 4 — Combining and + not: on only when i1 is pressed but i2 is NOT. ```tinkerpy if i1 == ON and not i2 == ON: o1 = pwm(100) ``` ### General Code wait(milliseconds) Pauses the program for a moment before continuing. | | | |----------------|--------------------| | `milliseconds` | 1000 = one second. A number from 0 to 65535 (about 65 seconds); for longer, put the wait inside a `repeat`. | Example 1 — Turns o1 on for half a second, then off. ```tinkerpy o1 = pwm(100) wait(500) o1 = 0 ``` Example 2 — A short wait makes a fast blink. ```tinkerpy repeat(5): o1 = pwm(100) wait(100) o1 = 0 wait(100) ``` Example 3 — Waits 2 seconds before doing anything. ```tinkerpy wait(2000) o1 = pwm(100) ``` wifi("network", "password") Lets your TinkerKit connect to a second WiFi network besides the default one. | | | |------------|------------------------------------------| | `network` | The WiFi network name (SSID), in quotes. | | `password` | The WiFi password, in quotes. | Example 1 — Connects to your home WiFi, then runs the rest of the code as normal. ```tinkerpy setup: wifi("HomeNetwork", "mypassword123") loop: o1 = pwm(100) ``` Example 2 — A second network for using the TinkerKit somewhere other than school. ```tinkerpy setup: wifi("Classroom-2A", "school2024") ``` Example 3 — Works with a phone hotspot too. ```tinkerpy setup: wifi("MyPhoneHotspot", "hotspot99") loop: if i1 == ON: o1 = pwm(100) ``` ### Analog Input Two ways to read an analog sensor (LDR, knob, soil sensor) on i1–i4: `analog_read` gives 0 – 100, `voltage` gives volts 0.00 – 3.30. Compile swaps one for the other when the numbers say so: `if analog_read(i1) < 1.3:` becomes `if voltage(i1) < 1.3:`, `if voltage(i1) < 40:` becomes `if analog_read(i1) < 40:`. analog_read(input) Firmware: 2.15+ Reads how much voltage is on an input pin, as 0 to 100 — for a light sensor, a knob or a soil sensor. Set the pin as adc in setup:. | | | |---------|------------------------------------------------------------------| | `input` | i1, i2, i3 or i4. That pin is then not used as an ON/OFF button. | Example 1 — A night lamp: an LDR on i1 turns the light on when it gets dark. ```tinkerpy light = analog_read(i1) if light < 30: o1 = ON else: o1 = OFF ``` Example 2 — A dimmer: turn the knob (potentiometer) on i2 to set the LED brightness. ```tinkerpy o1 = pwm(analog_read(i2)) ``` Example 3 — Shows the soil moisture and runs the pump on o2 when it is dry. ```tinkerpy soil = analog_read(i1) oled_write(1, left, small, regular, soil) if soil < 40: o2 = ON ``` voltage(input) Firmware: 2.24+ The volts on an input pin, 0.00 to 3.30. Compare it with decimals like `1.6` (the only place decimals are allowed); it shows as `1.62` on the OLED / LCD, in Bluetooth / IoT / wireless messages and in joined text. `pwm(voltage(i1))` treats 3.3 V as 100 %. Set the pin with `i1 = set_function(adc)` in `setup:`. | | | |---------|------------------------------------------------------------------| | `input` | i1, i2, i3 or i4. That pin is then not used as an ON/OFF button. | Example 1 — o1 comes on above 1.6 volts. ```tinkerpy setup: i1 = set_function(adc) loop: v = voltage(i1) if v > 1.6: o1 = ON else: o1 = OFF ``` Example 2 — Shows "Volts: 1.62" on the OLED. ```tinkerpy v = voltage(i1) oled_write(1, left, small, regular, "Volts: " + v) ``` Example 3 — A dimmer in volts: 3.3 V is full brightness. ```tinkerpy o1 = pwm(voltage(i2)) ``` ### Servo Function servo_write_angle(output, angle) Needs: `import servo` Sets an output to a servo angle from 0–180°. | | | |----------|-------------------------------------------------------| | `output` | An output pin, e.g. o1. | | `angle` | 0–180. Out-of-range values are clamped automatically. | Example 1 — Points the servo to the middle. ```tinkerpy servo_write_angle(o1, 90) ``` Example 2 — Moves from one end to the other. ```tinkerpy servo_write_angle(o1, 0) wait(500) servo_write_angle(o1, 180) ``` Example 3 — A button controls the servo position. ```tinkerpy if i1 == ON: servo_write_angle(o1, 180) else: servo_write_angle(o1, 0) ``` servo_increment(output, step, max_angle, step_delay) Needs: `import servo` Increases an output value once, by a fixed step — never past max_angle. | | | |--------------|--------------------------------------------------------------| | `output` | An output pin, e.g. o1. | | `step` | How much to increase by. | | `max_angle` | Won’t go above this, even if the step would push it further. | | `step_delay` | How long the move takes, in milliseconds. | Example 1 — Raises o1 by 10, taking 200ms, capped at 180. ```tinkerpy servo_increment(o1, 10, 180, 200) ``` Example 2 — Ramps up in steps of 20, but stops climbing once it hits 100 — even if called again. ```tinkerpy repeat(5): servo_increment(o1, 20, 100, 100) ``` Example 3 — Nudges the value up a little every press, capped at 90. ```tinkerpy if i1 == ON: servo_increment(o1, 5, 90, 50) ``` servo_decrement(output, step, min_angle, step_delay) Needs: `import servo` Decreases an output value once, by a fixed step — never below min_angle. | | | |--------------|--------------------------------------------------------------| | `output` | An output pin, e.g. o1. | | `step` | How much to decrease by. | | `min_angle` | Won’t go below this, even if the step would push it further. | | `step_delay` | How long the move takes, in milliseconds. | Example 1 — Lowers o1 by 10, taking 200ms, capped at 0. ```tinkerpy servo_decrement(o1, 10, 0, 200) ``` Example 2 — Ramps down in steps of 20, but stops descending once it hits 20. ```tinkerpy repeat(5): servo_decrement(o1, 20, 20, 100) ``` Example 3 — A second button nudges the value back down, capped at 10. ```tinkerpy if i2 == ON: servo_decrement(o1, 5, 10, 50) ``` servo_increment_till(output, start_angle, end_angle, step, step_delay) Needs: `import servo` Jumps to start_angle, then climbs step by step up to end_angle. | | | |---------------|-------------------------------------------------------------------| | `output` | An output pin, e.g. o1. | | `start_angle` | Where it begins — set immediately, before the climb starts. | | `end_angle` | Where it stops. If this isn’t above start_angle, nothing happens. | | `step` | How much to increase by each move. | | `step_delay` | Milliseconds to pause between steps. | Example 1 — Starts at 0, climbs to 100, 5 at a time. ```tinkerpy servo_increment_till(o1, 0, 100, 5, 50) ``` Example 2 — Sweeps a servo smoothly from 0° up to 180°. ```tinkerpy servo_increment_till(o1, 0, 180, 10, 30) ``` Example 3 — Only climbs while the button is held, always starting from 20. ```tinkerpy if i1 == ON: servo_increment_till(o1, 20, 100, 10, 20) ``` servo_decrement_till(output, start_angle, end_angle, step, step_delay) Needs: `import servo` Jumps to start_angle, then descends step by step down to end_angle. | | | |---------------|-------------------------------------------------------------------| | `output` | An output pin, e.g. o1. | | `start_angle` | Where it begins — set immediately, before the descent starts. | | `end_angle` | Where it stops. If this isn’t below start_angle, nothing happens. | | `step` | How much to decrease by each move. | | `step_delay` | Milliseconds to pause between steps. | Example 1 — Starts at 100, descends to 0, 5 at a time. ```tinkerpy servo_decrement_till(o1, 100, 0, 5, 50) ``` Example 2 — Sweeps a servo smoothly from 180° back down to 0°. ```tinkerpy servo_decrement_till(o1, 180, 0, 10, 30) ``` Example 3 — Only descends while a second button is held, always starting from 100. ```tinkerpy if i2 == ON: servo_decrement_till(o1, 100, 20, 10, 20) ``` servo_oscillate(output, home_angle, angle_a, angle_b, step, step_delay) Needs: `import servo` Sweeps an output back and forth between two points, once, then returns to where it started. | | | |--------------|------------------------------------------------------------------------------| | `output` | An output pin, e.g. o1. | | `home_angle` | Where the sweep BOTH begins and ends — the servo returns here when finished. | | `angle_a` | It first sweeps to this angle… | | `angle_b` | …then to this one, and then back home. | | `step` | How much the value changes each move. | | `step_delay` | Milliseconds to pause between steps. | Example 1 — Sweeps a servo from 0° to 180° and back, like a radar scanner — starts and ends at 0°. ```tinkerpy servo_oscillate(o1, 0, 0, 180, 5, 20) ``` Example 2 — A smaller, repeated sweep between 60° and 120°, but each time it returns to rest at 90° before sweeping again. ```tinkerpy repeat(3): servo_oscillate(o1, 90, 60, 120, 5, 20) ``` Example 3 — Only sweeps while the button is pressed, then rests back at 0°. ```tinkerpy if i1 == ON: servo_oscillate(o1, 0, 0, 180, 10, 10) ``` servo_flip(output, start_angle, end_angle, step, step_delay) Needs: `import servo` · Firmware: 2.14+ Each new press moves the servo the other way: start → end, then end → start. While the condition stays true it stays where it is. Needs firmware 2.14+. | | | |---------------|-------------------------------------------------------------------------| | `output` | An output pin with a servo, e.g. o1. | | `start_angle` | Where it rests at power-on, and where it returns on every second press. | | `end_angle` | Where the first press moves it to. | | `step` | Degrees per move — bigger is faster. | | `step_delay` | Milliseconds to pause between steps. | Example 1 — A gate: press once to open (0° → 90°), press again to close. Holding the button does not move it again. ```tinkerpy if i1 == ON: servo_flip(o1, 0, 90, 5, 20) ``` Example 2 — A hand waved near the sensor opens the lid; the next wave closes it. ```tinkerpy if distance() < 10: servo_flip(o2, 0, 180, 10, 15) ``` Example 3 — Each D from the app opens or closes the door. ```tinkerpy if bluetooth_read_char() == 'D': servo_flip(o1, 20, 160, 10, 10) ``` servo_scan_on(output, start_angle, end_angle, step, step_delay) Needs: `import servo` Starts a servo sweeping back and forth forever, on its own — once started it keeps sweeping in the background, even while the rest of the code is busy or inside a wait(). | | | |---------------|-----------------------------------------------------------------| | `output` | An output pin, e.g. o1. | | `start_angle` | One end of the sweep. | | `end_angle` | The other end of the sweep. | | `step` | How much the angle changes each move. | | `step_delay` | Milliseconds to pause between steps — controls the sweep speed. | Example 1 — Sweeps continuously between 0° and 180° like a radar dish — bounces back and forth forever, on its own. ```tinkerpy setup: servo_scan_on(o1, 0, 180, 5, 20) ``` Example 2 — The scan keeps sweeping the WHOLE 3 seconds this wait(3000) is running — it never pauses for the rest of the code, and the rest of the code never waits for it either. ```tinkerpy setup: servo_scan_on(o1, 0, 180, 5, 20) loop: wait(3000) o2 = pwm(100) ``` Example 3 — Starts the sweep the moment the button is pressed — once started, it keeps going even after the button is released (use servo_scan_stop(...) to actually stop it). ```tinkerpy if i1 == ON: servo_scan_on(o1, 0, 180, 5, 20) ``` Example 4 — Two servos can scan independently at once, each at its own angle range and speed. ```tinkerpy setup: servo_scan_on(o1, 0, 180, 5, 20) servo_scan_on(o2, 30, 150, 10, 15) ``` servo_scan_stop(output) Needs: `import servo` Freezes a servo_scan_on(...) sweep exactly where it currently is — the servo stops moving, but remembers its position and direction. | | | |----------|-----------------------------------------------------------------------------------------------------| | `output` | The output pin whose scan should freeze, e.g. o1 — must already be scanning via servo_scan_on(...). | Example 1 — Freezes the scan on o1 the instant the button is pressed, wherever it happened to be mid-sweep. ```tinkerpy if i1 == ON: servo_scan_stop(o1) ``` Example 2 — Lets the servo scan for 2 seconds, then freezes it in place — it stays exactly where it stopped, not jumping back to 0. ```tinkerpy setup: servo_scan_on(o1, 0, 180, 5, 20) loop: wait(2000) servo_scan_stop(o1) ``` Example 3 — Freezes the sweep as soon as something gets close, e.g. to avoid hitting an obstacle mid-scan. ```tinkerpy if distance() < 10: servo_scan_stop(o1) ``` servo_scan_resume(output) Needs: `import servo` Continues a servo_scan_on(...) sweep that was frozen with servo_scan_stop(...) — picks up from the exact angle and direction it stopped at, not from the beginning. | | | |----------|-----------------------------------------------------------------------------------------------------------------| | `output` | The output pin whose scan should continue, e.g. o1 — a no-op if that pin was never scanning in the first place. | Example 1 — Holding the button freezes the sweep; releasing it lets the sweep continue right from where it paused. ```tinkerpy if i1 == ON: servo_scan_stop(o1) else: servo_scan_resume(o1) ``` Example 2 — Scans for 2 seconds, pauses for 2 seconds, then picks the same sweep back up — never restarting from 0. ```tinkerpy setup: servo_scan_on(o1, 0, 180, 5, 20) loop: wait(2000) servo_scan_stop(o1) wait(2000) servo_scan_resume(o1) ``` Example 3 — A second button specifically resumes o2’s own scan, independent of whatever o1 is doing. ```tinkerpy if i2 == ON: servo_scan_resume(o2) ``` servo_read_angle(output) Needs: `import servo` Reads a servo’s CURRENT angle (0–180) — whatever it actually is right now, however it got there: a plain angle set with servo_angle(...), still mid-way through an increment/decrement/oscillate, or a servo_scan_on(...) sweep that’s either actively running or frozen with servo_scan_stop(...). | | | |----------|------------------------------------------| | `output` | The output pin the servo is on, e.g. o1. | Example 1 — Stores the servo’s current angle in a variable. ```tinkerpy a = servo_read_angle(o1) ``` Example 2 — Turns on a light only while the servo is past the halfway point. ```tinkerpy if servo_read_angle(o1) > 90: o2 = ON else: o2 = OFF ``` Example 3 — Scans for 2 seconds, freezes the sweep, then reads exactly where it stopped. ```tinkerpy setup: servo_scan_on(o1, 0, 180, 5, 20) loop: wait(2000) servo_scan_stop(o1) a = servo_read_angle(o1) ``` servo_sync(output_a, output_b) Needs: `import servo` Links two servos so they always move together — from this point on, ANY way either one’s angle changes (servo_angle(...), increment/decrement/oscillate, or a servo_scan_on(...) sweep) is mirrored onto the other automatically. Immediately matches the second pin to the first’s current angle when called. | | | |------------|---------------------------------------------------------------------------| | `output_a` | The first servo’s output pin, e.g. o1. | | `output_b` | The second servo’s output pin, e.g. o2 — must be different from output_a. | Example 1 — Both o1 and o2 move to 90° — setting either one from here on moves both. ```tinkerpy setup: servo_sync(o1, o2) loop: o1 = servo_angle(90) ``` Example 2 — o2 sweeps in perfect lockstep with o1’s scan, with no scan of its own needed. ```tinkerpy setup: servo_sync(o1, o2) servo_scan_on(o1, 0, 180, 5, 20) ``` Example 3 — Links the two servos together only once the button has been pressed. ```tinkerpy if i1 == ON: servo_sync(o1, o2) ``` servo_sync_reverse(output_a, output_b) Needs: `import servo` Links two servos to always move OPPOSITE each other — the second pin’s angle is kept at exactly 180 minus the first’s, through any of the same mechanisms servo_sync(...) covers (a direct set, increment/decrement/oscillate, or a scan). Useful for a pair like left/right legs or symmetric arms that should mirror in opposite directions. | | | |------------|---------------------------------------------------------------------------| | `output_a` | The first servo’s output pin, e.g. o1. | | `output_b` | The second servo’s output pin, e.g. o2 — must be different from output_a. | Example 1 — o1 moves to 30° while o2 automatically moves to 150°. ```tinkerpy setup: servo_sync_reverse(o1, o2) loop: o1 = servo_angle(30) ``` Example 2 — o2 sweeps the mirror-image range (60–90–120’s opposite) as o1 oscillates. ```tinkerpy setup: servo_sync_reverse(o1, o2) loop: servo_oscillate(o1, 90, 60, 120, 5, 20) ``` Example 3 — Links the two servos to move opposite each other only once the button has been pressed. ```tinkerpy if i1 == ON: servo_sync_reverse(o1, o2) ``` ### Output Function \ = \ Sets a PWM output to a value from 0–100. | | | |----------|-----------------------------------------------------------------------| | `output` | An output pin, e.g. o1, or an alias for one. | | `value` | 0–100 (percent power). Out-of-range values are clamped automatically. | Example 1 — Full power to o1. ```tinkerpy o1 = pwm(100) ``` Example 2 — Half power — good for dimming an LED. ```tinkerpy o1 = pwm(50) ``` Example 3 — You can assign a variable’s value too, not just a number. ```tinkerpy count = 75 o1 = count ``` \ = invert(\) The opposite ON / OFF of a digital pin: ON when that pin is OFF, OFF when it is ON. Digital pins only — not a pwm(), servo, buzzer, RGB or analog pin (the compiler refuses those). Reading an output (`invert(o2)`) needs board firmware 2.26; an input follows its wiring (active_low / active_high). For a variable, use `not x` instead. | | | |-------|---------------------------------------------------------------------| | `pin` | A digital pin or its name: an output like o2, or an input like i1. | Example 1 — o1 is always the opposite of o2 — one LED on, the other off. ```tinkerpy o1 = invert(o2) ``` Example 2 — The LED is ON until the button is pressed, then OFF. ```tinkerpy o1 = invert(i1) ``` output_increment(output, step, max_value, step_delay) Increases a general output value once, by a fixed step — never past max_value. | | | |--------------|----------------------------------------------------------------------| | `output` | An output pin, e.g. o1. | | `step` | How much to increase by. | | `max_value` | Won’t go above this, even if the step would push it further (0–100). | | `step_delay` | How long the move takes, in milliseconds. | Example 1 — Raises o1 by 10, taking 200ms, capped at 100. ```tinkerpy output_increment(o1, 10, 100, 200) ``` Example 2 — Ramps up in steps of 20, but stops climbing once it hits 80 — even if called again. ```tinkerpy repeat(5): output_increment(o1, 20, 80, 100) ``` Example 3 — Nudges the value up a little every press, capped at 90. ```tinkerpy if i1 == ON: output_increment(o1, 5, 90, 50) ``` output_decrement(output, step, min_value, step_delay) Decreases a general output value once, by a fixed step — never below min_value. | | | |--------------|----------------------------------------------------------------------| | `output` | An output pin, e.g. o1. | | `step` | How much to decrease by. | | `min_value` | Won’t go below this, even if the step would push it further (0–100). | | `step_delay` | How long the move takes, in milliseconds. | Example 1 — Lowers o1 by 10, taking 200ms, capped at 0. ```tinkerpy output_decrement(o1, 10, 0, 200) ``` Example 2 — Ramps down in steps of 20, but stops descending once it hits 20. ```tinkerpy repeat(5): output_decrement(o1, 20, 20, 100) ``` Example 3 — A second button nudges the value back down, capped at 10. ```tinkerpy if i2 == ON: output_decrement(o1, 5, 10, 50) ``` output_increment_till(output, start_value, end_value, step, step_delay) Jumps to start_value, then climbs step by step up to end_value. | | | |---------------|---------------------------------------------------------------------| | `output` | An output pin, e.g. o1. | | `start_value` | Where it begins — set immediately, before the climb starts (0–100). | | `end_value` | Where it stops. If this isn’t above start_value, nothing happens. | | `step` | How much to increase by each move. | | `step_delay` | Milliseconds to pause between steps. | Example 1 — Starts at 0, climbs to 100, 5 at a time — a smooth fade-in. ```tinkerpy output_increment_till(o1, 0, 100, 5, 50) ``` Example 2 — Ramps a fan or LED from 20% up to 80%. ```tinkerpy output_increment_till(o1, 20, 80, 10, 30) ``` Example 3 — Only climbs while the button is held, always starting from 20. ```tinkerpy if i1 == ON: output_increment_till(o1, 20, 100, 10, 20) ``` output_decrement_till(output, start_value, end_value, step, step_delay) Jumps to start_value, then descends step by step down to end_value. | | | |---------------|-----------------------------------------------------------------------| | `output` | An output pin, e.g. o1. | | `start_value` | Where it begins — set immediately, before the descent starts (0–100). | | `end_value` | Where it stops. If this isn’t below start_value, nothing happens. | | `step` | How much to decrease by each move. | | `step_delay` | Milliseconds to pause between steps. | Example 1 — Starts at 100, descends to 0, 5 at a time — a smooth fade-out. ```tinkerpy output_decrement_till(o1, 100, 0, 5, 50) ``` Example 2 — Ramps a fan or LED down from 80% to 20%. ```tinkerpy output_decrement_till(o1, 80, 20, 10, 30) ``` Example 3 — Only descends while a second button is held, always starting from 100. ```tinkerpy if i2 == ON: output_decrement_till(o1, 100, 20, 10, 20) ``` output_flip(output, off_value, on_value) Flips an output between two values each time this line runs: first on_value, then off_value, then on_value again… | | | |-------------|-----------------------------------------------------------------------| | `output` | An output pin, e.g. o1. | | `off_value` | The “off” value (0–100), e.g. 0. | | `on_value` | The “on” value (0–100), e.g. 100 — used the FIRST time the line runs. | Example 1 — Each time this line runs: 100, then 0, then 100, then 0 — a simple on/off flip. ```tinkerpy output_flip(o1, 0, 100) ``` Example 2 — Alternates between 60 and 20 (starting at 60) each time this line runs. ```tinkerpy output_flip(o1, 20, 60) ``` Example 3 — A button press flips the output between fully off and fully on, alternating with each press. ```tinkerpy if i1 == ON: output_flip(o1, 0, 100) ``` ### Ultrasonic Function distance() Needs: `import ultrasonic` Reads the ultrasonic sensor’s distance in cm. Its pins are fixed (i3/i4 on TinkerPy Mega, i1/i2 on Mini), so no pin is needed. Example 1 — Turns o1 on when something is closer than 10cm. ```tinkerpy d = distance() if d < 10: o1 = pwm(100) ``` Example 2 — Stores the distance in a variable to use later. ```tinkerpy d = distance() count = d o1 = pwm(100) ``` Example 3 — You can call distance() directly inside a condition too. ```tinkerpy if distance() > 50: o1 = 0 else: o1 = pwm(100) ``` ### DHT11 Function dht_temperature(input) Needs: `import dht11` Reads the DHT11 sensor’s temperature in °C. | | | |---------|---------------------------------------------| | `input` | Which input the DHT11 is wired to, e.g. i3. | Example 1 — Stores the current temperature in a variable. ```tinkerpy t = dht_temperature(i3) ``` Example 2 — Turns on a fan (o1) when it’s hot. ```tinkerpy if dht_temperature(i3) > 30: o1 = pwm(100) ``` Example 3 — Turns on a heater (o2) when it’s cold. ```tinkerpy t = dht_temperature(i3) if t < 15: o2 = pwm(100) ``` dht_humidity(input) Needs: `import dht11` Reads the DHT11 sensor’s humidity in %. | | | |---------|----------------------------------------------------------------------| | `input` | Which input the DHT11 is wired to — the same one as dht_temperature. | Example 1 — Stores the current humidity in a variable. ```tinkerpy h = dht_humidity(i3) ``` Example 2 — Turns something on when it’s very humid. ```tinkerpy if dht_humidity(i3) > 70: o1 = pwm(100) ``` Example 3 — Turns something on when the air is too dry. ```tinkerpy h = dht_humidity(i3) if h < 30: o2 = pwm(100) ``` ### MPU6050 Function tilt_x() Needs: `import mpu6050` How much the front edge (the X arrow on the sensor) is tilted: up = +, down = −, from −90 to 90 degrees. Example 1 — Shows the front/back tilt on the display. ```tinkerpy t = tilt_x() oled_write(1, left, small, regular, t) ``` Example 2 — Turns o1 on while the front is tipped down. ```tinkerpy if tilt_x() < -20: o1 = ON else: o1 = OFF ``` Example 3 — Sends a message when a lid is lifted past 45°. ```tinkerpy if tilt_x() > 45: iot_write("Lid is open") ``` tilt_y() Needs: `import mpu6050` How much it leans sideways: right side down = +, left side down = −, from −90 to 90 degrees. Example 1 — Turns o2 on when it leans to the right. ```tinkerpy if tilt_y() > 20: o2 = ON else: o2 = OFF ``` Example 2 — Shows the sideways tilt on line 2. ```tinkerpy t = tilt_y() oled_write(2, left, small, regular, t) ``` Example 3 — A "not level" warning light. ```tinkerpy if tilt_y() < -20 or tilt_y() > 20: o1 = ON ``` tilt_direction() Needs: `import mpu6050` Which way it is tipped: 'F' forward (front down), 'B' back, 'L' left, 'R' right, or 'N' flat (less than 15°). Example 1 — A gesture remote: tip forward to drive, hold flat to stop. ```tinkerpy d = tilt_direction() if d == 'F': robot_control("F", 80, "F", 80) elif d == 'N': robot_control("S", 0, "S", 0) ``` Example 2 — Lights o1 while tipped to the left. ```tinkerpy if tilt_direction() == 'L': o1 = ON else: o1 = OFF ``` Example 3 — Shows "Level!" when it lies flat. ```tinkerpy if tilt_direction() == 'N': oled_write(1, left, small, regular, "Level!") ``` shake_detected() Needs: `import mpu6050` 1 once after the sensor is shaken, then 0 until the next shake. Example 1 — Flashes a light when you shake it. ```tinkerpy if shake_detected() == 1: o1 = ON wait(1000) o1 = OFF ``` Example 2 — Counts the shakes. ```tinkerpy if shake_detected() == 1: c1.increment() oled_write(1, left, small, regular, c1) ``` Example 3 — Tells the app when it is shaken. ```tinkerpy if shake_detected() == 1: iot_write("Shaken!") ``` motion_level() Needs: `import mpu6050` How much it is moving right now, from 0 (still) to 100 (lots of movement). Example 1 — An anti-theft alarm: o1 goes on when the box is moved. ```tinkerpy if motion_level() > 30: o1 = ON else: o1 = OFF ``` Example 2 — Shows the movement level live. ```tinkerpy oled_write(1, left, small, regular, motion_level()) ``` Example 3 — The more it moves, the brighter o1 glows. ```tinkerpy o1 = motion_level() ``` fall_detected() Needs: `import mpu6050` 1 once after the sensor falls (free fall), then 0. Example 1 — A fall alarm that also sends a message. ```tinkerpy if fall_detected() == 1: o1 = ON iot_write("Fall detected!") ``` Example 2 — Shows a message after a drop. ```tinkerpy if fall_detected() == 1: oled_write(1, left, small, regular, "Oops! I fell") ``` Example 3 — Counts how many times it was dropped. ```tinkerpy if fall_detected() == 1: c1.increment() ``` turn_angle() Needs: `import mpu6050` Degrees it has turned (spun flat, like a robot turning) since reset_turn(): right = +, left = −. It slowly drifts — reset it before each turn. Example 1 — Turns the robot right until it has turned 90°. ```tinkerpy setup: reset_turn() loop: robot_control("F", 60, "B", 60) repeat(300): if turn_angle() >= 90: robot_control("S", 0, "S", 0) wait(10) ``` Example 2 — Shows how far it has turned. ```tinkerpy oled_write(1, left, small, regular, turn_angle()) ``` Example 3 — Lights o1 after turning 45° to the left. ```tinkerpy if turn_angle() < -45: o1 = ON ``` reset_turn() Needs: `import mpu6050` Sets turn_angle() back to 0 — call it just before a turn. Example 1 — Start counting the turn from here. ```tinkerpy setup: reset_turn() ``` Example 2 — A button sets the turn angle back to 0. ```tinkerpy if i1 == ON: reset_turn() ``` Example 3 — Shows how much it turned in 2 seconds. ```tinkerpy setup: reset_turn() loop: wait(2000) oled_write(1, left, small, regular, turn_angle()) ``` step_count() Needs: `import mpu6050` How many steps were counted (carry the sensor while walking) since reset_steps(). Example 1 — A simple pedometer. ```tinkerpy oled_write(1, left, small, regular, step_count()) ``` Example 2 — Lights o1 after 100 steps. ```tinkerpy if step_count() >= 100: o1 = ON ``` Example 3 — Sends a message at 1000 steps. ```tinkerpy if step_count() >= 1000: iot_write("1000 steps!") ``` reset_steps() Needs: `import mpu6050` Sets step_count() back to 0. Example 1 — Start counting steps from 0. ```tinkerpy setup: reset_steps() ``` Example 2 — A button resets the step counter. ```tinkerpy if i1 == ON: reset_steps() ``` Example 3 — Lights o1 every 50 steps. ```tinkerpy if step_count() >= 50: o1 = ON reset_steps() ``` accel_x() Needs: `import mpu6050` Raw acceleration along X in 1/100 g (100 = gravity). For older students. Example 1 — Shows the X acceleration. ```tinkerpy oled_write(1, left, small, regular, accel_x()) ``` Example 2 — On when the X axis points well upwards. ```tinkerpy a = accel_x() if a > 50: o1 = ON ``` Example 3 — Use it with the display while testing. ```tinkerpy iot_write("x") oled_write(2, left, small, regular, accel_x()) ``` accel_y() Needs: `import mpu6050` Raw acceleration along Y in 1/100 g (100 = gravity). Example 1 — Shows the Y acceleration. ```tinkerpy oled_write(2, left, small, regular, accel_y()) ``` Example 2 — On when the Y axis points well downwards. ```tinkerpy if accel_y() < -50: o1 = ON ``` Example 3 — Stores it in a variable first. ```tinkerpy a = accel_y() oled_write(1, left, small, regular, a) ``` accel_z() Needs: `import mpu6050` Raw acceleration along Z in 1/100 g — about 100 when lying flat, about −100 upside down. Example 1 — On when the sensor is upside down. ```tinkerpy if accel_z() < 0: o1 = ON ``` Example 2 — Shows the Z acceleration. ```tinkerpy oled_write(3, left, small, regular, accel_z()) ``` Example 3 — Says "Flat" when it lies level. ```tinkerpy if accel_z() > 90: oled_write(1, left, small, regular, "Flat") ``` gyro_x() Needs: `import mpu6050` How fast it rotates around X, in degrees per second. Example 1 — Shows the rotation speed around X. ```tinkerpy oled_write(1, left, small, regular, gyro_x()) ``` Example 2 — On while it is flipped forward quickly. ```tinkerpy if gyro_x() > 100: o1 = ON ``` Example 3 — Stores it in a variable first. ```tinkerpy g = gyro_x() oled_write(2, left, small, regular, g) ``` gyro_y() Needs: `import mpu6050` How fast it rotates around Y, in degrees per second. Example 1 — Shows the rotation speed around Y. ```tinkerpy oled_write(1, left, small, regular, gyro_y()) ``` Example 2 — On while it is rolled quickly to one side. ```tinkerpy if gyro_y() < -100: o1 = ON ``` Example 3 — Stores it in a variable first. ```tinkerpy g = gyro_y() oled_write(2, left, small, regular, g) ``` gyro_z() Needs: `import mpu6050` How fast it spins flat (around Z), in degrees per second. Example 1 — On while it is spun quickly. ```tinkerpy if gyro_z() > 100: o1 = ON else: o1 = OFF ``` Example 2 — Shows the spin speed. ```tinkerpy oled_write(1, left, small, regular, gyro_z()) ``` Example 3 — Tells the app when it spins fast either way. ```tinkerpy if gyro_z() > 200 or gyro_z() < -200: iot_write("Spinning!") ``` mpu_temperature() Needs: `import mpu6050` The temperature of the MPU6050 chip in °C (a little warmer than the room). Example 1 — Shows the chip temperature. ```tinkerpy oled_write(1, left, small, regular, mpu_temperature()) ``` Example 2 — A "too warm" light. ```tinkerpy if mpu_temperature() > 40: o1 = ON ``` Example 3 — Stores it in a variable first. ```tinkerpy t = mpu_temperature() oled_write(2, left, small, regular, t) ``` ### RTC Clock Function A real-time clock module (any DS3231 or DS1307) on o7 (SDA) / o8 (SCL). It keeps the time with its own small battery, even when the board is off. Set it once with rtc_set_time / rtc_set_date in setup: — the board sets the clock only when that new code arrives, not at every power-on. Address 0x68 (same as the MPU6050 — use one of them). Use a 3.3 V DS3231 board: “Tiny RTC” DS1307 boards need 5 V and put 5 V on the I2C wires, which the board’s pins can’t take. rtc_hour() Needs: `import rtc` · Firmware: 2.27+ The hour from the RTC clock module, 0 to 23 (2 PM = 14). The module keeps time even when the board is off (it has a small battery). Example 1 — Shows the hour. ```tinkerpy h = rtc_hour() oled_write(1, left, small, regular, h) ``` Example 2 — A light that comes on at 6 PM. ```tinkerpy if rtc_hour() >= 18: o1 = ON else: o1 = OFF ``` Example 3 — A 7:00 alarm. ```tinkerpy if rtc_hour() == 7 and rtc_minute() == 0: buzzer_play(o2, "school_bell") ``` rtc_minute() Needs: `import rtc` · Firmware: 2.27+ The minute from the RTC clock, 0 to 59. Example 1 — Shows the minute. ```tinkerpy oled_write(2, left, small, regular, rtc_minute()) ``` Example 2 — Turns o1 on at half past every hour. ```tinkerpy if rtc_minute() == 30: o1 = ON ``` Example 3 — o2 is on for the first 10 minutes of each hour. ```tinkerpy m = rtc_minute() if m < 10: o2 = ON ``` rtc_second() Needs: `import rtc` · Firmware: 2.27+ The second from the RTC clock, 0 to 59. Example 1 — Shows the seconds ticking. ```tinkerpy oled_write(3, left, small, regular, rtc_second()) ``` Example 2 — Blinks o1 with the clock: on for even seconds. ```tinkerpy if rtc_second() % 2 == 0: o1 = ON else: o1 = OFF ``` Example 3 — A short blink at the start of every minute. ```tinkerpy if rtc_second() == 0: o2 = ON wait(200) o2 = OFF ``` rtc_day() Needs: `import rtc` · Firmware: 2.27+ The day of the month, 1 to 31. Example 1 — Shows the date. ```tinkerpy oled_write(1, left, small, regular, rtc_day()) ``` Example 2 — A first-of-the-month reminder light. ```tinkerpy if rtc_day() == 1: o1 = ON ``` Example 3 — Keeps the day in a variable. ```tinkerpy d = rtc_day() m = rtc_month() oled_write(2, left, small, regular, d) ``` rtc_month() Needs: `import rtc` · Firmware: 2.27+ The month, 1 (January) to 12 (December). Example 1 — Shows the month number. ```tinkerpy oled_write(2, left, small, regular, rtc_month()) ``` Example 2 — Something special on 25 December. ```tinkerpy if rtc_month() == 12 and rtc_day() == 25: rgb_color(o1, all, "red", 80) ``` Example 3 — A summer-holiday light in April and May. ```tinkerpy if rtc_month() >= 4 and rtc_month() <= 5: o1 = ON ``` rtc_year() Needs: `import rtc` · Firmware: 2.27+ The year, like 2026. Example 1 — Shows the year. ```tinkerpy oled_write(3, left, small, regular, rtc_year()) ``` Example 2 — Keeps the year in a variable. ```tinkerpy y = rtc_year() oled_write(1, left, small, regular, y) ``` Example 3 — A hint when the clock was never set. ```tinkerpy if rtc_year() < 2026: oled_write(2, left, small, regular, "Set the clock") ``` rtc_weekday() Needs: `import rtc` · Firmware: 2.27+ The day of the week: 1 Monday, 2 Tuesday … 6 Saturday, 7 Sunday. Example 1 — No school bell on Saturday and Sunday. ```tinkerpy if rtc_weekday() >= 6: o1 = OFF ``` Example 2 — Shows the day number. ```tinkerpy d = rtc_weekday() oled_write(4, left, small, regular, d) ``` Example 3 — Monday morning reminder. ```tinkerpy if rtc_weekday() == 1 and rtc_hour() == 8: o1 = ON ``` rtc_set_time(hour, minute, second) Needs: `import rtc` · Firmware: 2.27+ Sets the RTC clock's time. Put it in setup: — the board sets the clock ONCE when this new code reaches it (not again at every power-on), so the clock keeps running from there. To set it again, change the numbers and upload again. | | | |---|---| | `hour` | 0-23 | | `minute` | 0-59 | | `second` | 0-59 | Example 1 — Sets the clock to 2:05:00 PM once, then shows the minute. ```tinkerpy setup: rtc_set_time(14, 5, 0) loop: oled_write(1, left, small, regular, rtc_minute()) ``` Example 2 — Sets 7:30 in the morning. ```tinkerpy setup: rtc_set_time(7, 30, 0) ``` Example 3 — Midnight, to test the date changing. ```tinkerpy setup: rtc_set_time(0, 0, 0) rtc_set_date(31, 12, 2026) ``` rtc_set_date(day, month, year) Needs: `import rtc` · Firmware: 2.27+ Sets the RTC clock's date, once when the new code reaches the board (like rtc_set_time). The year can be 2026 or 26. | | | |---|---| | `day` | 1-31 | | `month` | 1-12 | | `year` | 2000-2099 (or 0-99) | Example 1 — Sets 16 October 2026 and the time. ```tinkerpy setup: rtc_set_date(16, 10, 2026) rtc_set_time(9, 0, 0) ``` Example 2 — The year can be written as 27. ```tinkerpy setup: rtc_set_date(1, 1, 27) ``` Example 3 — 29 February works in a leap year. ```tinkerpy setup: rtc_set_date(29, 2, 2028) ``` ### Pulse Oximeter Function A pulse oximeter module (any MAX30100 or MAX30102) on o7 / o8, address 0x57. Rest a fingertip gently on it and keep still; the first numbers come after a few seconds. For learning only — not a medical device. A MAX30102 board is the easy choice; green GY-MAX30100 boards pull the I2C wires to 1.8 V and may not work. heart_rate() Needs: `import pulse_oximeter` · Firmware: 2.27+ Heart beats a minute from the finger on the sensor, or 0 when there is no finger (or it is still measuring — it takes a few seconds). For learning only, not for medical use. Example 1 — Shows the heart rate. ```tinkerpy oled_write(1, left, small, regular, heart_rate()) ``` Example 2 — A light when the heart beats fast, e.g. after running. ```tinkerpy if heart_rate() > 100: o1 = ON else: o1 = OFF ``` Example 3 — A slow-heart light (0 means no finger). ```tinkerpy b = heart_rate() if b > 0 and b < 60: o2 = ON ``` spo2() Needs: `import pulse_oximeter` · Firmware: 2.27+ How much oxygen the blood carries, in % (usually 95-100), or 0 when there is no finger. For learning only. Example 1 — Shows the oxygen %. ```tinkerpy oled_write(2, left, small, regular, spo2()) ``` Example 2 — A low-oxygen warning light. ```tinkerpy if finger_detected() == 1 and spo2() < 94: o2 = ON ``` Example 3 — Keeps the oxygen % in a variable. ```tinkerpy s = spo2() oled_write(3, left, small, regular, s) ``` finger_detected() Needs: `import pulse_oximeter` · Firmware: 2.27+ 1 while a finger is on the sensor, else 0. Example 1 — Asks for a finger. ```tinkerpy if finger_detected() == 0: oled_write(1, left, small, regular, "Put a finger on") ``` Example 2 — A light while a finger is on. ```tinkerpy if finger_detected() == 1: o1 = ON else: o1 = OFF ``` Example 3 — Shows the heart rate only with a finger on. ```tinkerpy if finger_detected() == 1: oled_write(1, left, small, regular, heart_rate()) ``` heart_beat() Needs: `import pulse_oximeter` · Firmware: 2.27+ 1 for one loop at every heart beat, else 0 — use it to blink or beep with the heart. Example 1 — Blinks o1 with each beat. ```tinkerpy if heart_beat() == 1: o1 = ON wait(100) o1 = OFF ``` Example 2 — Beeps with each beat. ```tinkerpy if heart_beat() == 1: buzzer_play(o2, "beep") ``` Example 3 — An RGB LED that glows with each beat. ```tinkerpy if heart_beat() == 1: rgb_color(o1, all, "red", 80) else: rgb_color(o1, all, "red", 5) ``` ### BMP280 Function A BMP280 (or BME280) air-pressure module on o7 / o8, address 0x76 or 0x77. pressure() Needs: `import bmp280` · Firmware: 2.27+ The air pressure in hPa (about 1013 at sea level, lower up a hill). Example 1 — Shows the air pressure. ```tinkerpy oled_write(1, left, small, regular, pressure()) ``` Example 2 — A "rain may come" light when the pressure falls. ```tinkerpy if pressure() < 1000: o1 = ON ``` Example 3 — A fine-weather light when the pressure is high. ```tinkerpy p = pressure() if p > 1020: o2 = ON ``` bmp_temperature() Needs: `import bmp280` · Firmware: 2.27+ The temperature from the BMP280 in °C. Example 1 — Shows the temperature. ```tinkerpy oled_write(2, left, small, regular, bmp_temperature()) ``` Example 2 — Switches a fan on when it is hot. ```tinkerpy if bmp_temperature() > 35: o2 = ON else: o2 = OFF ``` Example 3 — Keeps the temperature in a variable. ```tinkerpy t = bmp_temperature() oled_write(3, left, small, regular, t) ``` altitude() Needs: `import bmp280` · Firmware: 2.27+ How high you are above the sea in metres, worked out from the air pressure (it changes a little with the weather). Example 1 — Shows the height above sea level. ```tinkerpy oled_write(3, left, small, regular, altitude()) ``` Example 2 — Lights o1 when carried up 3 metres (a floor of a building). ```tinkerpy start = altitude() if altitude() > start + 3: o1 = ON ``` Example 3 — A light up in the hills. ```tinkerpy if altitude() > 900: o1 = ON ``` ### Laser Distance Function A VL53L0X laser distance (time-of-flight) sensor on o7 / o8, address 0x29: 3 cm to about 2 m, more exact than ultrasonic. 999 = nothing in range. It shares 0x29 with the TCS34725 — use one of them (for colour too, use an APDS-9960). laser_distance() Needs: `import vl53l0x` · Firmware: 2.27+ The distance to the object in front of the laser sensor, in cm (3 to about 200). 999 = nothing in range. More exact than ultrasonic, and works on soft things too. Example 1 — Shows the distance. ```tinkerpy oled_write(1, left, small, regular, laser_distance()) ``` Example 2 — Something close? Light on. ```tinkerpy if laser_distance() < 15: o1 = ON else: o1 = OFF ``` Example 3 — Parking help: o1 (red) on when closer than 30 cm. ```tinkerpy d = laser_distance() if d < 30: o1 = ON o2 = OFF ``` ### Colour Sensor Function A TCS34725 colour sensor (address 0x29) or an APDS-9960 (0x39) on o7 / o8. Hold the colour 1–2 cm from it with its light on. color_name() gives one of: "red" "orange" "yellow" "green" "blue" "purple" "pink" "white" "black". color_name() Needs: `import tcs34725 or import apds9960` · Firmware: 2.27+ The colour in front of the sensor — compare it with a colour name: "red" "orange" "yellow" "green" "blue" "purple" "pink" "white" "black". Example 1 — Lights o1 for red. ```tinkerpy if color_name() == "red": o1 = ON else: o1 = OFF ``` Example 2 — A colour sorter: green one way, blue the other. ```tinkerpy c = color_name() if c == "green": o2 = servo_angle(90) elif c == "blue": o2 = servo_angle(0) ``` Example 3 — A line follower idea: black or not. ```tinkerpy if color_name() == "black": o1 = OFF else: o1 = ON ``` color_red() Needs: `import tcs34725 or import apds9960` · Firmware: 2.27+ How much red the sensor sees, 0-255 (the strongest colour is always 255). Example 1 — Shows the red amount. ```tinkerpy oled_write(1, left, small, regular, color_red()) ``` Example 2 — Copies the colour it sees onto an RGB LED. ```tinkerpy rgb_hex_color(o1, all, color_red(), color_green(), color_blue()) ``` Example 3 — Red seen: lots of red, little green. ```tinkerpy if color_red() == 255 and color_green() < 100: o1 = ON ``` color_green() Needs: `import tcs34725 or import apds9960` · Firmware: 2.27+ How much green the sensor sees, 0-255. Example 1 — Shows the green amount. ```tinkerpy oled_write(2, left, small, regular, color_green()) ``` Example 2 — Green is the strongest colour. ```tinkerpy if color_green() == 255: o2 = ON else: o2 = OFF ``` Example 3 — Keeps it in a variable. ```tinkerpy g = color_green() oled_write(4, left, small, regular, g) ``` color_blue() Needs: `import tcs34725 or import apds9960` · Firmware: 2.27+ How much blue the sensor sees, 0-255. Example 1 — Shows the blue amount. ```tinkerpy oled_write(3, left, small, regular, color_blue()) ``` Example 2 — Lots of blue. ```tinkerpy if color_blue() > 200: o3 = ON ``` Example 3 — Keeps it in a variable. ```tinkerpy b = color_blue() oled_write(4, left, small, regular, b) ``` color_brightness() Needs: `import tcs34725 or import apds9960` · Firmware: 2.27+ How much light comes back to the colour sensor, 0-100 (dark = small). Example 1 — A light when it gets dark (or something black is in front). ```tinkerpy if color_brightness() < 10: o1 = ON ``` Example 2 — Shows the brightness. ```tinkerpy oled_write(1, left, small, regular, color_brightness()) ``` Example 3 — Something white or shiny in front. ```tinkerpy if color_brightness() > 80: o2 = ON ``` ### Gesture Function An APDS-9960 gesture sensor on o7 / o8, address 0x39. Swipe a hand 5–10 cm above it. Each swipe is seen in ONE pass of loop: (then None). It is also a colour sensor (the colour functions above). gesture() Needs: `import apds9960` · Firmware: 2.27+ The hand swipe just made over the sensor: compare it with "up" "down" "left" "right". It gives None when there is no new swipe — each swipe is seen in ONE loop. Example 1 — Swipe left = light on, right = off. ```tinkerpy if gesture() == "left": o1 = ON elif gesture() == "right": o1 = OFF ``` Example 2 — Counts up and down with swipes (import counter). ```tinkerpy g = gesture() if g == "up": c1.increment() elif g == "down": c1.decrement() ``` Example 3 — Swipe up / down to open and close a lid. ```tinkerpy if gesture() == "up": o1 = servo_angle(180) elif gesture() == "down": o1 = servo_angle(0) ``` proximity() Needs: `import apds9960` · Firmware: 2.27+ How near a hand (or object) is to the sensor: 0 far away … 100 very close (about 10 cm range). Example 1 — Shows how near your hand is. ```tinkerpy oled_write(1, left, small, regular, proximity()) ``` Example 2 — A touch-free switch: wave close to turn it on. ```tinkerpy if proximity() > 60: o1 = ON else: o1 = OFF ``` Example 3 — Keeps it in a variable. ```tinkerpy p = proximity() oled_write(2, left, small, regular, p) ``` ### GPS Function A GPS module (NEO-6M or similar, 9600 baud) — its TX wire goes to ANY pin, set in setup: as gps_rx: i1 = set_input(gps_rx) (TinkerPy Code adds the line on Compile, named gps_rx_1). Outdoors it needs about a minute to find satellites. Firmware 2.28. gps_found() Needs: `import gps` · Firmware: 2.28+ 1 when the GPS knows where it is (it has a fix), else 0. Outdoors it takes about a minute after power-on. Example 1 — A light that shows the GPS is ready. ```tinkerpy if gps_found() == 1: o1 = ON else: o1 = OFF ``` Example 2 — Tells you to wait. ```tinkerpy if gps_found() == 0: oled_write(1, left, small, regular, "Searching...") ``` Example 3 — Keeps it in a variable. ```tinkerpy f = gps_found() oled_write(2, left, small, regular, f) ``` gps_satellites() Needs: `import gps` · Firmware: 2.28+ How many satellites the GPS can see (4 or more is good). Example 1 — Shows the satellites. ```tinkerpy oled_write(1, left, small, regular, gps_satellites()) ``` Example 2 — A weak-signal light. ```tinkerpy if gps_satellites() < 4: o2 = ON ``` Example 3 — Sends it to the app (import bluetooth). ```tinkerpy s = gps_satellites() bluetooth_write(s) ``` gps_speed() Needs: `import gps` · Firmware: 2.28+ How fast it is moving, in km/h. Example 1 — A speedometer. ```tinkerpy oled_write(1, left, small, regular, gps_speed()) ``` Example 2 — Beeps when going faster than 40 km/h. ```tinkerpy if gps_speed() > 40: buzzer_play(o2, "beep") ``` Example 3 — A "stopped" light. ```tinkerpy s = gps_speed() if s == 0: o1 = ON ``` gps_altitude() Needs: `import gps` · Firmware: 2.28+ Height above the sea in metres. Example 1 — Shows the height. ```tinkerpy oled_write(2, left, small, regular, gps_altitude()) ``` Example 2 — On high ground. ```tinkerpy if gps_altitude() > 500: o1 = ON ``` Example 3 — Sends it over IoT. ```tinkerpy a = gps_altitude() iot_write(a) ``` gps_hour() Needs: `import gps` · Firmware: 2.28+ The hour from the satellites, in Indian time (0–23). Very exact — no clock to set. Example 1 — Shows the hour. ```tinkerpy oled_write(1, left, small, regular, gps_hour()) ``` Example 2 — A light from 6 PM. ```tinkerpy if gps_hour() >= 18: o1 = ON ``` Example 3 — Keeps the time in variables. ```tinkerpy h = gps_hour() m = gps_minute() oled_write(2, left, small, regular, h) ``` gps_minute() Needs: `import gps` · Firmware: 2.28+ The minute from the satellites, 0–59. Example 1 — Shows the minute. ```tinkerpy oled_write(2, left, small, regular, gps_minute()) ``` Example 2 — A 7:00 alarm. ```tinkerpy if gps_hour() == 7 and gps_minute() == 0: o1 = ON ``` Example 3 — On for the first 5 minutes of each hour. ```tinkerpy m = gps_minute() if m < 5: o2 = ON ``` gps_second() Needs: `import gps` · Firmware: 2.28+ The second from the satellites, 0–59. Example 1 — Shows the seconds. ```tinkerpy oled_write(3, left, small, regular, gps_second()) ``` Example 2 — Blinks with the satellite clock. ```tinkerpy if gps_second() % 2 == 0: o1 = ON else: o1 = OFF ``` Example 3 — Keeps it in a variable. ```tinkerpy s = gps_second() oled_write(4, left, small, regular, s) ``` gps_save_home() Needs: `import gps` · Firmware: 2.28+ Remembers where it is now as "home" (put it in setup:). If the GPS has no fix yet, home is saved as soon as it finds one. Example 1 — Saves home (write it in setup:). ```tinkerpy gps_save_home() ``` Example 2 — Press a button to save a new home. ```tinkerpy if i1 == ON: gps_save_home() ``` Example 3 — Saves home and says so. ```tinkerpy gps_save_home() oled_write(1, left, small, regular, "Home saved") ``` gps_distance_home() Needs: `import gps` · Firmware: 2.28+ How many metres it is from home (gps_save_home()). 0 until home is saved and the GPS has a fix. Example 1 — Shows the distance from home. ```tinkerpy oled_write(1, left, small, regular, gps_distance_home()) ``` Example 2 — A geofence: alarm when it goes more than 100 m away. ```tinkerpy if gps_distance_home() > 100: buzzer_play(o2, "alarm") ``` Example 3 — A "you are home" light. ```tinkerpy d = gps_distance_home() if d < 10: o1 = ON ``` gps_location() Needs: `import gps` · Firmware: 2.28+ Where it is, as text: "12.91416,74.85603" (latitude,longitude — paste it into Google Maps). Empty text (None) until the GPS has a fix. Show it, store it or send it by SMS / Bluetooth / IoT. Example 1 — Shows the position on the OLED. ```tinkerpy oled_write(1, left, small, regular, gps_location()) ``` Example 2 — Sends it to the app (import bluetooth). ```tinkerpy loc = gps_location() bluetooth_write(loc) ``` Example 3 — An SOS button: sends the position by SMS (import gsm). ```tinkerpy if i1 == ON: gsm_send_sms("+919876543210", "Help! I am at " + gps_location()) ``` ### GSM Function A SIM800L GSM module with a SIM card — its TX wire goes to a pin set as gsm_rx (any pin) and its RX wire to an output set as gsm_tx: i2 = set_input(gsm_rx), o5 = set_output(gsm_tx). It needs its own 4 V, 2 A power supply (not the board's 3.3 V or 5 V pin), with the grounds joined. Messages are up to 30 letters. The same SMS is sent once in 5 minutes, at most one SMS every 10 seconds. Firmware 2.28. gsm_send_sms("number", message) Needs: `import gsm` · Firmware: 2.28+ Sends an SMS. The number in quotes (with +91 if you like), the message is text, a number or a join like "Temp " + t (up to 30 letters). The same SMS is not sent again for 5 minutes, and at most one SMS every 10 seconds — SMS cost money. | | | |---|---| | `number` | The phone number in quotes, e.g. "+919876543210" — or gsm_sms_number() to reply. | | `message` | Text, a number, a text variable or a join. | Example 1 — An alarm SMS when the door opens. ```tinkerpy if i1 == ON: gsm_send_sms("+919876543210", "Door open") ``` Example 2 — Sends the temperature when it is too hot. ```tinkerpy t = dht_temperature(i3) if t > 40: gsm_send_sms("+919876543210", "Too hot: " + t) ``` Example 3 — Replies to whoever sent STATUS. ```tinkerpy if gsm_read_sms() == "STATUS": gsm_send_sms(gsm_sms_number(), "All OK") ``` gsm_sms_received() Needs: `import gsm` · Firmware: 2.28+ 1 for one loop when an SMS arrives, else 0. Example 1 — Beeps for every SMS. ```tinkerpy if gsm_sms_received() == 1: buzzer_play(o2, "beep") ``` Example 2 — Shows each new SMS. ```tinkerpy if gsm_sms_received() == 1: oled_write(1, left, small, regular, gsm_read_sms()) ``` Example 3 — Counts the SMS (import counter). ```tinkerpy if gsm_sms_received() == 1: c1.increment() ``` gsm_read_sms() Needs: `import gsm` · Firmware: 2.28+ The text of the SMS that just arrived (for one loop), or None. Compare it: gsm_read_sms() == "ON" (capitals count). Example 1 — Switch a pump or a light by SMS. ```tinkerpy if gsm_read_sms() == "ON": o1 = ON elif gsm_read_sms() == "OFF": o1 = OFF ``` Example 2 — Keeps the last SMS on the screen. ```tinkerpy msg = gsm_read_sms() if msg != None: oled_write(2, left, small, regular, msg) ``` Example 3 — Texts back the GPS position (import gps). ```tinkerpy if gsm_read_sms() == "WHERE": gsm_send_sms(gsm_sms_number(), gps_location()) ``` gsm_sms_number() Needs: `import gsm` · Firmware: 2.28+ Who sent the SMS that just arrived (their number, as text) — use it to reply. Example 1 — Replies to every SMS. ```tinkerpy if gsm_sms_received() == 1: gsm_send_sms(gsm_sms_number(), "Got it") ``` Example 2 — Only Mum's phone can switch it on. ```tinkerpy if gsm_sms_number() == "+919876543210": o1 = ON ``` Example 3 — Shows who sent it. ```tinkerpy n = gsm_sms_number() oled_write(1, left, small, regular, n) ``` gsm_call("number") Needs: `import gsm` · Firmware: 2.28+ Calls a phone. The same number is not called again for 30 seconds. | | | |---|---| | `number` | The phone number in quotes, or gsm_sms_number(). | Example 1 — A call button. ```tinkerpy if i1 == ON: gsm_call("+919876543210") ``` Example 2 — Calls when there is gas (import gas sensor on i2). ```tinkerpy if analog_read(i2) > 70: gsm_call("+919876543210") ``` Example 3 — Calls back whoever asked. ```tinkerpy if gsm_read_sms() == "CALL ME": gsm_call(gsm_sms_number()) ``` gsm_hang_up() Needs: `import gsm` · Firmware: 2.28+ Ends a call, or stops a phone that is ringing. Example 1 — Rejects every call. ```tinkerpy if gsm_ringing() == 1: gsm_hang_up() ``` Example 2 — A hang-up button. ```tinkerpy if i2 == ON: gsm_hang_up() ``` Example 3 — Rings for 20 seconds, then stops. ```tinkerpy gsm_call("+919876543210") wait(20000) gsm_hang_up() ``` gsm_ringing() Needs: `import gsm` · Firmware: 2.28+ 1 while someone is calling the board, else 0. Example 1 — A light while the board's phone rings. ```tinkerpy if gsm_ringing() == 1: o1 = ON else: o1 = OFF ``` Example 2 — Missed-call switch: call the board to turn o2 on. ```tinkerpy if gsm_ringing() == 1: o2 = ON gsm_hang_up() ``` Example 3 — Shows it. ```tinkerpy r = gsm_ringing() oled_write(1, left, small, regular, r) ``` gsm_signal() Needs: `import gsm` · Firmware: 2.28+ The mobile signal, 0 (none) to 100 (full). Example 1 — Shows the signal. ```tinkerpy oled_write(1, left, small, regular, gsm_signal()) ``` Example 2 — A weak-signal light. ```tinkerpy if gsm_signal() < 20: o2 = ON ``` Example 3 — Sends it to the app (import bluetooth). ```tinkerpy s = gsm_signal() bluetooth_write(s) ``` ### Buzzer Function buzzer_play(output, "tone") Needs: `import buzzer` · Firmware: 2.19+ Plays a tone or a song on the buzzer; the next line runs when it ends. Simple: beep, double_beep, triple_beep, long_beep, chirp_up, chirp_down, success, error, notify, start_up. Alerts: warning, alarm, ambulance, police, fire_truck, school_bell, school_long_bell, door_bell, countdown, quiz_wrong, phone_ring, marimba_ring, message_beep, retro_phone. Tunes: happy_birthday, jingle_bells, jana_gana_mana, twinkle_twinkle, ode_to_joy, mary_lamb, old_macdonald, merry_christmas. Tunes need a PASSIVE buzzer (an active one just beeps the rhythm). Listen to them all on the board: Menu \> Buzzer Tones. | | | |----------|----------------------------------------------------| | `output` | The pin the buzzer is on, e.g. o1. | | `tone` | Which tone or song, in quotes, e.g. "school_bell". | Example 1 — A door bell: press the button, hear ding-dong. ```tinkerpy if i1 == ON: buzzer_play(o1, "door_bell") ``` Example 2 — The school bell at 9 o’clock. ```tinkerpy setup: clock_start(8, 59, 50) loop: if HH == 9 and MM == 0 and SS == 0: buzzer_play(o1, "school_long_bell") ``` Example 3 — Happy birthday on a passive buzzer, then a 3 second rest. ```tinkerpy setup: o2 = set_function(passive_buzzer) buzzer_play(o2, "happy_birthday") wait(3000) ``` buzzer_play_background(output, "tone", repeat) Needs: `import buzzer` · Firmware: 2.29+ · TinkerPy Mega Starts a tone or song and the program goes on at once (it does not wait). repeat is optional: 1 (or 0) = once, 3 = three times with a 0.5 s gap. If the same tone is already playing on that buzzer it just keeps playing, so you can call it on every pass of loop: for an alarm that sounds while something is true; a different tone stops the old one. One tune plays at a time on the board. Same tones as buzzer_play. TinkerPy Mega, board firmware 2.29. | | | |----------|-------------------------------------------------------------------------------| | `output` | The pin the buzzer is on, e.g. buzzer (or o1). | | `tone` | Which tone or song, in quotes, e.g. "alarm". | | `repeat` | Optional: how many times to play it (0 or 1 = once). 0.5 s between the plays. | Example 1 — An alarm that keeps sounding while i1 is ON — and the program keeps checking. ```tinkerpy o1 = set_name("buzzer") loop: if i1 == ON: buzzer_play_background(buzzer, "alarm") ``` Example 2 — Plays "police" 3 times while the light still follows the button at once. ```tinkerpy o1 = set_name("buzzer") loop: if i2 == ON: buzzer_play_background(buzzer, "police", 3) o2 = i2 ``` Example 3 — A birthday song at power-on on a passive buzzer, while the button works straight away. ```tinkerpy o1 = set_name("buzzer") setup: buzzer = set_function(passive_buzzer) buzzer_play_background(buzzer, "happy_birthday") loop: o2 = i1 ``` buzzer_stop_background(output) Needs: `import buzzer` · Firmware: 2.29+ · TinkerPy Mega Stops the tone that buzzer_play_background started on that buzzer. Nothing happens if it is quiet. TinkerPy Mega, board firmware 2.29. | | | |----------|------------------------------------------------| | `output` | The pin the buzzer is on, e.g. buzzer (or o1). | Example 1 — The alarm sounds while i1 is ON and stops as soon as it is OFF. ```tinkerpy o1 = set_name("buzzer") loop: if i1 == ON: buzzer_play_background(buzzer, "alarm") else: buzzer_stop_background(buzzer) ``` Example 2 — A silence button on i2. ```tinkerpy o1 = set_name("buzzer") loop: if i2 == ON: buzzer_stop_background(buzzer) ``` Example 3 — A siren for 10 seconds at power-on, then quiet. ```tinkerpy o1 = set_name("buzzer") setup: buzzer_play_background(buzzer, "police", 100) wait(10000) buzzer_stop_background(buzzer) ``` is_buzzer_playing(output) Needs: `import buzzer` · Firmware: 2.29+ · TinkerPy Mega Gives 1 while a tune started by buzzer_play_background is still playing on that buzzer, 0 when it is quiet. (buzzer_play makes the program wait until its tune ends, so after it this gives 0.) TinkerPy Mega, board firmware 2.29. | | | |----------|------------------------------------------------| | `output` | The pin the buzzer is on, e.g. buzzer (or o1). | Example 1 — A light that is ON while the bell rings. ```tinkerpy o1 = set_name("buzzer") loop: if i1 == ON: buzzer_play_background(buzzer, "school_bell", 2) if is_buzzer_playing(buzzer) == 1: o2 = ON else: o2 = OFF ``` Example 2 — When the song ends: 2 seconds of quiet, then it plays again. ```tinkerpy o1 = set_name("buzzer") loop: if is_buzzer_playing(buzzer) == 0: wait(2000) buzzer_play_background(buzzer, "twinkle_twinkle") ``` Example 3 — A light blinks while the song plays, then stays off. ```tinkerpy o1 = set_name("buzzer") setup: buzzer = set_function(passive_buzzer) buzzer_play_background(buzzer, "jingle_bells") loop: if is_buzzer_playing(buzzer) == 1: o2 = ON wait(200) o2 = OFF wait(200) ``` ### TV Remote Function **Keys** (always in small letters, in quotes): `"1"`…`"9"` `"0"` · `"a"` `"b"` `"c"` `"d"` (red, green, yellow, blue) · `"up"` `"down"` `"left"` `"right"` `"ok"` · `"v+"` `"v-"` `"ch+"` `"ch-"` · `"play"` `"pause"` `"ff"` `"fb"` · `"menu"` `"exit"`. The old keys F B L R S / back / home are gone (Compile changes them). remote_read() Needs: `import tv_remote` · Firmware: 2.23+ The remote key pressed — for one loop, and again and again while it is held. None when no key. Learn the keys on the board first: Menu \> TV Remote \> Learn Remote. Example 1 — Drives a robot with the TV remote: up forward, down back, ok stop. ```tinkerpy k = remote_read() if k == "up": robot_control("F", 80, "F", 80) elif k == "down": robot_control("B", 80, "B", 80) elif k == "ok": robot_control("S", 0, "S", 0) ``` Example 2 — Key 1 turns the light on, key 0 turns it off. ```tinkerpy k = remote_read() if k == "1": o1 = ON elif k == "0": o1 = OFF ``` Example 3 — CH+ / CH- turn a light on and off. ```tinkerpy if remote_read() == "ch+": o1 = ON if remote_read() == "ch-": o1 = OFF ``` remote_read_string(count, start, display, visibility, seconds) Needs: `import tv_remote` · Firmware: 2.23+ Waits for a **code** typed on the TV remote (keys 0–9 and A–D) and gives it, or **0** when no code was typed. | | | |--------------|-----------------------------------------------------------------------------------------------------------------------------------| | `count` | 1–6 keys. | | `start` | The key that starts typing, e.g. `"menu"`. `"any"` or `0` = start straight away. When it is not pressed the line gives 0 at once. | | `display` | `"oled"` (board screen: Enter Code, `_ _ _`, countdown) · `"lcd"` (needs `lcd_begin`) · an output like `o1` (blinks 1× for the 1st key, 2× for the 2nd …) · `0` (nothing shown). | | `visibility` | `"visible"` (3 4 _) or `"invisible"` (each key shows for a moment, then *). | | `seconds` | 1–255 for the whole code. Time up → 0. `exit` cancels → 0. After the last key the code stays on the display for 2 seconds. | Store it in a variable and compare it **in quotes**: `if code == "48A":` (or `code != 0` = any code). A code can’t be shown with oled_write. Example 1 — A door lock: press menu, type 4 8 2 on the remote, and the servo opens. ```tinkerpy code = remote_read_string(3, "menu", "oled", "visible", 10) if code == "482": o1 = servo_angle(90) ``` Example 2 — A secret 4-key code on the LCD, shown as * — right code lights o2, wrong code o3. ```tinkerpy code = remote_read_string(4, "any", "lcd", "invisible", 15) if code == "12AB": o2 = ON elif code != 0: o3 = ON ``` Example 3 — No display: o1 blinks once for the 1st key, twice for the 2nd. ```tinkerpy setup: o1 = set_function(output) code = remote_read_string(2, "ok", o1, "visible", 9) if code == "77": o2 = ON ``` ### Wireless Function **Board to board, no wires** (ESP-NOW, firmware 2.24, TinkerPy Mega). Write the other board’s Device ID (TP and 8 numbers, on that board: Menu → Device info) before the dot: `TP00000002.send("ON")`. Compile looks each board up on tinkerpy.com (the student must be online; an unknown ID is an error). A link opens only when **both** boards’ programs list each other — and `connect()` each other in `setup:` — so a stranger’s board can’t disturb yours. Up to 6 boards; the link comes back by itself. A message is up to 30 characters and is there for one loop. The board screen header shows `LK: OK`; Menu → Wireless devices lists each board. TP00000002.connect() Needs: `import wireless` · Firmware: 2.24+ Starts the link to that board (in setup:). The ID is the other board's Device ID (Menu > Device info). The link opens when BOTH boards' programs list each other, and comes back by itself if a board was off. Example 1 — Links to board TP00000002 and says hi every second. ```tinkerpy setup: TP00000002.connect() loop: TP00000002.send("hi") wait(1000) ``` Example 2 — One board can link to up to 6 boards. ```tinkerpy setup: TP00000002.connect() TP00000003.connect() loop: wireless_send_all("ping") wait(2000) ``` Example 3 — o1 shows when the link is up. ```tinkerpy setup: TP00000002.connect() loop: if TP00000002.connected() == 1: o1 = ON else: o1 = OFF ``` TP00000002.send(value) Needs: `import wireless` · Firmware: 2.24+ Sends text, a number or a join ("T" + temp) to that board — up to 30 characters. Gives 1 when the board got it, 0 when not (not linked or out of range); use it on its own line when you do not need to check. | | | |---|---| | `value` | "text", a number, a variable or a join like "T" + temp. | Example 1 — A button on this board switches a light on the other one. ```tinkerpy setup: TP00000002.connect() loop: if i1 == ON: TP00000002.send("ON") else: TP00000002.send("OFF") wait(200) ``` Example 2 — Sends a number (a reading) every second. ```tinkerpy setup: TP00000002.connect() loop: t = 25 TP00000002.send(t) wait(1000) ``` Example 3 — o3 lights when the message did not arrive. ```tinkerpy setup: TP00000002.connect() loop: ok = TP00000002.send("ALARM") if ok == 0: o3 = ON wait(500) ``` TP00000002.available() Needs: `import wireless` · Firmware: 2.24+ 1 when a message from that board arrived (it is there for one loop), 0 when not. Example 1 — Blinks o1 for every message. ```tinkerpy setup: TP00000002.connect() loop: if TP00000002.available() == 1: o1 = ON wait(200) o1 = OFF ``` Example 2 — Passes each message on to the phone app. ```tinkerpy setup: TP00000002.connect() bluetooth_begin() loop: if TP00000002.available() == 1: msg = TP00000002.read() bluetooth_write(msg) ``` Example 3 — o2 off while nothing comes. ```tinkerpy setup: TP00000002.connect() loop: if TP00000002.available() == 0: o2 = OFF ``` TP00000002.read() Needs: `import wireless` · Firmware: 2.24+ The message from that board as text (None when nothing came). Store it (msg = TP00000002.read()), compare it or show it. Example 1 — The other board switches o1 on and off. ```tinkerpy setup: TP00000002.connect() loop: msg = TP00000002.read() if msg == "ON": o1 = ON elif msg == "OFF": o1 = OFF ``` Example 2 — Shows each message on the OLED. ```tinkerpy setup: TP00000002.connect() oled_begin() loop: msg = TP00000002.read() if msg != None: oled_write(1, left, small, regular, "Got: " + msg) ``` Example 3 — A buzzer beeps when the friend sends BUZZ. ```tinkerpy setup: TP00000002.connect() loop: if TP00000002.read() == "BUZZ": o1 = ON wait(300) o1 = OFF ``` TP00000002.read_number() Needs: `import wireless` · Firmware: 2.24+ The message from that board as a number (a sensor reading) — None when nothing came or it is not a number. Example 1 — Lights o1 when the other board's distance is under 20. ```tinkerpy setup: TP00000002.connect() loop: d = TP00000002.read_number() if d != None and d < 20: o1 = ON ``` Example 2 — Turns a servo to the angle the other board sends. ```tinkerpy setup: TP00000002.connect() loop: a = TP00000002.read_number() if a != None: o2 = servo_angle(a) ``` Example 3 — Shows the temperature sent by the other board. ```tinkerpy setup: TP00000002.connect() oled_begin() loop: t = TP00000002.read_number() if t != None: oled_write(1, center, large, bold, t) ``` TP00000002.signal() Needs: `import wireless` · Firmware: 2.24+ How strong that board's signal is: 0–100 (0 = not heard). A "how close is my friend" sensor. Example 1 — An out-of-range alarm. ```tinkerpy setup: TP00000002.connect() loop: if TP00000002.signal() < 20: o1 = ON else: o1 = OFF ``` Example 2 — The LED gets brighter as the friend comes closer. ```tinkerpy setup: TP00000002.connect() loop: s = TP00000002.signal() o1 = pwm(s) ``` Example 3 — Shows the signal on the OLED. ```tinkerpy setup: TP00000002.connect() oled_begin() loop: oled_write(1, left, small, regular, "Signal " + TP00000002.signal()) wait(500) ``` TP00000002.connected() Needs: `import wireless` · Firmware: 2.24+ 1 while the link to that board is up (both boards list each other and hear each other), 0 when not. Example 1 — o1 shows the link. ```tinkerpy setup: TP00000002.connect() loop: if TP00000002.connected() == 1: o1 = ON else: o1 = OFF ``` Example 2 — o2 blinks while waiting for the friend. ```tinkerpy setup: TP00000002.connect() loop: if TP00000002.connected() == 0: o2 = ON wait(200) o2 = OFF wait(200) ``` Example 3 — Sends only while linked. ```tinkerpy setup: TP00000002.connect() loop: if TP00000002.connected() == 1 and i1 == ON: TP00000002.send("GO") ``` TP00000002.disconnect() Needs: `import wireless` · Firmware: 2.24+ Closes the link to that board and stops taking its messages (connect() opens it again). Example 1 — Buttons to stop and start the link. ```tinkerpy setup: TP00000002.connect() loop: if i1 == ON: TP00000002.disconnect() if i2 == ON: TP00000002.connect() ``` Example 2 — Stops listening when the friend says BYE. ```tinkerpy setup: TP00000002.connect() loop: if TP00000002.read() == "BYE": TP00000002.disconnect() ``` Example 3 — Closes the link when the friend is too far. ```tinkerpy setup: TP00000002.connect() loop: if TP00000002.signal() < 5: TP00000002.disconnect() ``` wireless_send_all(value) Needs: `import wireless` · Firmware: 2.24+ Sends to every linked board at once; gives how many got it. | | | |---|---| | `value` | "text", a number, a variable or a join. | Example 1 — One button stops all robots. ```tinkerpy setup: TP00000002.connect() TP00000003.connect() loop: if i1 == ON: wireless_send_all("STOP") ``` Example 2 — o1 lights when not every board got it. ```tinkerpy setup: TP00000002.connect() TP00000003.connect() loop: n = wireless_send_all("hi") if n < 2: o1 = ON wait(1000) ``` Example 3 — Sends a reading to all boards. ```tinkerpy setup: TP00000002.connect() TP00000003.connect() loop: t = 30 wireless_send_all("T" + t) wait(2000) ``` id, data = wireless_read_any() Needs: `import wireless` · Firmware: 2.24+ The next message from ANY linked board: id = who sent it ("TP00000003"), data = the message. Both None when nothing came. Example 1 — Listens to two boards at once. ```tinkerpy setup: TP00000002.connect() TP00000003.connect() loop: id, data = wireless_read_any() if id == "TP00000003": o1 = ON if data == "OFF": o1 = OFF ``` Example 2 — A hub that shows who sent what. ```tinkerpy setup: TP00000002.connect() TP00000003.connect() oled_begin() loop: id, data = wireless_read_any() if id != None: oled_write(1, left, small, regular, id + ": " + data) ``` Example 3 — Passes every board's messages to the phone. ```tinkerpy setup: TP00000002.connect() TP00000003.connect() bluetooth_begin() loop: id, data = wireless_read_any() if data != None: bluetooth_write(data) ``` ### Wireless IoT Function **Board to board over the internet (firmware 2.25, TinkerPy Mega).** The same functions as Wireless with _iot after the ID: `TP00000002_iot.send("ON")`. The boards can be anywhere — each on its own WiFi; tinkerpy.com passes the messages, so a message takes a few seconds (about 5–10 s free, 2–4 s Pro; the board checks in every 5 s / 2 s while the program uses wireless_iot). A link opens only when both boards’ programs list each other. `send()` gives 1 when the message is on its way (the other board is online and linked). No `signal()` — use `connected()`. A program uses wireless (radio) or wireless_iot, not both; iot_ and bluetooth_ functions work with either. Up to 6 boards, 30 characters per message; a message waits up to 60 s. Menu → Wireless devices shows them (“OK net”). TP00000002_iot.connect() Needs: `import wireless_iot` · Firmware: 2.25+ Starts the link to that board over the internet (in setup:). The ID is the other board's Device ID (Menu > Device info) with _iot after it. Both boards must be online (WiFi); the link opens when BOTH boards' programs list each other. Example 1 — Links to board TP00000002 over the internet and says hi every 5 seconds. ```tinkerpy setup: TP00000002_iot.connect() loop: TP00000002_iot.send("hi") wait(5000) ``` Example 2 — One board can link to up to 6 boards. ```tinkerpy setup: TP00000002_iot.connect() TP00000003_iot.connect() loop: wireless_iot_send_all("ping") wait(2000) ``` Example 3 — o1 shows when the link is up. ```tinkerpy setup: TP00000002_iot.connect() loop: if TP00000002_iot.connected() == 1: o1 = ON else: o1 = OFF ``` TP00000002_iot.send(value) Needs: `import wireless_iot` · Firmware: 2.25+ Sends text, a number or a join ("T" + temp) to that board through tinkerpy.com — up to 30 characters; it arrives in a few seconds (about 5–10 s free, 2–4 s Pro). Gives 1 when it is on its way (that board is online and linked), 0 when not. | | | |---|---| | `value` | "text", a number, a variable or a join like "T" + temp. | Example 1 — A button on this board switches a light on the other one. ```tinkerpy setup: TP00000002_iot.connect() loop: if i1 == ON: TP00000002_iot.send("ON") else: TP00000002_iot.send("OFF") wait(200) ``` Example 2 — Sends a number (a reading) every second. ```tinkerpy setup: TP00000002_iot.connect() loop: t = 25 TP00000002_iot.send(t) wait(1000) ``` Example 3 — o3 lights when the other board is not online. ```tinkerpy setup: TP00000002_iot.connect() loop: ok = TP00000002_iot.send("ALARM") if ok == 0: o3 = ON wait(500) ``` TP00000002_iot.available() Needs: `import wireless_iot` · Firmware: 2.25+ 1 when a message from that board arrived (it is there for one loop), 0 when not. Example 1 — Blinks o1 for every message. ```tinkerpy setup: TP00000002_iot.connect() loop: if TP00000002_iot.available() == 1: o1 = ON wait(200) o1 = OFF ``` Example 2 — Passes each message on to the phone app. ```tinkerpy setup: TP00000002_iot.connect() bluetooth_begin() loop: if TP00000002_iot.available() == 1: msg = TP00000002_iot.read() bluetooth_write(msg) ``` Example 3 — o2 off while nothing comes. ```tinkerpy setup: TP00000002_iot.connect() loop: if TP00000002_iot.available() == 0: o2 = OFF ``` TP00000002_iot.read() Needs: `import wireless_iot` · Firmware: 2.25+ The message from that board as text (None when nothing came). Store it (msg = TP00000002_iot.read()), compare it or show it. Example 1 — The other board switches o1 on and off. ```tinkerpy setup: TP00000002_iot.connect() loop: msg = TP00000002_iot.read() if msg == "ON": o1 = ON elif msg == "OFF": o1 = OFF ``` Example 2 — Shows each message on the OLED. ```tinkerpy setup: TP00000002_iot.connect() oled_begin() loop: msg = TP00000002_iot.read() if msg != None: oled_write(1, left, small, regular, "Got: " + msg) ``` Example 3 — A buzzer beeps when the friend sends BUZZ. ```tinkerpy setup: TP00000002_iot.connect() loop: if TP00000002_iot.read() == "BUZZ": o1 = ON wait(300) o1 = OFF ``` TP00000002_iot.read_number() Needs: `import wireless_iot` · Firmware: 2.25+ The message from that board as a number (a sensor reading) — None when nothing came or it is not a number. Example 1 — Lights o1 when the other board's distance is under 20. ```tinkerpy setup: TP00000002_iot.connect() loop: d = TP00000002_iot.read_number() if d != None and d < 20: o1 = ON ``` Example 2 — Turns a servo to the angle the other board sends. ```tinkerpy setup: TP00000002_iot.connect() loop: a = TP00000002_iot.read_number() if a != None: o2 = servo_angle(a) ``` Example 3 — Shows the temperature sent by the other board. ```tinkerpy setup: TP00000002_iot.connect() oled_begin() loop: t = TP00000002_iot.read_number() if t != None: oled_write(1, center, large, bold, t) ``` TP00000002_iot.connected() Needs: `import wireless_iot` · Firmware: 2.25+ 1 while that board is online and linked (both programs list each other), 0 when not. Example 1 — o1 shows the link. ```tinkerpy setup: TP00000002_iot.connect() loop: if TP00000002_iot.connected() == 1: o1 = ON else: o1 = OFF ``` Example 2 — o2 blinks while the friend is offline. ```tinkerpy setup: TP00000002_iot.connect() loop: if TP00000002_iot.connected() == 0: o2 = ON wait(200) o2 = OFF wait(200) ``` Example 3 — Sends only while linked. ```tinkerpy setup: TP00000002_iot.connect() loop: if TP00000002_iot.connected() == 1 and i1 == ON: TP00000002_iot.send("GO") ``` TP00000002_iot.disconnect() Needs: `import wireless_iot` · Firmware: 2.25+ Closes the link to that board and stops taking its messages (connect() opens it again). Example 1 — Buttons to stop and start the link. ```tinkerpy setup: TP00000002_iot.connect() loop: if i1 == ON: TP00000002_iot.disconnect() if i2 == ON: TP00000002_iot.connect() ``` Example 2 — Stops listening when the friend says BYE. ```tinkerpy setup: TP00000002_iot.connect() loop: if TP00000002_iot.read() == "BYE": TP00000002_iot.disconnect() ``` Example 3 — Stops the link when the friend says STOP. ```tinkerpy setup: TP00000002_iot.connect() loop: if TP00000002_iot.read() == "STOP": TP00000002_iot.disconnect() o1 = OFF ``` wireless_iot_send_all(value) Needs: `import wireless_iot` · Firmware: 2.25+ Sends to every linked board at once over the internet; gives how many it is on its way to. | | | |---|---| | `value` | "text", a number, a variable or a join. | Example 1 — One button stops all robots. ```tinkerpy setup: TP00000002_iot.connect() TP00000003_iot.connect() loop: if i1 == ON: wireless_iot_send_all("STOP") ``` Example 2 — o1 lights when not every board got it. ```tinkerpy setup: TP00000002_iot.connect() TP00000003_iot.connect() loop: n = wireless_iot_send_all("hi") if n < 2: o1 = ON wait(1000) ``` Example 3 — Sends a reading to all boards. ```tinkerpy setup: TP00000002_iot.connect() TP00000003_iot.connect() loop: t = 30 wireless_iot_send_all("T" + t) wait(2000) ``` id, data = wireless_iot_read_any() Needs: `import wireless_iot` · Firmware: 2.25+ The next message from ANY linked board: id = who sent it ("TP00000003"), data = the message. Both None when nothing came. Example 1 — Listens to two boards at once. ```tinkerpy setup: TP00000002_iot.connect() TP00000003_iot.connect() loop: id, data = wireless_iot_read_any() if id == "TP00000003": o1 = ON if data == "OFF": o1 = OFF ``` Example 2 — A hub that shows who sent what. ```tinkerpy setup: TP00000002_iot.connect() TP00000003_iot.connect() oled_begin() loop: id, data = wireless_iot_read_any() if id != None: oled_write(1, left, small, regular, id + ": " + data) ``` Example 3 — Passes every board's messages to the phone. ```tinkerpy setup: TP00000002_iot.connect() TP00000003_iot.connect() bluetooth_begin() loop: id, data = wireless_iot_read_any() if data != None: bluetooth_write(data) ``` ### Joystick Function joystick_x() Needs: `import joystick` · Firmware: 2.18+ How far the stick is pushed left or right: −100 (left) to 100 (right), 0 in the middle. The X wire goes on i1–i4. Example 1 — The stick turns a servo left and right. ```tinkerpy setup: i1 = set_function(joystick_x) o1 = servo_angle(90 + joystick_x() * 9 / 10) ``` Example 2 — A light comes on when the stick is pushed right. ```tinkerpy x = joystick_x() if x > 50: o1 = ON else: o1 = OFF ``` Example 3 — Shows the X value on the OLED. ```tinkerpy oled_write(1, left, small, regular, joystick_x()) ``` joystick_y() Needs: `import joystick` · Firmware: 2.18+ How far the stick is pushed up or down: −100 (down) to 100 (up), 0 in the middle. The Y wire goes on i1–i4. Example 1 — Push up to make the light brighter. ```tinkerpy y = joystick_y() if y > 0: o1 = pwm(y) else: o1 = OFF ``` Example 2 — Sends the Y value to the app. ```tinkerpy setup: i2 = set_function(joystick_y) bluetooth_write(joystick_y()) ``` Example 3 — A level meter that follows the stick. ```tinkerpy rgb_bar(o3, all, "rainbow", joystick_y(), 100) ``` joystick_direction() Needs: `import joystick` · Firmware: 2.18+ Where the stick points: 'F' (up), 'B' (down), 'L', 'R' — or 'S' in the middle. Like the app's Digital Joystick. Example 1 — Drives a robot with the joystick. ```tinkerpy d = joystick_direction() if d == 'F': robot_control("F", 80, "F", 80) elif d == 'B': robot_control("B", 80, "B", 80) elif d == 'S': robot_control("S", 0, "S", 0) ``` Example 2 — A light for pushing left. ```tinkerpy if joystick_direction() == 'L': o1 = ON ``` Example 3 — Sends F / B / L / R / S to the app. ```tinkerpy bluetooth_write(joystick_direction()) ``` joystick_pressed() Needs: `import joystick` · Firmware: 2.18+ 1 while the stick is pushed in (its switch), otherwise 0. The SW wire can go on any pin. Example 1 — A buzzer while the stick is pushed in. ```tinkerpy if joystick_pressed() == 1: o2 = ON else: o2 = OFF ``` Example 2 — The switch on o5 flips an RGB LED. ```tinkerpy setup: o5 = set_function(joystick_swt) if joystick_pressed() == 1: rgb_flip(o1, 1, "green") ``` Example 3 — Counts the presses. ```tinkerpy if joystick_pressed() == 1: c1.increment() wait(300) ``` ### RGB LED Function rgb_begin(output, number_of_leds) Needs: `import rgb_single or import rgb_two or import rgb_three or import rgb_strip` · Firmware: 2.17+ Goes inside setup: — says which output the RGB LEDs are on and how many there are. Added for you when you tick an RGB LED library. | | | |------------------|-----------------------------------------------------------------------| | `output` | The output the LED board or strip is plugged into, like o1. | | `number_of_leds` | 1, 2 or 3 for an LED board, or how many LEDs your strip has (max 60). | Example 1 — A single-LED board on o1. ```tinkerpy setup: rgb_begin(o1, 1) ``` Example 2 — A 3-LED board on o1. ```tinkerpy setup: rgb_begin(o1, 3) ``` Example 3 — A strip with 30 LEDs on o2. ```tinkerpy setup: rgb_begin(o2, 30) ``` Example 4 — Two boards at once: 2 LEDs on o1 and a 60-LED strip on o2 (up to 4 boards). ```tinkerpy setup: rgb_begin(o1, 2) rgb_begin(o2, 60) ``` rgb_color(output, led, "color", brightness) Needs: `import rgb_single or import rgb_two or import rgb_three or import rgb_strip` · Firmware: 2.17+ Lights an LED (or all of them) in a colour. Brightness can be left out (100). | | | |--------------|---------------------------------------------------------------------------------------------------------------------------| | `output` | The output with the RGB LEDs, like o1. | | `led` | Which LED: 1, 2, 3 … or all. | | `color` | red, green, blue, yellow, orange, purple, pink, cyan, white, warm_white, off, random, rainbow — or a code like "#FF8800". | | `brightness` | Optional, 0–100. Left out = 100. | Example 1 — Every LED turns red. ```tinkerpy rgb_color(o1, all, "red") ``` Example 2 — LED 2 turns orange at 40% brightness. ```tinkerpy rgb_color(o1, 2, "#FF8800", 40) ``` Example 3 — Green while the button is pressed. ```tinkerpy if i1 == ON: rgb_color(o1, all, "green") else: rgb_color(o1, all, "off") ``` Example 4 — Spreads the rainbow over all the LEDs. ```tinkerpy rgb_color(o1, all, "rainbow") ``` rgb_flip(output, led, "color", brightness) Needs: `import rgb_single or import rgb_two or import rgb_three or import rgb_strip` · Firmware: 2.17+ Each new press flips the LED: on in that colour, then off, then on… While the button stays pressed nothing changes. Brightness can be left out (100). | | | |--------------|-------------------------------------------------------------------| | `output` | The output with the RGB LEDs, like o1. | | `led` | Which LED: 1, 2, 3 … or all. | | `color` | The colour it turns on in — a name, "#FF8800", random or rainbow. | | `brightness` | Optional, 0–100. Left out = 100. | Example 1 — Press once: LED 1 turns red. Press again: off. ```tinkerpy if i1 == ON: rgb_flip(o1, 1, "red") ``` Example 2 — A press on/off lamp for the whole strip. ```tinkerpy if i2 == ON: rgb_flip(o1, all, "white") ``` Example 3 — Two buttons, each one flips its own LED. ```tinkerpy if i1 == ON: rgb_flip(o1, 1, "green") if i2 == ON: rgb_flip(o1, 2, "blue") ``` rgb_hex_color(output, led, r, g, b) Needs: `import rgb_single or import rgb_two or import rgb_three or import rgb_strip` · Firmware: 2.17+ Mixes any colour from red, green and blue (0–255 each, like a colour picker). Numbers or variables. | | | |----------|----------------------------------------| | `output` | The output with the RGB LEDs, like o1. | | `led` | Which LED: 1, 2, 3 … or all. | | `r` | How much red, 0–255. | | `g` | How much green, 0–255. | | `b` | How much blue, 0–255. | Example 1 — Mixes orange (lots of red, some green). ```tinkerpy rgb_hex_color(o1, all, 255, 120, 0) ``` Example 2 — LED 1 gets bluer as the reading goes up. ```tinkerpy light = analog_read(i1) rgb_hex_color(o1, 1, 0, 0, light * 2) ``` Example 3 — A random mix between red and blue. ```tinkerpy red = random(0, 255) rgb_hex_color(o1, all, red, 0, 255 - red) ``` rgb_blink(output, led, "color", on_ms, off_ms) Needs: `import rgb_single or import rgb_two or import rgb_three or import rgb_strip` · Firmware: 2.17+ Blinks by itself while your code keeps running. on_ms and off_ms can be left out (500). | | | |----------|------------------------------------------------------------------------| | `output` | The output with the RGB LEDs, like o1. | | `led` | Which LED: 1, 2, 3 … or all. | | `color` | A colour name, "#FF8800", random or rainbow (a new colour each blink). | | `on_ms` | Optional: how long it is on, in ms (500). | | `off_ms` | Optional: how long it is off (same as on_ms). | Example 1 — LED 1 blinks red, half a second on, half off. ```tinkerpy rgb_blink(o1, 1, "red") ``` Example 2 — All LEDs blink fast in a new colour each time. ```tinkerpy rgb_blink(o1, all, "random", 300) ``` Example 3 — A short flash every second, like a beacon. ```tinkerpy rgb_blink(o1, 2, "white", 100, 900) ``` rgb_breathe(output, led, "color", time_ms) Needs: `import rgb_single or import rgb_two or import rgb_three or import rgb_strip` · Firmware: 2.17+ Slowly fades in and out, by itself. time_ms can be left out (2000). | | | |-----------|----------------------------------------------| | `output` | The output with the RGB LEDs, like o1. | | `led` | Which LED: 1, 2, 3 … or all. | | `color` | A colour name, "#FF8800", random or rainbow. | | `time_ms` | Optional: one breath, in ms (2000). | Example 1 — A calm purple glow. ```tinkerpy rgb_breathe(o1, all, "purple") ``` Example 2 — Each breath in the next rainbow colour. ```tinkerpy rgb_breathe(o1, 1, "rainbow", 3000) ``` Example 3 — Breathes while waiting; green when pressed. ```tinkerpy if i1 == OFF: rgb_breathe(o1, all, "blue") else: rgb_color(o1, all, "green") ``` rgb_swap(output, led, "color", "color2", time_ms) Needs: `import rgb_single or import rgb_two or import rgb_three or import rgb_strip` · Firmware: 2.17+ Swaps between two colours, by itself — neighbouring LEDs take turns, like police lights. | | | |-----------|----------------------------------------------------| | `output` | The output with the RGB LEDs, like o1. | | `led` | Which LED: 1, 2, 3 … or all. | | `color` | The first colour. | | `color2` | Optional: the second colour ("off"). | | `time_ms` | Optional: how long each colour stays, in ms (500). | Example 1 — Police lights. ```tinkerpy rgb_swap(o1, all, "red", "blue", 300) ``` Example 2 — LED 1 flashes yellow on and off. ```tinkerpy rgb_swap(o1, 1, "yellow") ``` Example 3 — A slow festive swap. ```tinkerpy rgb_swap(o1, all, "green", "white", 1000) ``` rgb_chase(output, led, "color", speed_ms) Needs: `import rgb_single or import rgb_two or import rgb_three or import rgb_strip` · Firmware: 2.17+ One light runs along the LEDs, by itself. With a number it runs over LEDs 1 to that number. "rainbow" makes a moving rainbow. | | | |------------|----------------------------------------------------| | `output` | The output with the RGB LEDs, like o1. | | `led` | all (the whole strip) or a number n (LEDs 1 to n). | | `color` | A colour name, "#FF8800", random or rainbow. | | `speed_ms` | Optional: time per step, in ms (100). | Example 1 — A blue light runs along the strip. ```tinkerpy rgb_chase(o1, all, "blue") ``` Example 2 — A moving rainbow. ```tinkerpy rgb_chase(o1, all, "rainbow", 50) ``` Example 3 — Runs over LEDs 1–3 only. ```tinkerpy rgb_chase(o1, 3, "red", 200) ``` rgb_wipe(output, led, "color", speed_ms) Needs: `import rgb_single or import rgb_two or import rgb_three or import rgb_strip` · Firmware: 2.17+ Fills the LEDs one after another, then stays on. With a number it fills LEDs 1 to that number. | | | |------------|----------------------------------------------| | `output` | The output with the RGB LEDs, like o1. | | `led` | all or a number n (LEDs 1 to n). | | `color` | A colour name, "#FF8800", random or rainbow. | | `speed_ms` | Optional: time per LED, in ms (50). | Example 1 — The strip fills up with green. ```tinkerpy rgb_wipe(o1, all, "green") ``` Example 2 — Fills with a rainbow. ```tinkerpy rgb_wipe(o1, all, "rainbow", 30) ``` Example 3 — A quick white fill when the button is pressed. ```tinkerpy if i1 == ON: rgb_wipe(o1, all, "white", 20) ``` rgb_twinkle(output, led, "color", speed_ms) Needs: `import rgb_single or import rgb_two or import rgb_three or import rgb_strip` · Firmware: 2.17+ LEDs sparkle at random, like stars, by themselves. | | | |------------|----------------------------------------------| | `output` | The output with the RGB LEDs, like o1. | | `led` | all or a number n (LEDs 1 to n). | | `color` | A colour name, "#FF8800", random or rainbow. | | `speed_ms` | Optional: how fast, in ms (100). | Example 1 — Starry sky. ```tinkerpy rgb_twinkle(o1, all, "white") ``` Example 2 — Party sparkles in every colour. ```tinkerpy rgb_twinkle(o1, all, "random", 60) ``` Example 3 — Gentle fairy lights. ```tinkerpy rgb_twinkle(o1, all, "warm_white", 200) ``` rgb_bar(output, led, "color", value, max) Needs: `import rgb_single or import rgb_two or import rgb_three or import rgb_strip` · Firmware: 2.17+ A level meter: lights more LEDs as the value goes up. "rainbow" goes green → yellow → red. | | | |----------|-----------------------------------------------------| | `output` | The output with the RGB LEDs, like o1. | | `led` | all or a number n (use LEDs 1 to n). | | `color` | A colour name, "#FF8800" or rainbow (green to red). | | `value` | The level to show — a number or a reading. | | `max` | Optional: the value that lights every LED (100). | Example 1 — A soil / light meter from 0 to 100. ```tinkerpy rgb_bar(o1, all, "green", analog_read(i1)) ``` Example 2 — Fills up as something comes closer. ```tinkerpy d = distance() rgb_bar(o1, all, "rainbow", 100 - d, 100) ``` Example 3 — Shows a counter from 0 to 10. ```tinkerpy rgb_bar(o1, all, "blue", c1, 10) ``` rgb_heat(output, led, "color", value, low, high) Needs: `import rgb_single or import rgb_two or import rgb_three or import rgb_strip` · Firmware: 2.17+ The colour follows a value: blue at low, the colour you pick at high. "rainbow" goes blue → green → red. | | | |----------|-----------------------------------------------| | `output` | The output with the RGB LEDs, like o1. | | `led` | Which LED: 1, 2, 3 … or all. | | `color` | The colour at high (like red), or rainbow. | | `value` | The number to show — a reading or a variable. | | `low` | Optional: blue at this value (0). | | `high` | Optional: full colour at this value (100). | Example 1 — A thermometer light: blue when cool, red when hot. ```tinkerpy rgb_heat(o1, all, "red", dht_temperature(i1), 20, 40) ``` Example 2 — A dial from blue to red. ```tinkerpy rgb_heat(o1, 1, "rainbow", analog_read(i1)) ``` Example 3 — Turns from blue to green as the counter climbs. ```tinkerpy rgb_heat(o1, all, "green", c1, 0, 20) ``` ### LCD Display Function lcd_begin(address) Needs: `import lcd_16x2` · Firmware: 2.16+ Starts the LCD. Goes inside setup: — added for you when you tick the 16x2 LCD. | | | |-----------|-----------------------------------------------------------------------------------------------------| | `address` | The LCD’s I2C address — most are 0x27 or 0x3F. Leave it empty, lcd_begin(), and the board finds it. | Example 1 — The most common LCD address. ```tinkerpy setup: lcd_begin(0x27) ``` Example 2 — Some LCD modules use 0x3F instead. ```tinkerpy setup: lcd_begin(0x3F) ``` Example 3 — Not sure? The board looks for the LCD by itself. ```tinkerpy setup: lcd_begin() ``` lcd_write(line, position, value) Needs: `import lcd_16x2` · Firmware: 2.16+ Writes text or a number on the LCD, starting at a place on a line. | | | |------------|-----------------------------------------------------| | `line` | Which line: 1 or 2. | | `position` | Where on the line to start: 1 (left) to 16 (right). | | `value` | Text in quotes, or a number / variable. | Example 1 — Writes on line 1, from the left. ```tinkerpy lcd_write(1, 1, "Hello!") ``` Example 2 — A label and a live number on the same line. ```tinkerpy lcd_write(2, 1, "Temp:") lcd_write(2, 7, dht_temperature(i1)) ``` Example 3 — Starts at place 6 — good for centring short words. ```tinkerpy lcd_write(1, 6, "Hi") ``` lcd_clear() Needs: `import lcd_16x2` · Firmware: 2.16+ Clears the whole LCD. Example 1 — Wipes both lines blank. ```tinkerpy lcd_clear() ``` Example 2 — Shows a message for 2 seconds, then clears it. ```tinkerpy lcd_write(1, 1, "Hello") wait(2000) lcd_clear() ``` Example 3 — Clears the screen when a button is pressed. ```tinkerpy if i1 == ON: lcd_clear() ``` lcd_clear_line(line) Needs: `import lcd_16x2` · Firmware: 2.16+ Clears just one line of the LCD. | | | |--------|------------------------------| | `line` | Which line to clear: 1 or 2. | Example 1 — Clears line 2, line 1 stays. ```tinkerpy lcd_clear_line(2) ``` Example 2 — Clear first, so an old longer number never leaves digits behind. ```tinkerpy count = 5 lcd_clear_line(1) lcd_write(1, 1, count) ``` Example 3 — Removes a message when the button is let go. ```tinkerpy if i1 == OFF: lcd_clear_line(2) ``` lcd_scroll(line, text) Needs: `import lcd_16x2` · Firmware: 2.16+ Scrolls long text along a line. It keeps scrolling by itself while the rest of your code runs. | | | |--------|--------------------------------| | `line` | Which line: 1 or 2. | | `text` | The text to scroll, in quotes. | Example 1 — A moving welcome message on line 1. ```tinkerpy lcd_scroll(1, "Welcome to TinkerPy!") ``` Example 2 — Line 1 scrolls while line 2 shows a reading. ```tinkerpy lcd_scroll(1, "Smart Plant Monitor") lcd_write(2, 1, analog_read(i1)) ``` Example 3 — Clearing the line stops the scrolling. ```tinkerpy lcd_scroll(2, "News: it is hot today") wait(5000) lcd_clear_line(2) ``` lcd_backlight(ON / OFF) Needs: `import lcd_16x2` · Firmware: 2.16+ Switches the LCD’s backlight on or off. The text stays. | | | |------------|---------------------------------------| | `ON / OFF` | ON lights the screen, OFF darkens it. | Example 1 — Darkens the screen to save power. ```tinkerpy lcd_backlight(OFF) ``` Example 2 — Lights the screen only while the button is pressed. ```tinkerpy if i1 == ON: lcd_backlight(ON) else: lcd_backlight(OFF) ``` Example 3 — Blinks the screen once to get attention. ```tinkerpy lcd_backlight(OFF) wait(500) lcd_backlight(ON) ``` ### OLED Display Function oled_begin(address) Needs: `import oled_display` · Firmware: 2.16+ Starts the OLED. Goes inside setup: — added for you when you tick the OLED. | | | |-----------|------------------------------------------------------------------| | `address` | Optional. Most OLEDs are 0x3C (used when empty); a few are 0x3D. | Example 1 — Starts the OLED at its usual address. ```tinkerpy setup: oled_begin() ``` Example 2 — For an OLED set to address 0x3D. ```tinkerpy setup: oled_begin(0x3D) ``` Example 3 — An OLED and an LCD together — each shows what its own functions write. ```tinkerpy setup: oled_begin() lcd_begin(0x27) ``` oled_write(line, align, size, weight, value) Needs: `import oled_display` · Firmware: 2.20+ Writes text or a number on a line of the OLED (it replaces that line). The OLED has 4 lines. Sizes: small = 21 letters, 1 line · medium = 10 letters, 2 lines · large = 7 letters, 2 lines (medium and large also use the line below, so start them on line 1, 2 or 3). | | | |----------|-----------------------------------------------------------------------------------------| | `line` | Which line: 1 to 4 (medium / large: 1 to 3 — they take 2 lines). | | `align` | left, center or right. | | `size` | small (21 letters, 1 line), medium (10 letters, 2 lines) or large (7 letters, 2 lines). | | `weight` | regular or bold. | | `value` | Text in quotes, or a number / variable. | Example 1 — Small text on line 3, from the left. ```tinkerpy oled_write(3, left, small, regular, "Sensor ON") ``` Example 2 — A big bold number in the middle of lines 1–2. ```tinkerpy oled_write(1, center, large, bold, c1) ``` Example 3 — A title, a label and a live value on the right. ```tinkerpy oled_write(1, center, medium, bold, "Weather") oled_write(3, left, small, regular, "Temp") oled_write(4, right, small, regular, dht_temperature(i1)) ``` oled_clear() Needs: `import oled_display` · Firmware: 2.16+ Clears the whole OLED. Example 1 — Wipes the screen blank. ```tinkerpy oled_clear() ``` Example 2 — Shows a message for 2 seconds, then clears it. ```tinkerpy oled_write(1, left, small, regular, "Hello") wait(2000) oled_clear() ``` Example 3 — Clears the screen when a button is pressed. ```tinkerpy if i1 == ON: oled_clear() ``` oled_clear_line(line) Needs: `import oled_display` · Firmware: 2.16+ Clears just one line of the OLED. | | | |--------|------------------------------| | `line` | Which line to clear: 1 to 4. | Example 1 — Clears line 3, the others stay. ```tinkerpy oled_clear_line(3) ``` Example 2 — Removes a message when the button is let go. ```tinkerpy if i1 == OFF: oled_clear_line(4) ``` Example 3 — Shows a message for a second, then removes it. ```tinkerpy oled_write(2, left, small, regular, "Saved!") wait(1000) oled_clear_line(2) ``` oled_eye_animation(name, repeat, speed, delay) Needs: `import oled_display` · Firmware: 2.19+ Robot eyes on the whole OLED: blink, look_left, look_right, look_up, look_down, look_around, happy, sad, angry, sleepy, surprised, wink, love, dizzy, suspicious, crying, confused, wake_up. It plays by itself while the rest of your code runs; oled_write / oled_clear stop it. Try them all on the board: Menu \> Animations \> Eyes. | | | |----------|----------------------------------------------------------| | `name` | Which animation, in quotes, e.g. "blink". | | `repeat` | How many times it plays. 0 = for ever. | | `speed` | 1 (slow) to 10 (fast). 5 is normal. | | `delay` | Pause between repeats in milliseconds (1000 = 1 second). | Example 1 — A robot face that blinks every 2 seconds, for ever. ```tinkerpy oled_eye_animation("blink", 0, 5, 2000) ``` Example 2 — Happy eyes when the button is pressed, looking around otherwise. ```tinkerpy if i1 == ON: oled_eye_animation("happy", 2, 6, 300) else: oled_eye_animation("look_around", 0, 4, 1000) ``` Example 3 — Falls asleep, then text takes the screen back. ```tinkerpy oled_eye_animation("sleepy", 1, 3, 0) wait(4000) oled_write(1, left, small, regular, "Good night") ``` oled_emoji_animation(name, repeat, speed, delay) Needs: `import oled_display` · Firmware: 2.19+ A moving emoji on the whole OLED: smile, laugh, wink, love, sad, cry, angry, surprised, sleepy, cool, tongue, heart, star, thinking, kiss. Plays by itself; oled_write / oled_clear stop it. See them all: Menu \> Animations \> Emoji. | | | |----------|----------------------------------------| | `name` | Which emoji, in quotes, e.g. "smile". | | `repeat` | How many times it plays. 0 = for ever. | | `speed` | 1 (slow) to 10 (fast). 5 is normal. | | `delay` | Pause between repeats in milliseconds. | Example 1 — A heart that keeps beating. ```tinkerpy oled_emoji_animation("heart", 0, 6, 0) ``` Example 2 — Laughs when tickled (button), sleeps otherwise. ```tinkerpy if i1 == ON: oled_emoji_animation("laugh", 3, 7, 0) else: oled_emoji_animation("sleepy", 0, 3, 500) ``` Example 3 — Sunglasses slide down — once. ```tinkerpy oled_emoji_animation("cool", 1, 5, 0) ``` oled_scroll(line, text) Needs: `import oled_display` · Firmware: 2.16+ Scrolls long text along a line. It keeps scrolling by itself while the rest of your code runs. | | | |--------|--------------------------------| | `line` | Which line: 1 to 4. | | `text` | The text to scroll, in quotes. | Example 1 — A moving welcome message on line 1. ```tinkerpy oled_scroll(1, "Welcome to TinkerPy!") ``` Example 2 — Line 4 scrolls while line 1 stays still. ```tinkerpy oled_scroll(4, "Press the button to start") oled_write(1, left, small, regular, "Game") ``` Example 3 — Clearing the line stops the scrolling. ```tinkerpy oled_scroll(2, "Game over") wait(5000) oled_clear_line(2) ``` ### Counter Function c1.auto_increment(interval_ms) Needs: `import counter` Starts counting up by 1, automatically, forever, in the background — once every interval_ms. | | | |---------------|------------------------------------------------------------| | `interval_ms` | How often to add 1, in milliseconds (1–32767). 1000 = once a second. | Example 1 — Counts up once a second, shown live on the display. ```tinkerpy setup: c1.auto_increment(1000) loop: oled_write(1, left, small, regular, c1) ``` Example 2 — Counts up fast; turns o1 on once it passes 50. ```tinkerpy setup: c1.auto_increment(200) loop: if c1 > 50: o1 = pwm(100) ``` Example 3 — Two counters can tick at completely different speeds at once. ```tinkerpy setup: c1.auto_increment(1000) c2.auto_increment(500) ``` c1.auto_decrement(interval_ms) Needs: `import counter` Starts counting down by 1, automatically, forever, in the background — once every interval_ms. | | | |---------------|-------------------------------------------| | `interval_ms` | How often to subtract 1, in milliseconds (1–32767). | Example 1 — A 60-second countdown, shown live on the display. ```tinkerpy setup: c1.set(60) c1.auto_decrement(1000) loop: oled_write(1, left, small, regular, c1) ``` Example 2 — Counts down from 10, then turns o1 on when it hits 0. ```tinkerpy setup: c1.set(10) c1.auto_decrement(500) loop: if c1 == 0: o1 = pwm(100) ``` Example 3 — A fast countdown, subtracting 1 every 100ms. ```tinkerpy setup: c1.set(100) c1.auto_decrement(100) ``` c1.increment() Needs: `import counter` Adds 1 to the counter, once, right now — not automatic. Example 1 — Counts how many times the button has been pressed. ```tinkerpy if i1 == ON: c1.increment() ``` Example 2 — Adds 1 and shows the new total. ```tinkerpy c1.increment() oled_write(1, left, small, regular, c1) ``` Example 3 — Adds 1 five times in a row — c1 ends up at 5. ```tinkerpy repeat(5): c1.increment() ``` c1.decrement() Needs: `import counter` Subtracts 1 from the counter, once, right now — not automatic. Example 1 — A second button counts back down. ```tinkerpy if i2 == ON: c1.decrement() ``` Example 2 — Starts at 10, subtracts 1, shows 9. ```tinkerpy setup: c1.set(10) loop: c1.decrement() oled_write(1, left, small, regular, c1) ``` Example 3 — One button counts up, another counts down. ```tinkerpy if i1 == ON: c1.increment() if i2 == ON: c1.decrement() ``` c1.clear() Needs: `import counter` Resets the counter to 0. Doesn’t stop auto_increment/auto_decrement if either is running. Example 1 — A button resets the counter back to 0. ```tinkerpy if i1 == ON: c1.clear() ``` Example 2 — Counts up, then resets itself once it passes 10. ```tinkerpy c1.increment() if c1 > 10: c1.clear() ``` Example 3 — Keeps auto-counting, but a button can reset it back to 0 at any time. ```tinkerpy setup: c1.auto_increment(1000) loop: if i1 == ON: c1.clear() ``` c1.pause() Needs: `import counter` Stops auto_increment/auto_decrement, freezing the counter where it is. Example 1 — Counts up automatically until a button freezes it. ```tinkerpy setup: c1.auto_increment(1000) loop: if i1 == ON: c1.pause() ``` Example 2 — A countdown that stops itself at 0, instead of going negative. ```tinkerpy setup: c1.auto_decrement(1000) loop: if c1 == 0: c1.pause() ``` Example 3 — Configures a countdown but starts it paused — call auto_decrement(...) again later to start it ticking. ```tinkerpy setup: c1.set(10) c1.auto_decrement(500) loop: c1.pause() ``` c1.set(value) Needs: `import counter` Jumps the counter straight to a specific number. | | | |---------|-----------------------------------------| | `value` | The exact number to set the counter to. | Example 1 — Starts the counter at 100 instead of 0. ```tinkerpy setup: c1.set(100) ``` Example 2 — A button can jump the counter back to a specific value. ```tinkerpy if i1 == ON: c1.set(0) ``` Example 3 — Sets the starting point, then counts down from there. ```tinkerpy setup: c1.set(60) c1.auto_decrement(1000) ``` ### Clock Function clock_start(hours, minutes, seconds) Needs: `import clock` Sets the clock to a starting time and begins running it. | | | |-----------|-------| | `hours` | 0-23. | | `minutes` | 0-59. | | `seconds` | 0-59. | Example 1 — Starts the clock at 12:30:00 and shows the hour. ```tinkerpy setup: clock_start(12, 30, 0) loop: oled_write(1, left, small, regular, HH) ``` Example 2 — Starts from midnight; turns o1 on once a minute has passed. ```tinkerpy setup: clock_start(0, 0, 0) loop: if MM == 1: o1 = pwm(100) ``` Example 3 — Starts just before midnight, to test the hour rolling over. ```tinkerpy setup: clock_start(23, 59, 55) ``` HH, MM, SS Needs: `import clock` Three special values that always hold the clock’s current hour, minute, and second — read them directly in a condition, no parentheses needed. | | | |------|---------------------------| | `HH` | The current hour, 0-23. | | `MM` | The current minute, 0-59. | | `SS` | The current second, 0-59. | Example 1 — Turns o1 on the instant the hour reaches 12. ```tinkerpy setup: clock_start(9, 0, 0) loop: if HH == 12: o1 = pwm(100) ``` Example 2 — Turns o1 on for exactly the one minute when MM equals 30, then back off. ```tinkerpy setup: clock_start(0, 0, 0) loop: if MM == 30: o1 = pwm(100) else: o1 = 0 ``` Example 3 — Comparing HH and MM together checks for one exact time, like an alarm. ```tinkerpy setup: clock_start(7, 55, 0) loop: if HH == 8 and MM == 0: bluetooth_write("It's 8:00!") ``` Example 4 — A night light: on from 10 PM until 6 AM, using HH with \>= and \< instead of ==. ```tinkerpy setup: clock_start(0, 0, 0) loop: if HH >= 22 or HH < 6: o1 = pwm(100) else: o1 = 0 ``` clock_speed(real_ms_per_second) Needs: `import clock` Changes how fast the clock runs — how many real milliseconds count as 1 simulated second. | | | |----------------------|------------------------------------------------------------| | `real_ms_per_second` | 1000 = real time. Smaller = faster (e.g. 100 = 10x speed). 1–32767. | Example 1 — Runs the clock 10x faster than real time — handy for testing. ```tinkerpy setup: clock_start(0, 0, 0) clock_speed(100) ``` Example 2 — Runs at true real-time speed — 1 real second = 1 clock second. ```tinkerpy setup: clock_start(0, 0, 0) clock_speed(1000) ``` Example 3 — Runs at half speed — 2 real seconds pass for every 1 clock second. ```tinkerpy setup: clock_start(0, 0, 0) clock_speed(2000) ``` clock_pause() Needs: `import clock` Freezes the clock exactly where it is. Example 1 — A button freezes the clock, like a stopwatch. ```tinkerpy setup: clock_start(0, 0, 0) loop: if i1 == ON: clock_pause() ``` Example 2 — Stops itself once 5 minutes have passed. ```tinkerpy setup: clock_start(0, 5, 0) loop: if MM >= 5: clock_pause() ``` clock_resume() Needs: `import clock` Starts the clock ticking again after clock_pause(). Example 1 — A button starts the clock running again. ```tinkerpy setup: clock_start(0, 0, 0) loop: clock_pause() if i1 == ON: clock_resume() ``` Example 2 — One button pauses, another resumes — like a real stopwatch. ```tinkerpy setup: clock_start(0, 0, 0) loop: if i1 == ON: clock_pause() if i2 == ON: clock_resume() ``` ### Bluetooth & IoT Function bluetooth_begin() Needs: `import bluetooth` Switches Bluetooth on when the board starts. Goes inside setup: — every Bluetooth program needs it (the editor adds it for you). Example 1 — Bluetooth starts once at power-on, then the loop reacts to the app. ```tinkerpy setup: bluetooth_begin() loop: if bluetooth_read_char() == 'A': o1 = ON ``` Example 2 — Starts Bluetooth with your own password. ```tinkerpy setup: bluetooth_begin() set_device_password("5678") ``` Example 3 — Says hello to the app every second. ```tinkerpy setup: bluetooth_begin() loop: bluetooth_write("hello") wait(1000) ``` bluetooth_connected() Needs: `import bluetooth` · Firmware: 2.15+ Gives 1 while a phone or app is connected (and gave the password), otherwise 0. Needs firmware 2.15+. Example 1 — Safety stop: the robot stops if the phone disconnects. ```tinkerpy if bluetooth_connected() == 0: robot_control("S", 0, "S", 0) ``` Example 2 — A blue light that shows when the app is connected. ```tinkerpy if bluetooth_connected() == 1: o1 = ON else: o1 = OFF ``` Example 3 — Waits for the app before the project starts. ```tinkerpy while bluetooth_connected() == 0: oled_write(1, left, small, regular, "Connect app") wait(500) oled_clear() ``` bluetooth_write(value) Needs: `import bluetooth` Sends to the app over Bluetooth: a letter ('A'), text ("hello") or a number / variable (temp). **Up to 3 numbers / variables in one message** (firmware 2.24+): `bluetooth_write(angle, distance())` sends "90,35", `bluetooth_write(a, b, c)` sends "a,b,c" — no text in this form. The same message twice in a row is sent once. | | | |---------|-----------------------------------------------------------------------| | `value` | A letter in quotes, text up to 32 characters, or a number / variable. | | `a, b, c` | 2 or 3 numbers / variables, sent together as "a,b" or "a,b,c". | Example 1 — Sends the text hello. ```tinkerpy bluetooth_write("hello") ``` Example 2 — Sends the temperature as a number, e.g. 25. ```tinkerpy t = dht_temperature(i1) bluetooth_write(t) ``` Example 3 — Sends the letter B when the button is pressed. ```tinkerpy if i1 == ON: bluetooth_write('B') ``` bluetooth_read_char() Needs: `import bluetooth` · Firmware: 2.18+ The letter the app sent (like a button tap). It lasts one loop cycle, then gives None until the next letter arrives. Example 1 — Turns o1 on when the letter F arrives. ```tinkerpy if bluetooth_read_char() == 'F': o1 = ON ``` Example 2 — Two buttons in the app: 1 = on, 0 = off. ```tinkerpy c = bluetooth_read_char() if c == '1': o1 = ON elif c == '0': o1 = OFF ``` Example 3 — Answers every letter that arrives. ```tinkerpy if bluetooth_read_char() != None: bluetooth_write("got it") ``` bluetooth_read_string() Needs: `import bluetooth` · Firmware: 2.18+ Text the app sent (up to 32 characters), for one loop cycle. Compare it, show it, send it, or keep it in a text variable (msg = …) so it stays after that cycle. Example 1 — Opens the door when the app sends the word open. ```tinkerpy if bluetooth_read_string() == "open": o1 = servo_angle(90) ``` Example 2 — Shows any text from the app on the LCD. ```tinkerpy setup: lcd_begin() lcd_write(1, 1, bluetooth_read_string()) ``` Example 3 — Answers ok to every text. ```tinkerpy if bluetooth_read_string() != None: bluetooth_write("ok") ``` bluetooth_read_number() Needs: `import bluetooth` · Firmware: 2.18+ A number the app sent (like a slider), for one loop cycle — then None until a new one arrives. Example 1 — A slider in the app sets the brightness of o1. ```tinkerpy n = bluetooth_read_number() if n != None: o1 = pwm(n) ``` Example 2 — The app turns a servo to any angle. ```tinkerpy n = bluetooth_read_number() if n != None: o2 = servo_angle(n) ``` Example 3 — Sends back double the number. ```tinkerpy n = bluetooth_read_number() if n != None: bluetooth_write(n * 2) ``` x, y = bluetooth_read_position() Needs: `import bluetooth` · Firmware: 2.18+ A position from the app: x and y, each −100 to 100 — or x, y, d with its data number (0 if the app sent none; Hand Tracker 2 sends the gesture). None when nothing new arrived this cycle. Example 1 — Pushing the joystick up makes o1 brighter. ```tinkerpy x, y = bluetooth_read_position() if y != None: o1 = pwm(y) ``` Example 2 — Left / right on the joystick turns a servo. ```tinkerpy x, y = bluetooth_read_position() if x != None: o2 = servo_angle(90 + x) ``` Example 3 — Joystick forward drives the robot forward. ```tinkerpy x, y = bluetooth_read_position() if y != None and y > 50: robot_control("F", 80, "F", 80) ``` Example 4 — With its data (Hand Tracker 2 sends the gesture as d): 1 = light on, 2 = light off. ```tinkerpy x, y, d = bluetooth_read_position() if d == 1: o1 = ON elif d == 2: o1 = OFF ``` r, g, b = bluetooth_read_rgb() Needs: `import bluetooth` · Firmware: 2.18+ A colour from the app’s colour picker: red, green, blue, each 0–255. None, None, None when nothing new arrived this cycle. Example 1 — The RGB LEDs take the colour picked in the app. ```tinkerpy r, g, b = bluetooth_read_rgb() if r != None: rgb_hex_color(o1, all, r, g, b) ``` Example 2 — Uses only the red part to dim a lamp. ```tinkerpy r, g, b = bluetooth_read_rgb() if r != None: o1 = pwm(r * 100 / 255) ``` Example 3 — Says thank you for the colour. ```tinkerpy r, g, b = bluetooth_read_rgb() if r != None: bluetooth_write("colour set") ``` set_device_password("1234") Needs: `import bluetooth` · Firmware: 2.13+ Sets the board’s Bluetooth password (4 digits) and saves it. Needs firmware 2.13+. | | | |------------|-------------------------------------------------------------------------------------------| | `password` | Exactly 4 digits in quotes, e.g. "5678". Phones and the editor must type this to connect. | Example 1 — Gives the board your own password once, when the program starts. ```tinkerpy setup: set_device_password("5678") ``` Example 2 — Changes the password when the button is pressed. ```tinkerpy if i1 == ON: set_device_password("2468") ``` Example 3 — Safe inside the loop — the board only saves it when it really changes. ```tinkerpy setup: set_device_password("5678") loop: bluetooth_write("ready") ``` iot_write(value) Needs: `import iot` · Firmware: 2.18+ Sends to the app over the internet: a letter ('A'), text ("hello") or a number / variable (temp). **Up to 3 numbers / variables in one message** (firmware 2.24+): `iot_write(angle, distance())` sends "90,35", `iot_write(a, b, c)` sends "a,b,c" — no text in this form. The same message twice in a row is sent once. | | | |---------|-----------------------------------------------------------------------| | `value` | A letter in quotes, text up to 32 characters, or a number / variable. | | `a, b, c` | 2 or 3 numbers / variables, sent together as "a,b" or "a,b,c". | Example 1 — Sends the text hello. ```tinkerpy iot_write("hello") ``` Example 2 — Sends the temperature as a number, e.g. 25. ```tinkerpy t = dht_temperature(i1) iot_write(t) ``` Example 3 — Sends the letter B when the button is pressed. ```tinkerpy if i1 == ON: iot_write('B') ``` iot_read_char() Needs: `import iot` · Firmware: 2.18+ The letter the app sent (like a button tap). It lasts one loop cycle, then gives None until the next letter arrives. Example 1 — Turns o1 on when the letter F arrives. ```tinkerpy if iot_read_char() == 'F': o1 = ON ``` Example 2 — Two buttons in the app: 1 = on, 0 = off. ```tinkerpy c = iot_read_char() if c == '1': o1 = ON elif c == '0': o1 = OFF ``` Example 3 — Answers every letter that arrives. ```tinkerpy if iot_read_char() != None: iot_write("got it") ``` iot_read_string() Needs: `import iot` · Firmware: 2.18+ Text the app sent (up to 32 characters), for one loop cycle. Compare it, show it, send it, or keep it in a text variable (msg = …) so it stays after that cycle. Example 1 — Opens the door when the app sends the word open. ```tinkerpy if iot_read_string() == "open": o1 = servo_angle(90) ``` Example 2 — Shows any text from the app on the LCD. ```tinkerpy setup: lcd_begin() lcd_write(1, 1, iot_read_string()) ``` Example 3 — Answers ok to every text. ```tinkerpy if iot_read_string() != None: iot_write("ok") ``` iot_read_number() Needs: `import iot` · Firmware: 2.18+ A number the app sent (like a slider), for one loop cycle — then None until a new one arrives. Example 1 — A slider in the app sets the brightness of o1. ```tinkerpy n = iot_read_number() if n != None: o1 = pwm(n) ``` Example 2 — The app turns a servo to any angle. ```tinkerpy n = iot_read_number() if n != None: o2 = servo_angle(n) ``` Example 3 — Sends back double the number. ```tinkerpy n = iot_read_number() if n != None: iot_write(n * 2) ``` x, y = iot_read_position() Needs: `import iot` · Firmware: 2.18+ A position from the app: x and y, each −100 to 100 — or x, y, d with its data number (0 if the app sent none; Hand Tracker 2 sends the gesture). None when nothing new arrived this cycle. Example 1 — Pushing the joystick up makes o1 brighter. ```tinkerpy x, y = iot_read_position() if y != None: o1 = pwm(y) ``` Example 2 — Left / right on the joystick turns a servo. ```tinkerpy x, y = iot_read_position() if x != None: o2 = servo_angle(90 + x) ``` Example 3 — Joystick forward drives the robot forward. ```tinkerpy x, y = iot_read_position() if y != None and y > 50: robot_control("F", 80, "F", 80) ``` Example 4 — With its data (Hand Tracker 2 sends the gesture as d): 1 = light on, 2 = light off. ```tinkerpy x, y, d = iot_read_position() if d == 1: o1 = ON elif d == 2: o1 = OFF ``` r, g, b = iot_read_rgb() Needs: `import iot` · Firmware: 2.18+ A colour from the app’s colour picker: red, green, blue, each 0–255. None, None, None when nothing new arrived this cycle. Example 1 — The RGB LEDs take the colour picked in the app. ```tinkerpy r, g, b = iot_read_rgb() if r != None: rgb_hex_color(o1, all, r, g, b) ``` Example 2 — Uses only the red part to dim a lamp. ```tinkerpy r, g, b = iot_read_rgb() if r != None: o1 = pwm(r * 100 / 255) ``` Example 3 — Says thank you for the colour. ```tinkerpy r, g, b = iot_read_rgb() if r != None: iot_write("colour set") ``` ### Robot Function robot_control(left_dir, left_speed, right_dir, right_speed) Needs: `import motor` Drives both of the rover’s motors at once — one call expresses any movement: straight, reverse, a spin-in-place turn, a curve at any ratio, a full stop, or leaving one motor exactly as it was. | | | |---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `left_dir` | "F" (forward), "B" (backward), "S" (stop — forces this motor to 0 even if a speed is given), or "X" (do not disturb — leaves this motor completely untouched, pwm ignored). Always in quotes. | | `left_speed` | 0–100 — the left wheel’s speed. Ignored if left_dir is "S" or "X". | | `right_dir` | Same four options as left_dir, for the right wheel. | | `right_speed` | 0–100 — the right wheel’s speed. Ignored if right_dir is "S" or "X". | Example 1 — Both wheels forward, full speed — drives straight ahead. ```tinkerpy robot_control("F", 100, "F", 100) ``` Example 2 — Both wheels backward, full speed — reverses straight. ```tinkerpy robot_control("B", 100, "B", 100) ``` Example 3 — Left backward, right forward — spins in place, turning left. ```tinkerpy robot_control("B", 100, "F", 100) ``` Example 4 — Left forward, right backward — spins in place, turning right. ```tinkerpy robot_control("F", 100, "B", 100) ``` Example 5 — Both forward, but the right wheel is faster — arcs left while still moving. ```tinkerpy robot_control("F", 60, "F", 100) ``` Example 6 — Both forward, left wheel faster — arcs right while still moving. ```tinkerpy robot_control("F", 100, "F", 60) ``` Example 7 — A slow, gentle crawl forward — useful for careful maneuvering. ```tinkerpy robot_control("F", 30, "F", 30) ``` Example 8 — Obstacle avoidance: backs away from anything closer than 20cm, otherwise drives forward. ```tinkerpy if distance() < 20: robot_control("B", 60, "B", 60) else: robot_control("F", 80, "F", 80) ``` Example 9 — A button acts like a dead-man’s switch — the robot only moves while it’s held down. ```tinkerpy if i1 == ON: robot_control("F", 100, "F", 100) else: robot_control("F", 0, "F", 0) ``` Example 10 — Drives forward, then spins a quarter turn, four times in a row — traces out a rough square. ```tinkerpy repeat(4): robot_control("F", 100, "F", 100) wait(1000) robot_control("B", 100, "F", 100) wait(500) ``` Example 11 — Ramps smoothly from a stop up to full speed, 10% at a time, using a variable instead of a fixed number. ```tinkerpy speed = 0 repeat(10): speed = speed + 10 robot_control("F", speed, "F", speed) wait(200) ``` Example 12 — Both reversing, but the LEFT wheel is faster this time — curves right while backing up (curving while reversing flips which side is "faster", compared to driving forward). ```tinkerpy robot_control("B", 100, "B", 60) ``` Example 13 — A simple line-follower shape: drives straight when both sensors agree, leans toward whichever sensor is off, stops if neither is triggered. ```tinkerpy if i1 == ON and i2 == ON: robot_control("F", 80, "F", 80) elif i1 == ON: robot_control("F", 40, "F", 80) elif i2 == ON: robot_control("F", 80, "F", 40) else: robot_control("F", 0, "F", 0) ``` Example 14 — Stops both motors completely — the same as robot_control("F", 0, "F", 0), just more explicit about the intent. ```tinkerpy robot_control("S", 0, "S", 0) ``` Example 15 — Controls only the LEFT motor with a button — "X" leaves the right motor completely alone, whatever it was already doing. ```tinkerpy if i1 == ON: robot_control("F", 70, "X", 0) else: robot_control("S", 0, "X", 0) ``` motor_control_right(direction, speed) Needs: `import motor` Drives just the RIGHT motor — the same o3/o4 pins robot_control(...) uses for its right side, controlled on their own instead of alongside the left motor. | | | |-------------|-------------------------------------------------------------------------------------------------------------------| | `direction` | "F" (forward), "B" (backward), or "S" (stop — forces this motor to 0 even if a speed is given). Always in quotes. | | `speed` | 0–100 — the wheel’s speed. Ignored if direction is "S". | Example 1 — Right wheel forward at 70% speed. ```tinkerpy motor_control_right("F", 70) ``` Example 2 — Stops just the right motor. ```tinkerpy motor_control_right("S", 0) ``` Example 3 — Right forward, left backward — spins in place, using two separate calls instead of one robot_control(...). ```tinkerpy motor_control_right("F", 60) motor_control_left("B", 60) ``` motor_control_left(direction, speed) Needs: `import motor` Drives just the LEFT motor — the same o5/o6 pins robot_control(...) uses for its left side, controlled on their own instead of alongside the right motor. | | | |-------------|-------------------------------------------------------------------------------------------------------------------| | `direction` | "F" (forward), "B" (backward), or "S" (stop — forces this motor to 0 even if a speed is given). Always in quotes. | | `speed` | 0–100 — the wheel’s speed. Ignored if direction is "S". | Example 1 — Left wheel forward at 70% speed. ```tinkerpy motor_control_left("F", 70) ``` Example 2 — Stops just the left motor. ```tinkerpy motor_control_left("S", 0) ``` Example 3 — A button controls just the left wheel, independent of whatever the right wheel is doing. ```tinkerpy if i1 == ON: motor_control_left("F", 50) else: motor_control_left("S", 0) ``` ## 5.3 Firmware needed The board must have this firmware (or newer) for a program that uses the feature. TinkerPy Code shows the needed version when uploading. The newest board firmware is **2.26** (the board password for WiFi upload too, shown on the CODE DOWNLOAD screens; 2.25 added wireless_iot — board to board over the internet; 2.24 added voltage(), text variables, joining text with + and wireless board to board), so update boards to 2.25. Upload checks the board’s live firmware and says so when it is too old. | Firmware | Adds | |----------|-----------------------------------------------------------------------------------------| | 2.13 | set_device_password | | 2.14 | servo_flip | | 2.15 | random, while, break, analog_read, bluetooth_connected | | 2.16 | OLED and LCD functions (oled\_…, lcd\_…) | | 2.17 | RGB LEDs (rgb\_…) | | 2.18 | bluetooth_read_number / string / position / rgb, iot_read\_…, iot_write(text), joystick | | 2.19 | buzzer_play, TV remote, OLED eye / emoji animations, position data | | 2.20 | oled_write(line, align, size, weight, value) | | 2.23 | TV remote: the 29 general keys (remote_read) and remote_read_string — learn the remote again after updating | | 2.24 | voltage() (volts 0.00 – 3.30, decimals like 1.6), Debug → Analog Input, text variables, joining with +, wireless (import wireless: TP00000002.connect() / send / read …, wireless_send_all, wireless_read_any) | | 2.25 | wireless_iot (import wireless_iot: TP00000002_iot.connect() / send / read …, wireless_iot_send_all, wireless_iot_read_any — board to board over the internet) | | 2.26 | invert(o2) (reading an output back), WiFi upload asks for the board password (the 4 digits on the CODE DOWNLOAD screen, the same as Bluetooth); set_device_password("5678") changes it (was bluetooth_password) | | 2.29 | buzzer_play_background, buzzer_stop_background, is_buzzer_playing (TinkerPy Mega) | # Part 6 — Complete example projects 45 complete programs, each checked by the real TinkerPy compiler. Use them as patterns for structure, wiring and style. ## Basic ### Blink an LED The classic first project: an LED turns on and off every half second. Wiring: LED on o1 (long leg to o1, short leg to GND). ```tinkerpy # ===== Blink an LED ===== # LED on o1 # This code block executes forever loop: o1 = ON wait(500) o1 = OFF wait(500) ``` ### Push Button Light Hold the button and the LED glows. Let go and it switches off. Wiring: Push button on i1, LED on o1. ```tinkerpy # ===== Push Button Light ===== # Button on i1, LED on o1 loop: if i1 == ON: o1 = ON else: o1 = OFF ``` ### Traffic Light Red, yellow and green LEDs change just like a real traffic signal. Wiring: Red LED on o1, yellow LED on o2, green LED on o3. ```tinkerpy # ===== Traffic Light ===== # Red o1, Yellow o2, Green o3 loop: # Red - stop o1 = ON wait(4000) o1 = OFF # Green - go o3 = ON wait(4000) o3 = OFF # Yellow - get ready to stop o2 = ON wait(1500) o2 = OFF ``` ### Breathing LED The LED slowly fades in and out, like it is breathing. Wiring: LED on o1. ```tinkerpy # ===== Breathing LED ===== # LED on o1 fades in and out loop: output_increment_till(o1, 0, 100, 5, 40) output_decrement_till(o1, 100, 0, 5, 40) wait(300) ``` ### Toggle Switch Press the button once to switch the light on, press again to switch it off. Wiring: Push button on i1, LED on o1. ```tinkerpy # ===== Toggle Switch ===== # Each press of i1 flips the LED on o1 loop: if i1 == ON: output_flip(o1, 0, 100) # wait until the button is let go, so one press = one flip wait(300) ``` ## Servo ### Servo Sweep The servo arm sweeps smoothly from 0° to 180° and back again. Wiring: Servo signal wire on o1 (brown/black to GND, red to 5V). ```tinkerpy # ===== Servo Sweep ===== # Servo on o1 import servo setup: o1 = set_function(servo) # servo loop: servo_increment_till(o1, 0, 180, 5, 20) servo_decrement_till(o1, 180, 0, 5, 20) ``` ### Button Gate Press the button to open the gate. It closes again after 3 seconds. Wiring: Servo (the gate arm) on o1, push button on i1. ```tinkerpy # ===== Button Gate ===== # Servo gate on o1, button on i1 import servo setup: o1 = set_function(servo) # servo servo_write_angle(o1, 0) loop: if i1 == ON: servo_write_angle(o1, 90) wait(3000) servo_write_angle(o1, 0) ``` ### Radar Scanner The servo scans left and right forever, like a radar dish. Wiring: Servo on o1. ```tinkerpy # ===== Radar Scanner ===== # Servo on o1 scans by itself import servo setup: o1 = set_function(servo) # servo servo_scan_on(o1, 0, 180, 5, 20) loop: wait(1000) ``` ### Waving Robot Hand A cardboard hand on the servo waves hello three times when you press the button. Wiring: Servo with a cardboard hand on o1, push button on i1. ```tinkerpy # ===== Waving Robot Hand ===== # Servo hand on o1, button on i1 import servo setup: o1 = set_function(servo) # servo servo_write_angle(o1, 90) loop: if i1 == ON: repeat(3): servo_write_angle(o1, 45) wait(300) servo_write_angle(o1, 135) wait(300) servo_write_angle(o1, 90) ``` ### Mirror Servos Two servos move like a pair of wings: when one goes up, the other goes down. Wiring: Servo 1 on o1, servo 2 on o2. ```tinkerpy # ===== Mirror Servos ===== # Servos on o1 and o2 move like wings import servo setup: o1 = set_function(servo) # servo o2 = set_function(servo) # servo servo_sync_reverse(o1, o2) loop: servo_increment_till(o1, 30, 150, 5, 25) servo_decrement_till(o1, 150, 30, 5, 25) ``` ## Ultrasonic ### Distance Alarm A buzzer beeps when something comes closer than 20 cm. Wiring: Ultrasonic sensor: Trig on i3, Echo on i4. Buzzer on o1. ```tinkerpy # ===== Distance Alarm ===== # Ultrasonic (Trig i3, Echo i4), buzzer on o1 import ultrasonic setup: i3 = set_function(ultrasonic_TX) # cannot be changed i4 = set_function(ultrasonic_RX) # cannot be changed loop: if distance() < 20: o1 = ON else: o1 = OFF ``` ### Parking Sensor Beeps faster and faster as a car gets closer to the wall, just like a real parking sensor. Wiring: Ultrasonic sensor: Trig on i3, Echo on i4. Buzzer on o1. ```tinkerpy # ===== Parking Sensor ===== # Ultrasonic (Trig i3, Echo i4), buzzer on o1 import ultrasonic setup: i3 = set_function(ultrasonic_TX) # cannot be changed i4 = set_function(ultrasonic_RX) # cannot be changed loop: d = distance() if d < 10: o1 = ON elif d < 30: o1 = ON wait(100) o1 = OFF wait(100) elif d < 60: o1 = ON wait(100) o1 = OFF wait(400) else: o1 = OFF ``` ### Smart Dustbin The dustbin lid opens by itself when your hand comes near, then closes. Wiring: Ultrasonic sensor: Trig on i3, Echo on i4 (facing up). Servo for the lid on o1. ```tinkerpy # ===== Smart Dustbin ===== # Ultrasonic (Trig i3, Echo i4), lid servo on o1 import ultrasonic import servo setup: o1 = set_function(servo) # servo i3 = set_function(ultrasonic_TX) # cannot be changed i4 = set_function(ultrasonic_RX) # cannot be changed servo_write_angle(o1, 0) loop: if distance() < 15: servo_write_angle(o1, 100) wait(3000) servo_write_angle(o1, 0) ``` ### Water Tank Level Shows how full a water tank is with 3 LEDs. The sensor looks down at the water. Wiring: Ultrasonic sensor at the top of the tank: Trig on i3, Echo on i4. LEDs on o1 (low), o2 (half), o3 (full). ```tinkerpy # ===== Water Tank Level ===== # Ultrasonic looks down at the water; LEDs o1 o2 o3 import ultrasonic setup: i3 = set_function(ultrasonic_TX) # cannot be changed i4 = set_function(ultrasonic_RX) # cannot be changed loop: # small distance = water is near the top = tank is full d = distance() o1 = ON if d < 20: o2 = ON else: o2 = OFF if d < 8: o3 = ON else: o3 = OFF wait(500) ``` ### Touchless Hand Wash A small pump runs for 2 seconds when hands come under the tap. No touching needed! Wiring: Ultrasonic sensor under the tap: Trig on i3, Echo on i4. Small 5V pump (through a driver) on o1. ```tinkerpy # ===== Touchless Hand Wash ===== # Ultrasonic (Trig i3, Echo i4), pump on o1 import ultrasonic setup: i3 = set_function(ultrasonic_TX) # cannot be changed i4 = set_function(ultrasonic_RX) # cannot be changed loop: if distance() < 12: o1 = ON wait(2000) o1 = OFF # wait for the hands to move away wait(1500) ``` ## Wireless (two boards) Each program goes to its own board; each lists the OTHER board’s ID. Firmware 2.24. ### Wireless Doorbell — button board Press the button: the other board rings. A warning LED shows when the bell board did not get it. Wiring: Push button on i1, LED on o1. Board TP00000001. ```tinkerpy # ===== Wireless Doorbell — the button board (TP00000001) ===== # Button on i1. Upload this to TP00000001. import wireless setup: TP00000002.connect() # the bell board loop: if i1 == ON: ok = TP00000002.send("RING") if ok == 0: o1 = ON # not delivered: warning LED else: o1 = OFF wait(300) ``` ### Wireless Doorbell — bell board Rings and shows “Visitor!” when the button board sends RING. Wiring: Passive buzzer on o1, OLED (SDA o7, SCL o8). Board TP00000002. ```tinkerpy # ===== Wireless Doorbell — the bell board (TP00000002) ===== # Passive buzzer on o1, OLED. Upload this to TP00000002. import wireless setup: TP00000001.connect() # the button board o1 = set_function(passive_buzzer) oled_begin() loop: msg = TP00000001.read() if msg == "RING": oled_write(1, center, medium, bold, "Visitor!") buzzer_play(o1, "door_bell") if TP00000001.connected() == 0: oled_write(4, left, small, regular, "Waiting for button") ``` ## Wireless IoT (two boards over the internet) Each program goes to its own board; each lists the OTHER board’s ID with _iot. Both boards need WiFi. Firmware 2.25. ### Internet Doorbell — button board Press the button: the other board rings, wherever it is. An LED shows when the bell board is offline. Wiring: Push button on i1, LED on o1. Board TP00000001. ```tinkerpy # ===== Internet Doorbell — the button board (TP00000001) ===== # Button on i1. Upload this to TP00000001. Both boards need WiFi. import wireless_iot setup: TP00000002_iot.connect() # the bell board, anywhere loop: if i1 == ON: ok = TP00000002_iot.send("RING") if ok == 0: o1 = ON # the bell board is offline else: o1 = OFF wait(1000) ``` ### Internet Doorbell — bell board Rings and shows “Visitor!” when the button board sends RING. Wiring: Passive buzzer on o1, OLED (SDA o7, SCL o8). Board TP00000002. ```tinkerpy # ===== Internet Doorbell — the bell board (TP00000002) ===== # Passive buzzer on o1, OLED. Upload this to TP00000002. import wireless_iot setup: TP00000001_iot.connect() # the button board o1 = set_function(passive_buzzer) oled_begin() loop: msg = TP00000001_iot.read() if msg == "RING": oled_write(1, center, medium, bold, "Visitor!") buzzer_play(o1, "door_bell") if TP00000001_iot.connected() == 0: oled_write(4, left, small, regular, "Button board offline") ``` ## Clock ### Digital Clock Shows the time (hours, minutes, seconds) on the OLED display. Wiring: 0.96" OLED display (SDA o7, SCL o8). Change the start time in setup. · Firmware 2.20+ ```tinkerpy # ===== Digital Clock ===== # Set the start time below, shown on the OLED import clock import oled_display setup: oled_begin() # starts the OLED o7 = set_function(SDA) # cannot be changed o8 = set_function(SCL) # cannot be changed clock_start(10, 30, 0) loop: oled_write(1, left, small, regular, "Time now") oled_write(2, left, small, regular, HH) oled_write(3, left, small, regular, MM) oled_write(4, left, small, regular, SS) wait(500) ``` ### School Bell Rings a bell (buzzer) at the start of each period: 9:00, 9:45 and 10:30. Wiring: Buzzer on o1. Set the clock to the real time in setup. ```tinkerpy # ===== School Bell ===== # Buzzer on o1 rings at period times import clock setup: clock_start(8, 59, 50) loop: if SS == 0: if HH == 9 and MM == 0: o1 = ON wait(3000) o1 = OFF if HH == 9 and MM == 45: o1 = ON wait(3000) o1 = OFF if HH == 10 and MM == 30: o1 = ON wait(3000) o1 = OFF wait(500) ``` ### Night Lamp The lamp switches on by itself at 7 PM and off at 6 AM. Wiring: Lamp/LED on o1. Set the clock to the real time in setup. ```tinkerpy # ===== Night Lamp ===== # Lamp on o1, on from 7 PM to 6 AM import clock setup: clock_start(18, 59, 50) loop: if HH >= 19 or HH < 6: o1 = ON else: o1 = OFF wait(1000) ``` ### Plant Watering Timer Waters the plants for 10 seconds every morning at 7:00. Wiring: Small water pump (through a driver) on o1. Set the clock to the real time in setup. ```tinkerpy # ===== Plant Watering Timer ===== # Pump on o1 runs at 7:00 every day import clock setup: clock_start(6, 59, 50) loop: if HH == 7 and MM == 0 and SS == 0: o1 = ON wait(10000) o1 = OFF wait(500) ``` ### Stopwatch Button i1 starts and stops the stopwatch, button i2 resets it to zero. Wiring: Start/stop button on i1, reset button on i2, OLED display (SDA o7, SCL o8). · Firmware 2.20+ ```tinkerpy # ===== Stopwatch ===== # i1 start/stop, i2 reset, time on the OLED import clock import oled_display setup: oled_begin() # starts the OLED o7 = set_function(SDA) # cannot be changed o8 = set_function(SCL) # cannot be changed clock_start(0, 0, 0) clock_pause() running = 0 loop: if i1 == ON: if running == 0: clock_resume() running = 1 else: clock_pause() running = 0 wait(300) if i2 == ON: clock_start(0, 0, 0) clock_pause() running = 0 oled_write(1, left, small, regular, "Stopwatch") oled_write(2, left, small, regular, MM) oled_write(3, left, small, regular, SS) wait(100) ``` ## OLED ### Hello Display Your first OLED project: shows a greeting on the screen. Wiring: 0.96" OLED display (SDA o7, SCL o8). · Firmware 2.20+ ```tinkerpy # ===== Hello Display ===== # OLED on o7 (SDA) / o8 (SCL) import oled_display setup: oled_begin() # starts the OLED o7 = set_function(SDA) # cannot be changed o8 = set_function(SCL) # cannot be changed oled_write(1, center, medium, bold, "Hello!") # big + bold, uses lines 1-2 oled_write(3, center, small, regular, "I am TinkerPy") oled_write(4, center, small, regular, "Let's build!") loop: wait(1000) ``` ### Button Counter Counts how many times the button is pressed and shows the number. Wiring: Push button on i1 (count), i2 (reset). OLED display (SDA o7, SCL o8). · Firmware 2.20+ ```tinkerpy # ===== Button Counter ===== # i1 counts, i2 resets, number on the OLED import oled_display import counter setup: oled_begin() # starts the OLED o7 = set_function(SDA) # cannot be changed o8 = set_function(SCL) # cannot be changed oled_write(1, left, small, bold, "Presses:") loop: if i1 == ON: c1.increment() wait(250) if i2 == ON: c1.clear() oled_write(2, center, large, bold, c1) # a big number on lines 2-3 ``` ### Distance Meter A digital measuring tape: shows the distance in cm on the screen. Wiring: Ultrasonic sensor: Trig on i3, Echo on i4. OLED display (SDA o7, SCL o8). · Firmware 2.20+ ```tinkerpy # ===== Distance Meter ===== # Ultrasonic (Trig i3, Echo i4) + OLED import oled_display import ultrasonic setup: oled_begin() # starts the OLED i3 = set_function(ultrasonic_TX) # cannot be changed i4 = set_function(ultrasonic_RX) # cannot be changed o7 = set_function(SDA) # cannot be changed o8 = set_function(SCL) # cannot be changed oled_write(1, center, small, bold, "Distance (cm)") loop: oled_write(2, center, large, bold, distance()) # a big number on lines 2-3 wait(300) ``` ### Weather Station Shows the room temperature and humidity from a DHT11 sensor. Wiring: DHT11 sensor data pin on i3. OLED display (SDA o7, SCL o8). · Firmware 2.20+ ```tinkerpy # ===== Weather Station ===== # DHT11 on i3, readings on the OLED import oled_display import dht11 setup: oled_begin() # starts the OLED i3 = set_function(dht11) o7 = set_function(SDA) # cannot be changed o8 = set_function(SCL) # cannot be changed loop: oled_write(1, left, small, bold, "Temp (C)") oled_write(2, right, small, regular, dht_temperature(i3)) oled_write(3, left, small, bold, "Humidity (%)") oled_write(4, right, small, regular, dht_humidity(i3)) wait(2000) ``` ### Countdown Timer Press the button to start a 10-second countdown. A buzzer beeps at zero. Wiring: Start button on i1, buzzer on o1, OLED display (SDA o7, SCL o8). · Firmware 2.20+ ```tinkerpy # ===== Countdown Timer ===== # i1 starts, buzzer on o1, OLED shows the count import oled_display import counter setup: oled_begin() # starts the OLED o7 = set_function(SDA) # cannot be changed o8 = set_function(SCL) # cannot be changed c1.set(10) oled_write(1, center, small, regular, "Press to start") loop: if i1 == ON: c1.set(10) c1.auto_decrement(1000) oled_write(1, center, small, regular, "Counting down") oled_write(2, center, large, bold, c1) # a big number on lines 2-3 if c1 == 0: c1.pause() oled_write(1, center, small, bold, "Time up!") o1 = ON wait(1000) o1 = OFF c1.set(10) ``` ## Bluetooth ### Bluetooth Light Switch an LED on and off from your phone with Bluetooth. Wiring: LED on o1. Connect with the TinkerPy App and send 1 (on) or 0 (off). · Firmware 2.18+ ```tinkerpy # ===== Bluetooth Light ===== # Send 1 / 0 from the TinkerPy App import bluetooth setup: bluetooth_begin() # switches Bluetooth on when the board starts loop: bt_data = bluetooth_read_char() if bt_data == '1': o1 = ON elif bt_data == '0': o1 = OFF ``` ### Bluetooth Robot Car Drive the robot car from your phone: F, B, L, R and S (stop). Wiring: Motors on o3–o6 (motor driver). Use the arrow buttons in the TinkerPy App. · Firmware 2.18+ ```tinkerpy # ===== Bluetooth Robot Car ===== # F B L R S from the TinkerPy App import bluetooth import motor setup: o3 = set_function(motor_right_forward) # cannot be changed o4 = set_function(motor_right_backward) # cannot be changed o5 = set_function(motor_left_forward) # cannot be changed o6 = set_function(motor_left_backward) # cannot be changed bluetooth_begin() # switches Bluetooth on when the board starts loop: bt_data = bluetooth_read_char() if bt_data == 'F': robot_control("F", 80, "F", 80) elif bt_data == 'B': robot_control("B", 80, "B", 80) elif bt_data == 'L': robot_control("B", 70, "F", 70) elif bt_data == 'R': robot_control("F", 70, "B", 70) elif bt_data == 'S': robot_control("S", 0, "S", 0) ``` ### Bluetooth Door Lock A servo locks and unlocks a door when the phone sends U (unlock) or L (lock). Wiring: Servo (the lock) on o1. Send U or L from the TinkerPy App. · Firmware 2.18+ ```tinkerpy # ===== Bluetooth Door Lock ===== # U unlocks, L locks; servo on o1 import bluetooth import servo setup: o1 = set_function(servo) # servo bluetooth_begin() # switches Bluetooth on when the board starts servo_write_angle(o1, 0) loop: bt_data = bluetooth_read_char() if bt_data == 'U': servo_write_angle(o1, 90) bluetooth_write("Door unlocked") elif bt_data == 'L': servo_write_angle(o1, 0) bluetooth_write("Door locked") ``` ### Bluetooth Doorbell Press the doorbell button and a message pops up on your phone. Wiring: Push button on i1, buzzer on o1. Open the TinkerPy App to see the messages. ```tinkerpy # ===== Bluetooth Doorbell ===== # Button i1 sends a message to the phone import bluetooth setup: bluetooth_begin() # switches Bluetooth on when the board starts loop: if i1 == ON: o1 = ON bluetooth_write("Someone is at the door!") wait(500) o1 = OFF wait(1000) ``` ### Bluetooth Fan Speed Choose the fan speed from your phone: 0 (off), 1 (slow), 2 (medium), 3 (fast). Wiring: Small DC fan (through a driver) on o1. Send 0–3 from the TinkerPy App. · Firmware 2.18+ ```tinkerpy # ===== Bluetooth Fan Speed ===== # Send 0, 1, 2 or 3 from the TinkerPy App import bluetooth setup: bluetooth_begin() # switches Bluetooth on when the board starts loop: bt_data = bluetooth_read_char() if bt_data == '0': o1 = pwm(0) elif bt_data == '1': o1 = pwm(40) elif bt_data == '2': o1 = pwm(70) elif bt_data == '3': o1 = pwm(100) ``` ## IoT ### IoT Light Switch Switch a light on and off from anywhere using the internet. Wiring: LED or relay on o1. Connect the TinkerPy App over IoT (Device ID + PIN) and send 1 / 0. · Firmware 2.18+ ```tinkerpy # ===== IoT Light Switch ===== # Send 1 / 0 from the TinkerPy App (IoT) import iot loop: iot_data = iot_read_char() if iot_data == '1': o1 = ON iot_write("Light is ON") elif iot_data == '0': o1 = OFF iot_write("Light is OFF") ``` ### IoT Door Alert Sends a message to the app whenever the door is opened. Wiring: Door switch (or button) on i1. Open the TinkerPy App (IoT) to see alerts. · Firmware 2.18+ ```tinkerpy # ===== IoT Door Alert ===== # Door switch on i1 sends an alert import iot loop: if i1 == ON: iot_write("Door opened!") wait(3000) ``` ### IoT Room Monitor Sends the room temperature and humidity to the app every 10 seconds. Wiring: DHT11 data pin on i3. The app shows channel 1 (temperature) and channel 2 (humidity). · Firmware 2.18+ ```tinkerpy # ===== IoT Room Monitor ===== # DHT11 on i3 → app channels 1 and 2 import iot import dht11 setup: i3 = set_function(dht11) loop: if dht_temperature(i3) > 30: iot_write("It is hot!") if dht_temperature(i3) > 25: iot_write("warm") else: iot_write("cool") if dht_humidity(i3) > 70: iot_write("humid") else: iot_write("dry") wait(10000) ``` ### IoT Smart Plug Turn a plug on or off from the app, or with the button on the board. Wiring: Relay module on o1, button on i1. Send 1 / 0 from the TinkerPy App (IoT). · Firmware 2.18+ ```tinkerpy # ===== IoT Smart Plug ===== # App 1/0 or button i1 switches the relay on o1 import iot loop: iot_data = iot_read_char() if iot_data == '1': o1 = ON iot_write("on") elif iot_data == '0': o1 = OFF iot_write("off") if i1 == ON: output_flip(o1, 0, 100) iot_write("Switched by button") wait(300) ``` ### IoT Garden Watering Start watering from the app (W), stop it (S). The app hears when the pump starts and stops. Wiring: Water pump (through a driver) on o1. Send W / S from the TinkerPy App (IoT). · Firmware 2.18+ ```tinkerpy # ===== IoT Garden Watering ===== # W starts, S stops the pump on o1 import iot loop: iot_data = iot_read_char() if iot_data == 'W': o1 = ON iot_write("Watering started") elif iot_data == 'S': o1 = OFF iot_write("Watering stopped") ``` ## Robotics ### Robot Dance The robot moves forward, back, and spins — a little dance! Wiring: Motors on o3–o6 through the motor driver. ```tinkerpy # ===== Robot Dance ===== # Motors on o3-o6 import motor setup: o3 = set_function(motor_right_forward) # cannot be changed o4 = set_function(motor_right_backward) # cannot be changed o5 = set_function(motor_left_forward) # cannot be changed o6 = set_function(motor_left_backward) # cannot be changed loop: robot_control("F", 70, "F", 70) wait(1000) robot_control("B", 70, "B", 70) wait(1000) robot_control("F", 70, "B", 70) wait(800) robot_control("B", 70, "F", 70) wait(800) robot_control("S", 0, "S", 0) wait(1500) ``` ### Obstacle Avoider The robot drives forward and turns away when something is in front of it. Wiring: Motors on o3–o6. Ultrasonic sensor at the front: Trig on i3, Echo on i4. ```tinkerpy # ===== Obstacle Avoider ===== # Motors o3-o6, ultrasonic Trig i3 / Echo i4 import motor import ultrasonic setup: o3 = set_function(motor_right_forward) # cannot be changed o4 = set_function(motor_right_backward) # cannot be changed o5 = set_function(motor_left_forward) # cannot be changed o6 = set_function(motor_left_backward) # cannot be changed i3 = set_function(ultrasonic_TX) # cannot be changed i4 = set_function(ultrasonic_RX) # cannot be changed loop: if distance() < 20: robot_control("S", 0, "S", 0) wait(200) robot_control("B", 60, "B", 60) wait(400) robot_control("F", 70, "B", 70) wait(500) else: robot_control("F", 70, "F", 70) ``` ### Line Follower Follows a black line on the floor using two IR sensors. Wiring: Motors on o3–o6. Left IR sensor on i1, right IR sensor on i2 (ON = sees the black line). ```tinkerpy # ===== Line Follower ===== # IR left i1, IR right i2, motors o3-o6 import motor setup: o3 = set_function(motor_right_forward) # cannot be changed o4 = set_function(motor_right_backward) # cannot be changed o5 = set_function(motor_left_forward) # cannot be changed o6 = set_function(motor_left_backward) # cannot be changed loop: if i1 == OFF and i2 == OFF: robot_control("F", 60, "F", 60) elif i1 == ON and i2 == OFF: # line is on the left - turn left robot_control("S", 0, "F", 60) elif i1 == OFF and i2 == ON: # line is on the right - turn right robot_control("F", 60, "S", 0) else: robot_control("S", 0, "S", 0) ``` ### Square Path The robot drives in a square: forward, turn, forward, turn… Wiring: Motors on o3–o6. Change the turn time until the robot turns exactly 90°. ```tinkerpy # ===== Square Path ===== # Motors on o3-o6 import motor setup: o3 = set_function(motor_right_forward) # cannot be changed o4 = set_function(motor_right_backward) # cannot be changed o5 = set_function(motor_left_forward) # cannot be changed o6 = set_function(motor_left_backward) # cannot be changed loop: repeat(4): robot_control("F", 70, "F", 70) wait(1500) robot_control("F", 70, "B", 70) wait(550) robot_control("S", 0, "S", 0) wait(3000) ``` ### Button Remote Robot Two buttons steer the robot: both = forward, one = turn that way. Wiring: Motors on o3–o6. Left button on i1, right button on i2. ```tinkerpy # ===== Button Remote Robot ===== # i1 + i2 steer, motors o3-o6 import motor setup: o3 = set_function(motor_right_forward) # cannot be changed o4 = set_function(motor_right_backward) # cannot be changed o5 = set_function(motor_left_forward) # cannot be changed o6 = set_function(motor_left_backward) # cannot be changed loop: if i1 == ON and i2 == ON: robot_control("F", 80, "F", 80) elif i1 == ON: robot_control("F", 30, "F", 80) elif i2 == ON: robot_control("F", 80, "F", 30) else: robot_control("S", 0, "S", 0) ``` ## Motion (MPU6050) ### Spirit Level Shows how much the board is tilted and lights an LED when it lies perfectly flat. Wiring: MPU6050 and OLED on o7 (SDA) / o8 (SCL), LED on o1. Keep the board still for the first second after power-on. · Firmware 2.20+ ```tinkerpy # ===== Spirit Level ===== # MPU6050 + OLED on o7/o8, LED on o1 import mpu6050 import oled_display setup: o7 = set_function(SDA) # cannot be changed o8 = set_function(SCL) # cannot be changed oled_begin() # starts the OLED loop: oled_clear() oled_write(1, left, small, regular, "Tilt front / side") oled_write(2, left, small, regular, tilt_x()) oled_write(3, left, small, regular, tilt_y()) if tilt_direction() == 'N': oled_write(4, left, small, regular, "Level!") o1 = ON else: oled_write(4, left, small, regular, "Tilted") o1 = OFF wait(200) ``` ### Exact Turn Robot The robot drives forward, then uses the gyro to turn exactly 90° — a perfect square every time. Wiring: MPU6050 on o7/o8 (flat on the robot), motors on o3–o6. ```tinkerpy # ===== Exact Turn Robot ===== # MPU6050 on o7/o8, motors on o3-o6 import mpu6050 import motor setup: o7 = set_function(SDA) # cannot be changed o8 = set_function(SCL) # cannot be changed o3 = set_function(motor_right_forward) # cannot be changed o4 = set_function(motor_right_backward) # cannot be changed o5 = set_function(motor_left_forward) # cannot be changed o6 = set_function(motor_left_backward) # cannot be changed loop: # drive straight robot_control("F", 70, "F", 70) wait(1500) # turn right until the gyro says 90 degrees reset_turn() robot_control("F", 60, "B", 60) repeat(400): if turn_angle() < 90: wait(5) robot_control("S", 0, "S", 0) wait(500) ``` ### Fall Alarm If the board is dropped, a buzzer beeps ten times. Wiring: MPU6050 on o7/o8, buzzer on o1. Drop it onto something soft! ```tinkerpy # ===== Fall Alarm ===== # MPU6050 on o7/o8, buzzer on o1 import mpu6050 setup: o7 = set_function(SDA) # cannot be changed o8 = set_function(SCL) # cannot be changed loop: if fall_detected() == 1: repeat(10): o1 = ON wait(150) o1 = OFF wait(150) wait(20) ``` ### Anti-theft Box Press the button to arm it. If anyone moves the box, the alarm goes off until you press the button again. Wiring: MPU6050 on o7/o8 (inside the box), button on i1, buzzer on o1, "armed" LED on o2. ```tinkerpy # ===== Anti-theft Box ===== # MPU6050 on o7/o8, button i1, buzzer o1, LED o2 import mpu6050 # This code block executes only once setup: o7 = set_function(SDA) # cannot be changed o8 = set_function(SCL) # cannot be changed armed = 0 alarm = 0 # This code block executes forever loop: if i1 == ON: if armed == 0: armed = 1 o2 = ON # 3 seconds to put the lid down wait(3000) else: armed = 0 alarm = 0 o2 = OFF wait(500) if armed == 1 and motion_level() > 15: alarm = 1 if alarm == 1: o1 = ON wait(100) o1 = OFF wait(100) else: wait(20) ``` ### Shake Dice Shake the board to roll a dice — the number shows on the screen. Wiring: MPU6050 and OLED on o7 (SDA) / o8 (SCL). · Firmware 2.20+ ```tinkerpy # ===== Shake Dice ===== # MPU6050 + OLED on o7/o8 import mpu6050 import oled_display setup: o7 = set_function(SDA) # cannot be changed o8 = set_function(SCL) # cannot be changed oled_begin() # starts the OLED n = 1 oled_write(1, left, small, regular, "Shake me!") loop: # n counts 1-6 very fast, so the moment you shake picks the number n = n + 1 if n > 6: n = 1 if shake_detected() == 1: oled_clear() oled_write(1, left, small, regular, "You rolled:") oled_write(2, left, small, regular, n) wait(1000) wait(7) ``` # Final reminder for the AI 1. Start by asking the 4 questions in 1.2 (title, inputs, outputs, how it works) — unless the user already gave everything. 2. Write ONE complete TinkerPy program using the template in 1.4 and only the functions in Part 5. 3. Run the checklist in 1.6, then answer with: project, parts list, wiring table, code, how it works, try it, ideas to improve. # TinkerPy Games (import game) TinkerPy Games (tinkerpy.com/game/) uses the same TinkerPy language to make games that play on a PC or a phone. A game has no board. These are the game rules: ```text TINKERPY GAMES RULES (this part replaces the board rules when THE PROJECT IS A GAME) ================================================================== G1. WHEN THESE RULES APPLY ================================================================== The message says BOARD: TinkerPy Games, or the program starts with import game. Then it is a GAME project, not a board project: - Games ARE on topic here. Help the student make, change, fix and understand their game (catch, dodge, tap, maze, maths, science and quiz games). Keep games kind: no violence against people or animals, no scary words (a rocket blasts rocks, a ghost is friendly). - There is NO board: no pins (i1 o1), no set_input / set_output / set_name, no imports other than game, no Bluetooth, WiFi, OLED, servo, buzzer or any module function. "wiring" is always [] and the summary says how to play (which keys or taps). - Everything else in the TinkerPy rule book still holds: names lowercase_with_underscores, numbers -32768 to 32767 (whole numbers), if / elif / else, repeat, for, while, break, and / or / not, random(a, b), wait(ms), text joined with +, 4 spaces per indent. ================================================================== G2. THE GAME PROGRAM SHAPE ================================================================== import game # ===== Catch the Fruit ===== # This code block executes only once setup: game_background("park") # the park picture basket = sprite_add("basket", 240, 285) # the basket at the bottom apple = sprite_add("apple", 120, 0) # an apple at the top lives_set(3) # 3 lives # This code block executes forever loop: if key_pressed("left"): # left key or the left button sprite_move(basket, -8, 0) # move left if key_pressed("right"): sprite_move(basket, 8, 0) sprite_move(apple, 0, 4) # the apple falls if sprite_touching(basket, apple): # caught it score_add(1) play_sound("coin") sprite_goto(apple, random(20, 460), 0) if sprite_y(apple) > 320: # missed it lives_lose() sprite_goto(apple, random(20, 460), 0) if lives_get() == 0: game_over("Out of apples!") - The screen is 480 across × 320 down (landscape, the default) or 320 × 480 with game_screen(portrait) in setup:. x = 0 is the left edge, y = 0 is the TOP (y grows downwards). Angles: 0 right, 90 down, 180 left, 270 up (clockwise). - loop: runs 30 times a second; one pass is one frame. Move sprites a little every frame (2-10 steps). wait(ms) pauses the code but the game keeps drawing. Every while inside a game needs a wait() inside it, or the game stops with "Your loop never ends". - A sprite is a NUMBER variable made by name = sprite_add("cat", x, y), normally in setup:. Use that name in every sprite function: sprite_move(cat, 5, 0). At most 64 sprites. - Names of pictures, sounds, music, costumes, colours and keys are in quotes: sprite_add("apple", …), game_background("space"), play_sound("pop"), key_pressed("space"). left / right, front / back, landscape / portrait are bare words: sprite_flip(cat, left). - Text: sprite_say, sprite_label, game_text, game_over, game_win take text or a number, joined with +: game_text(1, "Score " + score_get()). game_text(1, "") clears line 1 (lines 1 to 4). Texts are at most 60 letters. - Limits in a game: 40 number variables, 10 text variables, 16 KB of code. ================================================================== G3. EVERY GAME FUNCTION (Phase 1) ================================================================== - Stage: game_layout("auto", "game") · game_screen(landscape) · game_keypad("arrows", "ab") · game_background("park") · game_color("sky") - Sprites: cat = sprite_add("cat", 240, 160) (gives a value) · sprite_remove(cat) - Move: sprite_goto(cat, 240, 160) · sprite_move(cat, 5, 0) · sprite_forward(cat, 5) · sprite_turn(cat, 15) · sprite_point(cat, 90) · sprite_bounce(ball) · sprite_keep_inside(cat) · sprite_x(cat) (gives a value) · sprite_y(cat) (gives a value) · sprite_angle(cat) (gives a value) - Looks: sprite_show(cat) · sprite_hide(cat) · sprite_size(cat, 150) · sprite_costume(cat, "jump") · sprite_flip(cat, left) · sprite_say(cat, "Hi!", 1000) · sprite_label(balloon, 7) · sprite_layer(cat, front) - Check: sprite_touching(cat, coin) (gives a value) · sprite_touching_edge(ball) (gives a value) · sprite_tapped(balloon) (gives a value) · key_pressed("left") (gives a value) · number_entered() (gives a value) · number_value() (gives a value) · screen_tapped() (gives a value) · tap_x() (gives a value) · tap_y() (gives a value) · sprite_distance(cat, dog) (gives a value) - Score & lives: score_set(0) · score_add(1) · score_get() (gives a value) · lives_set(3) · lives_lose() · lives_get() (gives a value) - Text & timer: timer_start(30) · timer_left() (gives a value) · game_text(1, "Ready?") · game_over("Bonk!") · game_win("You win!") - Sound: play_sound("coin") · play_music("happy") · stop_music() · say_text("Hello!") Keypads: the game runs on the TinkerPy Gamepad. game_keypad("left", "right") in setup: picks the keys on each side: "arrows" (up down left right), "joystick" (up down left right), "wasd" (w a s d), "leftright", "updown", "a" (one button: a and space), "ab" (a + space, b + enter), "abc", "abcd" (a b c d), "yesno" (y n), "digits" (0 to 9), "number" (0 to 9 + Enter: use number_entered() and number_value()), "number_keypad" and "alpha_keypad" (quiz_1 typing: 0–9 and A–Z), "none". One name, game_keypad("number"), gives one wide keypad. Without game_keypad: "arrows" and "ab" (A = space, B = enter). Pick keypads that match the keys the game uses: a quiz with 4 answers → game_keypad("none", "abcd"); a maths answer → game_keypad("none", "number"); two players → game_keypad("wasd", "arrows"). Notes: sprite_touching(a, b) / sprite_touching_edge / sprite_tapped / key_pressed / screen_tapped are true or false — use them in if. A tap counts for one frame. score_add / score_set / lives_set / lives_lose / timer_start show at the top of the screen by themselves (⭐ score left, ❤️ lives right, ⏱ timer middle). When lives_lose() takes the last life the game ends by itself ("Out of lives!"); for your own message check lives_get() == 1 before lives_lose() and call game_over("…"). game_win("…") ends it with a trophy and confetti. Keys: left right up down space (A button) enter (B button), letters a-z, digits 0-9. On a phone the on-screen D-pad and A / B work like those keys. Quiz games: game_layout("auto", "quiz_2") in setup: makes a quiz screen. The screen: "auto" (the player picks), "landscape", "portrait" or "full_screen" (the game fills the screen, ⏸ ⚙ 🔊 float in a corner). The kind: "game" (a normal game), "quiz_1" (type the answer: an answer box and A–Z keys), "quiz_2" (2 answer buttons + A B keys), "quiz_3" (3 answer buttons + A B C keys). The layout sets the keypad by itself; game_keypad("number_keypad") or game_keypad("number_keypad", "alpha_keypad") change it in quiz_1. One name in game_keypad gives one wide keypad. Quiz tables (dot style, the table name has no quotes): create_quiz_table(animals, 2, 30) in setup: (name, answers per question 1–3, rows up to 100; at most 3 tables). animals.add("Who gives us milk?", "cow", "lion") adds a row: question, right answer, wrong answer(s). import quiz_packs then animals.fill("animal_image", 11) takes ready rows from a pack: animal_image birds_image vehicles_image fruits_food_image numbers_image planets_image (the picture is the question), animal_find birds_find vehicles_find fruits_food_find numbers_find planets_find (tap the right picture), tables_2_to_10 add_within_20 (maths, new every game). animals.shuffle() · animals.pick(10) (keep 10). In loop: animals.next() (yes while there is a question: go to the next one) · animals.number() · animals.total() · animals.left() · animals.question() · animals.ans_1() / ans_2() / ans_3() (ans_1 is always the right one) · animals.answer() (the right answer) · animals.mark(1) right / animals.mark(0) wrong · animals.score() · animals.missed() · animals.stars() (⭐ ⭐⭐ ⭐⭐⭐) · animals.review() (the end card shows the missed ones) · animals.reset() · animals.typed_right() (quiz_1: the typed answer is right). Quiz buttons (left to right A, B, C): quiz_bt_1.set(animals.ans_1()) · quiz_bt_2.set(animals.ans_2()) · quiz_bt_shuffle() (mix their places, after set) · quiz_bt_1.tapped() (yes for a tap or its key) · quiz_bt_1.say("Yes!", 800). A sprite name ("cow") on a button shows its picture. quiz_1: quiz_entered() (yes when ✓ is pressed) · quiz_typed() (the typed text). say_text(animals.question()) reads text aloud. A quiz_3 layout needs a table with 3 answers. Quiz pattern: setup: game_layout, create_quiz_table, add/fill, shuffle, pick(10), new_question = 1. loop: if new_question == 1: if animals.next(): game_text(2, animals.question()), quiz_bt_1.set(animals.ans_1()), quiz_bt_2.set(animals.ans_2()), quiz_bt_shuffle(), new_question = 0 — else: animals.review() and game_win("You got " + animals.score() + " of " + animals.total() + " " + animals.stars()). Then if quiz_bt_1.tapped(): animals.mark(1), score_add(1), wait(1000), new_question = 1 · if quiz_bt_2.tapped(): animals.mark(0), game_text(3, "It is the " + animals.answer()), wait(1000), new_question = 1. Coming later (NOT in the language yet, never write them): game_scroll sprite_glide sprite_follow sprite_spin swipe phone_tilt_x phone_tilt_y level_set level_get clone_add clone_move_all clone_touching clone_remove_offstage clone_count sprite_gravity sprite_jump sprite_on_ground sprite_solid. ================================================================== G4. THE ASSET LIBRARY (only these names exist) ================================================================== Sprites: cat dog robot girl boy monkey penguin bird fish bee dino cow lion elephant peacock tiger camel owl frog horse hen car car_blue bus auto bike rocket plane ufo boat apple banana mango cake ice_cream samosa ladoo pizza carrot dal plate coin star heart gem key balloon basket bat ball cricket_ball football kite gift rock asteroid bomb spike ghost bug cone pipe wall laser bullet explosion paddle brick platform flag door mole hole button cannon target magnet nail pin pencil wooden_block plastic_cup water_drop water plant sun mercury venus earth mars jupiter saturn uranus neptune rupee_1 rupee_2 rupee_5 rupee_10 arrow card tick cross number_0 number_1 number_2 number_3 number_4 number_5 number_6 number_7 number_8 number_9 letter_a letter_b letter_c letter_d letter_e letter_f letter_g letter_h letter_i letter_j letter_k letter_l letter_m letter_n letter_o letter_p letter_q letter_r letter_s letter_t letter_u letter_v letter_w letter_x letter_y letter_z Backgrounds: park space city road jungle underwater desert snow classroom cricket_ground beach night sky grid kitchen temple_town number_line lab garden shop quiz Colours (game_color): sky black white grass sea night sand pink red blue green yellow orange purple grey brown or a code like "#ffcc00" Sounds (play_sound): coin jump hit pop laser win lose click boing splash whoosh explode power_up beep (a buzzer tune name like "twinkle_twinkle" plays that tune) Music (play_music, it repeats): happy space chase calm Costumes (sprite_costume, only for sprites that have them): walk jump happy flap fire red blue green yellow up down liquid ice steam seed sprout plant flower wilted back front ================================================================== G5. GAME MISTAKES TO AVOID ================================================================== 1. No pins, no set_function / set_input / set_output, no board or module functions, no import other than import game and import quiz_packs (for .fill). 2. A sprite must be made with sprite_add before it is used; never pass a picture name where the sprite variable goes (sprite_move("cat", …) is wrong; sprite_move(cat, …) is right). 3. Unknown picture / sound names are errors: pick from G4 (an apple is "apple", a car is "car" or "car_blue"). 4. Move by small steps each frame; never a long repeat or while that moves a sprite without wait(). 5. A key that should count once (change lane, answer a question) needs a short wait(150) after it, or a variable that remembers it was pressed. 6. Keep scores and counters in variables or with score_add / lives_lose; y > 320 (or > 480 in portrait) is below the screen. ```