Waveform Input » History » Version 2
Adam Klama, 06/21/2026 03:24 PM
| 1 | 1 | Adam Klama | # Waveform Input |
|---|---|---|---|
| 2 | |||
| 3 | ## Overview |
||
| 4 | A **Waveform Input** generates a **timed value** — a waveform — in response to the |
||
| 5 | edges of another input. When the observed input switches on or off, it plays back a |
||
| 6 | sequence of *(time, value)* points you define. Typical uses are clutch-by-wire |
||
| 7 | **engage on button press** and **release on button release**, **blinker / hazard** |
||
| 8 | lights, and simple **test signals**. It watches an input you already configured and |
||
| 9 | produces a value from it. |
||
| 10 | |||
| 11 | ## Prerequisites & hardware |
||
| 12 | - A **source input** to observe — usually a button or switch (for example a |
||
| 13 | 2 | Adam Klama | [Digital Input](Digital_Input)). Create it first and note its identifier. |
| 14 | 1 | Adam Klama | - The observed input is treated as **digital**: a value **< 512 is LOW**, a value |
| 15 | **≥ 512 is HIGH**. |
||
| 16 | - A **LOW → HIGH** transition fires the **RISE** trigger. |
||
| 17 | - A **HIGH → LOW** transition fires the **FALL** trigger. |
||
| 18 | - At startup no transition is detected, so the first trigger can occur no earlier |
||
| 19 | than the second cycle. |
||
| 20 | |||
| 21 | ## Add it in the app |
||
| 22 | 1. Add a new input and choose **Waveform Input** as the type. |
||
| 23 | 2. Set the **Observed input** to the source you want to watch. |
||
| 24 | 3. Give it a clear **alias** (e.g. `Clutch Command`). |
||
| 25 | 4. Define the **Rise waveform** and **Fall waveform** as lists of *(time, value)* |
||
| 26 | points. |
||
| 27 | 5. Set the **idle values** and the **repeat** / **minimum repeats** behaviour. |
||
| 28 | |||
| 29 | ## Settings reference |
||
| 30 | |||
| 31 | | Setting | Meaning | Unit | Range / values | Notes | |
||
| 32 | |---|---|---|---|---| |
||
| 33 | | **Observed input** | The input whose edges trigger the waveforms | — | int32 (input id) | Read as digital: `< 512` LOW, `≥ 512` HIGH. | |
||
| 34 | | **Rise waveform** | Points played on a LOW → HIGH edge | (ms, value) pairs | list of sint32 times + sint32 values | Time stamps in ms; output value at each point. An empty list outputs the idle value. | |
||
| 35 | | **Fall waveform** | Points played on a HIGH → LOW edge | (ms, value) pairs | list of sint32 times + sint32 values | As above, for the falling edge. | |
||
| 36 | | **Rise repeat** | Loop the rise waveform | — | on / off | **Off:** play once, then hold the idle value (or stop early if a new trigger arrives and minimum repeats > 0). **On:** when the timer passes the last point, reset and replay from the start. | |
||
| 37 | | **Fall repeat** | Loop the fall waveform | — | on / off | As above, for the fall waveform. | |
||
| 38 | | **Rise minimum repeats** | Full plays before a new trigger can interrupt the rise waveform | plays | int (`0`, `1`, `n`) | `0` = interruptible as soon as the next trigger is seen; `1` = play at least once fully; `n` = at least n times. **Ignored when Rise repeat is off.** | |
||
| 39 | | **Fall minimum repeats** | Full plays before a new trigger can interrupt the fall waveform | plays | int (`0`, `1`, `n`) | As above, for the fall waveform. | |
||
| 40 | | **Idle value (LOW)** | Output when no waveform is playing and the observed input is LOW | value | sint32 | Held between waveforms. | |
||
| 41 | | **Idle value (HIGH)** | Output when no waveform is playing and the observed input is HIGH | value | sint32 | The input picks LOW or HIGH idle from the observed input's current state. | |
||
| 42 | |||
| 43 | ### How a waveform is described |
||
| 44 | Each waveform is a list of **(time, value)** points. After a trigger, a timer starts |
||
| 45 | at `0 ms` and the input outputs the value scheduled for the elapsed time, **linearly |
||
| 46 | interpolating** between points to give a smooth ramp: |
||
| 47 | |||
| 48 | ``` |
||
| 49 | value |
||
| 50 | 1000 | ______ |
||
| 51 | | / |
||
| 52 | 0 |________/ |
||
| 53 | +--------+----+----> time (ms) |
||
| 54 | 0 200 300 |
||
| 55 | points: (0,0) (200,1000) (300,1000) -> interpolated between points |
||
| 56 | ``` |
||
| 57 | |||
| 58 | When the timer passes the **last** point, the input either holds the idle value |
||
| 59 | (repeat off) or resets to `0 ms` and plays again (repeat on). |
||
| 60 | |||
| 61 | ## Common settings |
||
| 62 | Waveform Input also uses the shared setting — alias. See |
||
| 63 | 2 | Adam Klama | [Common IO Settings](Common_IO_Settings). |
| 64 | 1 | Adam Klama | |
| 65 | ## Example — clutch engage on press, ramped release on release |
||
| 66 | 2 | Adam Klama | Watch a clutch button (a [Digital Input](Digital_Input)) and drive a clutch |
| 67 | 1 | Adam Klama | command from `0` (open) to `1000` (closed). |
| 68 | |||
| 69 | 1. Type **Waveform Input**, alias `Clutch Command`, **Observed input** = the |
||
| 70 | clutch button. |
||
| 71 | 2. **Rise waveform** (button pressed → engage quickly): |
||
| 72 | `(0 ms, 0) → (200 ms, 1000)` — ramps up over 200 ms. |
||
| 73 | 3. **Fall waveform** (button released → ramp out gently): |
||
| 74 | `(0 ms, 1000) → (600 ms, 0)` — ramps down over 600 ms. |
||
| 75 | 4. **Rise repeat off**, **Fall repeat off** — each plays once, then holds idle. |
||
| 76 | 5. **Idle value (LOW)** `0`, **Idle value (HIGH)** `1000` — so once engaged it |
||
| 77 | stays closed and once released it stays open. |
||
| 78 | |||
| 79 | For a **hazard light** instead: put a square pulse in the Rise waveform and turn |
||
| 80 | **Rise repeat on** so it blinks continuously until the next trigger. |
||
| 81 | |||
| 82 | ## Troubleshooting |
||
| 83 | - **Nothing happens on the first press:** at startup no edge exists; the first |
||
| 84 | trigger comes no earlier than the second cycle. Toggle the input once. |
||
| 85 | - **Waveform never stops / keeps looping:** **repeat** is on. Turn it off for a |
||
| 86 | one-shot, or set **minimum repeats** so the next trigger can interrupt it. |
||
| 87 | - **A new press is ignored mid-play:** **minimum repeats** is too high — lower it |
||
| 88 | (or use `0`) so the next trigger can interrupt. |
||
| 89 | - **Output sits at the wrong level between presses:** check **Idle value (LOW/HIGH)**. |
||
| 90 | - **Ramp too fast or too slow:** adjust the point **timestamps** — the output |
||
| 91 | interpolates linearly between consecutive points. |
||
| 92 | - **Triggers fire on the wrong edge:** LOW/HIGH is split at **512** — make sure the |
||
| 93 | observed input crosses that threshold. |
||
| 94 | |||
| 95 | ## Related |
||
| 96 | 2 | Adam Klama | - [Digital Input](Digital_Input) — a typical button/switch source to observe. |
| 97 | - [Constant Value Input](Constant_Value_Input) — a fixed value with no timing. |
||
| 98 | - [Counter Input](Counter_Input) — count edges rather than play a waveform. |