Skip to content

Commit

Permalink
Add a 'tour of TinyGo' with interactive examples in a mini-playground
Browse files Browse the repository at this point in the history
  • Loading branch information
aykevl authored and deadprogram committed Jun 18, 2024
1 parent 58af802 commit 30b9f8a
Show file tree
Hide file tree
Showing 14 changed files with 735 additions and 1 deletion.
1 change: 1 addition & 0 deletions content/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Ready to get started? [Click here](getting-started).
</div>
<div class="col col-auto">
<button class="btn btn-secondary playground-btn-flash" disabled>Download binary</button>
<a href="/tour/" class="btn btn-link">Tour of TinyGo</a>
</div>
</div>
<textarea placeholder="Loading..." class="form-control input" rows="20" style="font-family: monospace; tab-size: 4" spellcheck="false"></textarea>
Expand Down
8 changes: 8 additions & 0 deletions content/getting-started/tour.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: "Tour"
type: "docs"
---

We have a Tour of TinyGo, where you'll learn how to use TinyGo even if you aren't very familiar with programming hardware. You can find it [here]({{< ref "tour/blink/onboard.md" >}}).

The tour assumes you are already familiar with Go. If not, you can follow the [Tour of Go](https://go.dev/tour/) to get started.
10 changes: 10 additions & 0 deletions content/tour/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: "Tour of TinyGo"
type: "docs"
---

Welcome to the tour of TinyGo!

This tour assumes you're already familiar with Go. If not, you can go through the [tour of Go](https://go.dev/tour/) to get started.

Every example in this tour is runnable directly in the browser, and most can be downloaded directly to your own electronics board (like the [Adafruit Circuit Playground Express](https://www.adafruit.com/product/3333)).
9 changes: 9 additions & 0 deletions content/tour/blink/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
title: "Blinking LED"
type: "docs"
description: "Write the \"hello world\" of electronics by making an LED blink!"
---

This short tour will get you up to speed with blinking a simple LED. This is a great way to start, especially if you've never done electronics before: if the LED blinks you know that everything works to continue in the tour. If you can't get it to work, you might need to do some troubleshooting before you can continue.

This tour also teaches the basics of the TinyGo-specific machine package.
131 changes: 131 additions & 0 deletions content/tour/blink/external.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
---
title: "External LED"
description: "Same blinking LED as in the previous example, but now with an external LED."
weight: 2
---

Instead of using an on-board LED, you can also connect a LED to an external pin. Just like you see in the example on the right. It connects an external LED (a red one in this case) to the pin A1 on the board.

The code is almost identical to the previous example. The only difference is this line:

```go
led := machine.A1
```

We've replaced the `led` variable: instead of the on-board LED we're now using the external pin A1.

If you want to try this on a development board, make sure you use the correct wiring:

* Connect the LED cathode (short lead with flat side) to a resistor of around 220Ω-330Ω. Use at least 150Ω to protect the LED, and use at most 1000Ω to still be able to see the LED (higher values will make the LED very dim).
* Connect the other end of the resistor to ground.
* Connect the LED anode to pin A1 on the board. See the silkscreen on the board or the graphic in the simulator to know which pin this is.

**Warning**: the resistor is not optional, not using the resistor can destroy the LED and/or your board. The LED might even explode!

The simulation doesn't need this resistor because the virtual LED can't burn out. This simplifies the demo, but remember that the real world is messy and LEDs need a resistor. (There are technical reasons for this, read [this answer](https://electronics.stackexchange.com/questions/28393/why-do-we-need-resistors-in-led) for more details).

<script type="module">
import { setupTour } from '/tour.js';
let ledConfig = {
type: 'led',
humanName: 'External LED',
color: [255, 0, 0],
svg: 'led-tht-5mm.svg',
};
let code = `
// You can edit this code!
package main
import (
"machine"
"time"
)
func main() {
led := machine.LED
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
for {
led.High()
time.Sleep(time.Second/2)
led.Low()
time.Sleep(time.Second/2)
}
}`;
setupTour({
boards: {
'arduino': {
code: code.replace('machine.LED', 'machine.D2 // Arduino Uno'),
parts: {
led: {
config: ledConfig,
x: 45,
y: -10,
rotation: 90,
}
},
wires: [
{from: 'main.D2', to: 'led.anode'},
{from: 'main.GND#2', to: 'led.cathode'},
],
},
'arduino-nano33': {
code: code.replace('machine.LED', 'machine.D2 // Arduino Nano 33 IoT'),
parts: {
led: {
config: ledConfig,
x: 12,
y: -18,
}
},
wires: [
{from: 'main.D2', to: 'led.anode'},
{from: 'main.GND#1', to: 'led.cathode'},
],
},
'circuitplay-bluefruit': {
code: code.replace('machine.LED', 'machine.A2 // Circuit Playground'),
parts: {
led: {
config: ledConfig,
x: 35,
y: -4,
rotation: 90,
}
},
wires: [
{from: 'main.A2', to: 'led.anode'},
{from: 'main.GND#1', to: 'led.cathode'},
],
},
'circuitplay-express': {
code: code.replace('machine.LED', 'machine.A2 // Circuit Playground'),
parts: {
led: {
config: ledConfig,
x: 35,
y: -4,
rotation: 90,
}
},
wires: [
{from: 'main.A2', to: 'led.anode'},
{from: 'main.GND#1', to: 'led.cathode'},
],
},
'pico': {
code: code.replace('machine.LED', 'machine.GP20 // Raspberry Pi Pico'),
parts: {
led: {
config: ledConfig,
x: 16,
y: -18,
}
},
wires: [
{from: 'main.GP20', to: 'led.anode'},
{from: 'main.GND#4', to: 'led.cathode'},
],
},
}});
</script>
85 changes: 85 additions & 0 deletions content/tour/blink/onboard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
title: "Blinking LED"
description: "Hello world of hardware. Blink an on-board LED using your own development board."
weight: 1
---

This is the classic "blinking LED" demo you will find in many places. You can find it for the [Arduino IDE](https://docs.arduino.cc/built-in-examples/basics/Blink/) for example. Here is the equivalent in Go.

If you have one of the supported boards (see the dropdown below the code), you can run this code on your own hardware! If you don't, you can just use the simulator that's already running.

Going through the code we can see the following:

```go
package main
```

This is just standard Go, so we begin with package main.

```go
import (
"machine"
"time"
)
```

We import two packages. The time package is the well-known time package which we need to sleep while blinking. However the machine package is new: it is a special standard library package used by TinyGo.

You can think of the machine package like the os or syscall package: it provides an abstraction layer over the underlying hardware and makes code more portable across boards.

```go
led := machine.LED
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
```

This configures the LED pin. The constant `LED` is defined in the machine package and represents the pin that is connected to the on-board LED. It is of type `machine.Pin`.

We configure the pin here as an output pin, that is, it outputs either a high or low signal. _High_ or _low_ in this case mean that the output voltage is either somewhere close to the supply voltage (usually 5V or 3.3V) or close to ground (0V).

```go
for {
led.High()
time.Sleep(time.Second/2)

led.Low()
time.Sleep(time.Second/2)
}
```

Here we just blink the LED: we set the output to high for ½ second and then set it to low for ½ second.

Try changing these values and see what happens! For example you can set both to 1 second, or only one of them.

When you play around with the sleep duration, you might discover that "high" and "low" don't actually match the "on" and "off" state of the LED. "high" usually means that the LED is off, while "low" means that it is on. This is because of the way the LED is wired: the anode is connected to the power source (probably via a resistor), and the cathode is connected to the microcontroller pin. This means that when the pin is high (close to the power source) both sides are positive and no current will flow. And when the pin is negative, current will flow from the power source through the LED into the microcontroller. Some boards are wired differently however, and "high" will mean the LED is on while "low" is off.

<script type="module">
import { setupTour } from '/tour.js';
setupTour({
boards: {
'arduino-nano33': {},
'arduino': {},
'circuitplay-bluefruit': {},
'circuitplay-express': {},
'pico': {},
},
code: `
// You can edit this code!
package main
import (
"machine"
"time"
)
func main() {
led := machine.LED
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
for {
led.High()
time.Sleep(time.Second/2)
led.Low()
time.Sleep(time.Second/2)
}
}`});
</script>
7 changes: 7 additions & 0 deletions content/tour/button/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: "Reading button inputs"
description: "Make interactive hardware by responding to button presses."
type: "docs"
---

We've seen a blinking LED which provides output, now we're ready for reading from an input.
Loading

0 comments on commit 30b9f8a

Please sign in to comment.