GPIO simulator
The GPIO simulator stands in for a board for the programs you run on Windows. Each pin of the program connects to a card: an LED that lights up, a pushbutton you press with the mouse, a potentiometer you turn, a WS2812 LED strip… That way you can test a program that uses the GPIO module or the LED module without having the board at hand.
You open it with Build › Debug › GPIO Sim, on the ribbon. It's an IDE panel like the others: you can dock it or leave it floating (The interface).
- It only sees programs that run on Windows, with Windows x64 in Build › Target. On a board, the program drives its real pins and the simulator knows nothing about it.
- You don't need to open it before Run. It connects by itself as soon as the program uses
GPIOorLED, and from then on it updates every 30 ms.
A walkthrough
The LED strip of the LedStrip example, as an 8 × 8 matrix.
- Create the project. Press Home › Project › New and, in Example Projects, double-click LedStrip (Projects). Its main program,
Code/Matrix8x8Plasma.aru, creates a strip of 64 LEDs on GP17 and paints a colour plasma on it. - Open the simulator with Build › Debug › GPIO Sim. The table already has two pins: GP17, connected to WS2812 Strip, and GP19, to Signal generator, which this program doesn't use. The example keeps them in
Config/jaru_sim.json. - Pick the shape. On the WS2812 Strip · GP17 card, open Layout and pick 8 x 8.
- Run it. Press Run. The card shows the plasma, and below it,
64 LEDs | 8x8 | Bright: 255. - Try the wiring. Change Wiring to Serpentine H: every other row runs backwards and the picture breaks on those rows, because the program counts the LEDs row by row. That's what you would see on a matrix wired in a zigzag.
To use your own pins, add them with Add GPIO Pin and connect them to a device in the Connected to column.
The pin table
The table on the left holds the pins you are going to use. It doesn't fill itself with the program's pins: you add each pin yourself.
- Add GPIO Pin asks for the pin number, from 0 to 48. A new pin is a digital input with nothing connected:
INPUT,DIGITAL,NONE,LOWand-- Free --. It doesn't let you add the same pin twice. - Delete GPIO Pin removes the selected row and its card, without asking.
| Column | What it shows |
|---|---|
| GPIO | The pin: GP2, GP17… |
| Direction | INPUT or OUTPUT. The program sets it, with GPIO.pinmode or with GPIO.awrite; until then, the pin is an input. |
| Type | DIGITAL; ADC_IN, with a Potentiometer, a Temperature or a Signal generator; PWM Ch.0 (with its channel) if the program uses GPIO.awrite; DAC_OUT, an analog output with no channel. |
| Pull | NONE, PULLUP or PULLDOWN, as set by GPIO.pinmode. |
| Status | On a digital pin, HIGH (green dot) or LOW (grey dot). On an analog one, the value and a bar. |
| Connected to | The device connected to the pin, or -- Free --. |
With the mouse:
- Click Connected to: the list of devices drops down. Pick one and press
Enter, or click elsewhere: its card appears on the right.Escleaves it as it was, and -- Free -- removes the card. Each pin takes one device at most. - Click Status, on a digital input, while the program runs: the pin goes from
LOWtoHIGHor the other way round. It's a quick switch, with no card. - Click Status, on an analog pin: a box with the value comes up, from 0 to 4095. Type another one and press
Enter(Escdoesn't change it). If the program is running, it reads it withGPIO.aread.
With a PWM of 10 Hz or less, Status makes the pin blink at the PWM's pace, as you would see it on an LED.
Every time a program starts, the VM sets all the pins to zero. Whatever you set on the cards beforehand (a turned potentiometer, a switch that's on) doesn't reach the program until you touch it again.
The cards
On the right there is one card for each pin with a device, in the order you connect them. The title says the device and the pin, like Potentiometer · GP2.
| Device | What it is | The program uses it with |
|---|---|---|
| Red LED, Green LED, Blue LED | An LED that lights up with the pin. | GPIO.write, GPIO.awrite |
| Pushbutton | A pushbutton: the pin changes while you hold it down. | GPIO.read, GPIO.onInterrupt |
| Switch | A switch: each click turns it on or off. | GPIO.read, GPIO.onInterrupt |
| Potentiometer | A knob you turn: from 0 to 4095. | GPIO.aread |
| Temperature | A temperature sensor: from 0 to 4095. | GPIO.aread |
| Phototransistor | A light sensor: from 0 to 4095. | GPIO.aread |
| Oscilloscope | Draws the pin's PWM signal. | GPIO.awrite |
| Signal generator | Gives random voltages or the ones in a CSV file. | GPIO.aread |
| WS2812 Strip | A strip or a matrix of colour LEDs. | LED.new and show() |
LEDs
A round LED that follows the pin, and next to it, its state:
- With
GPIO.awrite(PWM), it shines according to the duty cycle. The card gives the duty, likeDuty: 128 / 255 (50%), and below it the channel, the frequency and the resolution, likePWM Ch.0 | 5000Hz | 8bit. - With
GPIO.write, it lights up withHIGH:ON (HIGH)orOFF (LOW).
Pushbutton and Switch
A round button you press with the mouse:
- Pushbutton changes the pin while you hold it down and puts it back when you let go.
- Switch changes the pin with each click and leaves it that way.
What the program reads depends on the pin mode, as on a board:
- with
GPIO.PULLUP, the pressed button gives0(LOW) and released,1; - with
GPIO.INPUTorGPIO.PULLDOWN, pressed gives1and released,0.
The card says both things: PRESSED (LOW), Released (HIGH)… The interrupts of GPIO.onInterrupt fire with the button's changes, as on the board.
Potentiometer, Temperature and Phototransistor
All three give the pin a value from 0 to 4095, the one GPIO.aread reads:
- Potentiometer: turn the knob by dragging around it, or click a point of the circle to take it there. 0 is at the top, and the value grows clockwise. You can also click the bar below: the value jumps to that point.
- Temperature: it has no knob; click the bar. The card shows the value in degrees, from 0 °C (0) to 100 °C (4095), and below it, the number (
Raw: 2048). - Phototransistor: drag up to give it more light and down for less. With
Shift, the value moves more slowly.
On the potentiometer and the phototransistor, the mouse wheel moves the value in steps of 1 % (about 41), and with Shift, of 0.1 %. On all three, you can also type the value in the Status column of the table.
Oscilloscope
It draws the signal of a PWM output (GPIO.awrite): the square wave, with its frequency and its duty cycle. At the top it gives the channel, the frequency, the resolution and the duty, and on the right, the duty in numbers (Duty: 128 / 255).
The - and + buttons, inside the screen, show fewer or more cycles of the wave: from 1 to 20, and 3 by default. With no PWM on the pin, it says No signal.
Signal generator
It gives the pin a voltage that changes by itself, to test a program that reads a sensor. Its controls:
- Random or CSV: random voltages or the ones in a file.
- ▶ Play starts it and ■ Stop stops it. It works even when the program isn't running: the graph below shows what it is giving.
- Loop: when the CSV ends, it starts over. On by default.
- The ms box: how many milliseconds between new values, from 10 to 5000. 50 by default.
- Min and Max: the voltage that gives 0 and the one that gives 4095, from 0 to 3.3 V. 0 and 3.3 by default.
- CSV... loads a file and switches the generator to CSV.
At the bottom, the card gives the voltage and the value the program reads: 1.99V | ADC: 2465.
With Random, each new value is a random voltage between Min and Max: the program reads a random number between 0 and 4095.
With CSV, the generator plays the file at its own pace: each line is a point, with the time in milliseconds from the start and the voltage in volts, separated by a comma. Between one point and the next, it joins the two with a straight line. Blank lines, lines that start with # and a text header are skipped. This one rises to 3 V in half a second and goes back down:
# time_ms,volts
0,0
500,3
1000,0
If the voltage has decimals, write them the way your Windows writes them: with a point (250,1.5) if Min and Max show as 0.0 and 3.3, and with a comma (250,1,5) if they show as 0,0 and 3,3. When it reaches the last point, it starts over if Loop is on; if not, it stops and keeps the last value.
WS2812 Strip
It shows the LED strip that the program creates on that pin with LED.new. It is painted every time the program calls show().
- Layout picks the shape: Strip (a strip, in rows that fill the card) or a matrix of 8 x 8, 16 x 16, 32 x 8, 8 x 32 or 4 x 4 (width by height). The change shows on the program's next
show(). - Wiring says how the matrix is wired, and only matters in a matrix. LED 0 is at the top left:
- Sequential: row by row, all of them left to right.
- Serpentine H: row by row, in a zigzag: the first one left to right, the second one right to left, and so on.
- Serpentine V: column by column, in a zigzag: the first one downwards, the second one upwards, and so on.
LEDs that don't fit in the matrix aren't shown. At the bottom, the card gives how many LEDs the strip has, the shape and the brightness from setBrightness: 64 LEDs | 8x8 | Bright: 255. If there is no strip on that pin, No active strip.
What it saves
The simulator keeps its pins in Config/jaru_sim.json, inside the project: each pin, with the device it has. This is the one of the LedStrip example:
{
"pins" : [
{
"gpio" : 17,
"connectedTo" : "WS2812 Strip"
},
{
"gpio" : 19,
"connectedTo" : "Signal generator"
}
]
}
- It saves it when you close the simulator, when you close the project or open another one, and when you close the IDE. With no project open, it saves nothing.
- It reads it when you open the simulator, and when you open a project with the simulator open.
- It saves nothing else: Layout, Wiring, the generator settings and the position of the controls go back to their defaults every time.
From code
On Windows, the GPIO module doesn't touch any hardware: it reads and writes a memory it shares with the simulator. The program doesn't know whether the simulator is open. Without it, nobody moves the inputs: an input pin reads 0 (1 with GPIO.PULLUP), and GPIO.aread, 0.
This program expects a Pushbutton on GP4, a Potentiometer on GP2 and a Red LED on GP5. While you hold the button down, the LED shines according to the potentiometer:
use GPIO
GPIO.pinmode(4, GPIO.PULLUP) // GP4: Pushbutton
while (true)
var value = GPIO.aread(2) // GP2: Potentiometer, from 0 to 4095
if (GPIO.read(4) == 0) then // with PULLUP, pressed is 0
GPIO.awrite(5, value / 16) // GP5: Red LED, brightness from 0 to 255
else
GPIO.awrite(5, 0)
end
pause(50)
end
The LED module drives WS2812 strips. LED.new(pin, n) creates a strip of n LEDs on the pin, from 1 to 1024. You set the colours with setPixel(i, r, g, b), fill(r, g, b), setHSV and fillHSV; the brightness, with setBrightness (from 0 to 255), and clear() sets them all to black. None of that reaches the strip until you call show(). This one lights a red LED that runs along a strip of 64 on GP17:
use LED
var strip = LED.new(17, 64)
strip.setBrightness(128)
var step = 0
while (true)
strip.clear()
strip.setPixel(step % 64, 255, 0, 0)
strip.show() // the card is painted here
step = step + 1
pause(50)
end
- On Windows there is room for 8 strips and 2,048 LEDs among all of them. Beyond that,
LED.newgives an error. - The card shows the colours just as the program sets them.
setOrder, which on a board says in which order the strip expects the colours, changes nothing here.
The whole GPIO module is in GPIO.
Known issues
- The buttons' hints say something else. When you hover over Add GPIO Pin and Delete GPIO Pin, the hint says "New Source Code".
- The Phototransistor shows as digital in the table. The table shows its pin as
DIGITALand withHIGH/LOW. The value the program reads is the one on the card. - A CSV with decimals depends on Windows. A file written with a decimal point doesn't load on a Windows that uses a decimal comma, nor the other way round: the lines it doesn't understand are skipped without a warning.
- The generator's button stays at Stop. When a CSV ends without Loop, the generator stops, but the button still says ■ Stop. One click starts it again.
All the known issues of JARU, together, are in Known issues.