Digital IO (GPIO)
DeviceScript provides access to digital GPIO (General Purpose Input/Output) operations on pins that do not require precise real time timings.
It is recommended to encapsulate the GPIO access into server implementation as they are rather low level.
If your application needs consistent response times of under 10ms, you can either implement the driver natively in C using interrupts, or better yet offload it to an external Jacdac module.
Pin mappings
While you can use hardware GPIO numbers with the ds.gpio()
function,
it is highly recommended that you instead import a board definition file an use pin names
matching silk on the hardware.
import { pins } from "@dsboard/adafruit_qt_py_c3"
const A2 = pins.A2_D2
The doc-string for pins.A2_D2
will tell you GPIO number (1
in this case).
Using named pins is also less error-prone since pins used for internal
functions are not exposed through the pins
object and the pins that are
exposed are annotated with type (input, output, analog, etc.) which is then
required by the startSomething()
functions.
Pins generally share names for boards with the same pinout. In particular, QT Py and XIAO share names.
The gpio()
function does not check for pin functions or usage.
It will return undefined
when named pin is not available or used for something else.
import { gpio } from "@devicescript/core"
const P0 = gpio(0)
Mode
The pin can be access through the generic gpio
function or through board specific packages
that provide predefined pin mappings (see devices).
You can configure the input/output mode through setMode
.
import { gpio, GPIOMode } from "@devicescript/core"
import "@devicescript/gpio"
// p0 -> output
const p0 = gpio(0)
await p0.setMode(GPIOMode.Output)
// P1 -> input
const p1 = gpio(1)
await p1.setMode(GPIOMode.Input)
Output
Use write
to set the output value of a pin. This example flips a pin state every second.
import { gpio, GPIOMode } from "@devicescript/core"
import "@devicescript/gpio"
const p0 = gpio(0)
await p0.setMode(GPIOMode.Output)
let loop = 0
setInterval(async () => {
await p0.write(loop++ % 2)
}, 1000)
Input
Use value
to read the input value of a pin. This example reads the input value every second.
import { gpio, GPIOMode } from "@devicescript/core"
import "@devicescript/gpio"
const p1 = gpio(1)
await p1.setMode(GPIOMode.Input)
// polling read pin
setInterval(async () => {
const v = p1.value
console.log({ poll: v })
}, 1000)
Use subscribe
to run code whenever the pin changes state.
import { gpio, GPIOMode } from "@devicescript/core"
import "@devicescript/gpio"
const p1 = gpio(1)
await p1.setMode(GPIOMode.Input)
p1.subscribe(v => console.log({ sub: v }))