{"id":16976421,"url":"https://github.com/boisgera/tinygo-arduino","last_synced_at":"2026-03-11T17:35:55.692Z","repository":{"id":65073759,"uuid":"553812640","full_name":"boisgera/tinygo-arduino","owner":"boisgera","description":"TinyGo for Arduino","archived":false,"fork":false,"pushed_at":"2022-12-25T09:58:12.000Z","size":11060,"stargazers_count":15,"open_issues_count":10,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-25T21:21:24.485Z","etag":null,"topics":["arduino","golang","iot","tinygo"],"latest_commit_sha":null,"homepage":"","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/boisgera.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-10-18T20:12:15.000Z","updated_at":"2025-03-09T04:26:04.000Z","dependencies_parsed_at":"2023-01-06T12:43:01.710Z","dependency_job_id":null,"html_url":"https://github.com/boisgera/tinygo-arduino","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boisgera%2Ftinygo-arduino","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boisgera%2Ftinygo-arduino/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boisgera%2Ftinygo-arduino/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boisgera%2Ftinygo-arduino/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/boisgera","download_url":"https://codeload.github.com/boisgera/tinygo-arduino/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248504774,"owners_count":21115204,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arduino","golang","iot","tinygo"],"created_at":"2024-10-14T01:26:02.923Z","updated_at":"2026-03-11T17:35:55.624Z","avatar_url":"https://github.com/boisgera.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TinyGo for Arduino\n\n![](slides/images/sahand-babali-owjrvbyXYyc-unsplash.jpg)\n\n## 🧭 Introduction\n\n  - 📖 [Slide deck](https://boisgera.github.io/tinygo-arduino/slides/index.html)\n\n\n## 📖 Documentation\n\n  - 📖 [TinyGo `machine` package for Arduino Uno](https://tinygo.org/docs/reference/microcontrollers/machine/arduino/).\n\n  - 📖 [Arduino Projects Book](https://github.com/boisgera/tinygo-arduino/raw/master/doc/arduino-projects-book.pdf), license [CC-BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/3.0/) by Arduino LLC.\n\n\n## 🧰 Do It Yourself (DIY)\n\n### 💻 Hello world! (PC/Go version)\n\n![](https://img.shields.io/static/v1?label=\u0026message=app.go\u0026logo=go\u0026color=white)\n```go\npackage main\n\nfunc main() {\n    println(\"Hello! 👋\")\n}\n```\n\nRun from source:\n```\n$ go run app.go\nHello! 👋\n```\n\nCompile:\n```\n$ go build app.go\n$ ls\napp  app.go\n```\n\nExecute:\n```\n$ ./app \nHello! 👋\n```\n\n\nFile size:\n```\n$ du -h app\n1,2M\tapp\n```\n\nCross-compile (Windows):\n```\n$ GOOS=windows go build app.go \n ls\napp  app.exe  app.go\n$ du -h app.exe \n1,2M\tapp.exe\n```\n\nCross-compile (Apple Silicon):\n```\n$ rm app app.exe\n$ ls\napp.go\n$ GOOS=darwin GOARCH=arm64 go build app.go\n$ ls\napp  app.go\n$ du -h app\n1,1M\tapp\n```\n\nℹ️ If you use [Visual Studio Code](https://code.visualstudio.com/), \nyou may install the [Go extension](https://marketplace.visualstudio.com/items?itemName=golang.go)\nto get code completion, signature help, etc.\n\n### 💻 Hello world! (PC/TinyGo version)\n\n![](https://img.shields.io/static/v1?label=\u0026message=app.go\u0026logo=go\u0026color=white)\n```go\npackage main\n\nfunc main() {\n    println(\"Hello! 👋\")\n}\n```\n\nRun from source:\n```\n$ tinygo run app.go\nHello! 👋\n```\n\nBuild:\n```\n$ tinygo build app.go\n(base) boisgera@oddball:~/tmp/sandbox$ ls\napp  app.go\n(base) boisgera@oddball:~/tmp/sandbox$ du -h app\n68K\tapp\n```\n\nExecute:\n```\n$ ./app \nHello! 👋\n```\n\n### 📟 Hello world! (Arduino/TinyGo version)\n\n![](https://img.shields.io/static/v1?label=\u0026message=app.go\u0026logo=go\u0026color=white)\n```go\npackage main\n\nfunc main() {\n    println(\"Hello from Arduino! 👋\")\n}\n```\n\n```bash\ntinygo flash -target=arduino app.go\n```\n\n```\navrdude: AVR device initialized and ready to accept instructions\n\nReading | ################################################## | 100% 0.00s\n\navrdude: Device signature = 0x1e950f (probably m328p)\navrdude: NOTE: \"flash\" memory has been specified, an erase cycle will be performed\n         To disable this feature, specify the -D option.\navrdude: erasing chip\navrdude: reading input file \"/tmp/tinygo287452646/main.hex\"\navrdude: writing flash (1174 bytes):\n\nWriting | ################################################## | 100% 0.20s\n\navrdude: 1174 bytes of flash written\navrdude: verifying flash memory against /tmp/tinygo287452646/main.hex:\navrdude: load data flash data from input file /tmp/tinygo287452646/main.hex:\navrdude: input file /tmp/tinygo287452646/main.hex contains 1174 bytes\navrdude: reading on-chip flash data:\n\nReading | ################################################## | 100% 0.16s\n\navrdude: verifying ...\navrdude: 1174 bytes of flash verified\n\navrdude done.  Thank you.\n\n```\n\nIf you are familiar with Python, you can read this message with:\n\n```bash\npip install pyserial\n```\n\n![](https://img.shields.io/static/v1?label=\u0026message=read.py\u0026logo=python\u0026color=white)\n```python\nimport serial\n\n# ⚙️ Configuration\nBAUD_RATE = 9600\nSERIAL_PORT = \"/dev/ttyACM0\"\n\n# ⏳ Loop\nwith serial.Serial(SERIAL_PORT, BAUD_RATE) as file:\n    while True:\n        bytes = file.readline().strip()\n        print(bytes.decode(\"utf-8\"))\n```\n\n``` bash\n$ python read.py\nHello from Arduino! 👋\n⏳\n```\n\nBut there is a simpler alternative with TinyGo:\n\n```bash\n$ tinygo flash -monitor -baudrate=9600 -target arduino app.go\n...\nConnected to /dev/ttyACM0. Press Ctrl-C to exit.\nHello from Arduino! 👋\n⏳\n```\n\n### ⏱️ Time\n\n![](https://img.shields.io/static/v1?label=\u0026message=app.go\u0026logo=go\u0026color=white)\n```go\npackage main\n\nimport \"time\"\n\nfunc main() {\n    for i := 0; i \u003c 3; i++ {\n        println(\"Hello from Arduino! 👋\")\n        time.Sleep(500 * time.Millisecond)\n    }\n}\n```\n\n```bash\n$ tinygo flash -monitor -baudrate=9600 -target arduino app.go\n...\nConnected to /dev/ttyACM0. Press Ctrl-C to exit.\nHello from Arduino! 👋\nHello from Arduino! 👋\nHello from Arduino! 👋\n⏳\n```\n\n![](https://img.shields.io/static/v1?label=\u0026message=app.go\u0026logo=go\u0026color=white)\n```go\npackage main\n\nimport \"time\"\n\nfunc main() {\n    for {\n        println(\"Hello from Arduino! 👋\")\n        time.Sleep(500 * time.Millisecond)\n    }\n}\n```\n\n```bash\n$ tinygo flash -monitor -baudrate=9600 -target arduino app.go\n...\nConnected to /dev/ttyACM0. Press Ctrl-C to exit.\nHello from Arduino! 👋\nHello from Arduino! 👋\nHello from Arduino! 👋\n⏳\n```\n\n⚠️ The standard [`Timer` \u0026 `Ticker` standard API](https://pkg.go.dev/time) would be super \nnice to have, but [they are buggy at the moment](https://github.com/tinygo-org/tinygo/issues/2169#issuecomment-985644057).\n\n### 🚥 Blinky\n\n![](https://img.shields.io/static/v1?label=\u0026message=app.go\u0026logo=go\u0026color=white)\n```go\npackage main\n\nimport (\n    \"machine\"\n    \"time\"\n)\n\nvar Output = machine.PinConfig{Mode: machine.PinOutput}\n\nfunc main() {\n    led := machine.LED // i.e. machine.D13 (a Pin)\n    led.Configure(Output)\n    for {\n        led.Low()\n        time.Sleep(1000 * time.Millisecond)\n        led.High()\n        time.Sleep(3000 * time.Millisecond)\n    }\n}\n```\n\n```bash\ntinygo flash -target=arduino app.go\n```\n\n\n\nℹ️ If you use [Visual Studio Code](https://code.visualstudio.com/), \nyou may install the [TinyGo extension](https://marketplace.visualstudio.com/items?itemName=tinygo.vscode-tinygo) and select the `arduino` target to get code completion and signature \nhelp for the `machine` package. \nFor more details, refer to the [TinyGo documentation](https://tinygo.org/docs/guides/ide-integration/vscode/).\n\n### 📄 Intel HEX\n\n\u003e **Intel hexadecimal object file format**, Intel hex format or Intellec Hex is a file format that conveys binary information in ASCII text form. It is commonly used for programming microcontrollers, EPROMs, and other types of programmable logic devices and hardware emulators. In a typical application, a compiler or assembler converts a program's source code (such as in C or assembly language) to machine code and outputs it into a HEX file. [...] The HEX file is then read by a programmer to write the machine code into a PROM or is transferred to the target system for loading and execution. \n\n([Wikipedia](https://en.wikipedia.org/wiki/Intel_HEX))\n\n```bash\ntinygo build -o app.hex -target=arduino app.go\n```\n\n```\n$ cat app.hex\n:100000000C9434000C9472020C9472020C947202E0\n:100010000C9472020C9472020C9464020C9472029E\n:100020000C9472020C9472020C9472020C94720280\n...\n:10007000BEBF0F92A0E0B3E0C4E6D3E0EEE1F5E04E\n:1005700066726F6D2041726475696E6F2120F09F05\n:02058000918B5D\n:00000001FF\n```\n\n```bash\npip install intelhex\n```\n\n```bash\n$ hexinfo.py app.hex\n- file: 'app.hex'\n  data:\n  - { first: 0x00000000, last: 0x00000581, length: 0x00000582 }\n```\n\n```pycon\n\u003e\u003e\u003e 0x00000582 \n1410\n```\n\n(1410 bytes, well below the 32 kb limit for Arduino Uno).\n\nThen instead of `tinygo flash`, do:\n\n```bash\navrdude -C /etc/avrdude.conf -p atmega328p -c arduino -P /dev/ttyACM0 -D -U flash:w:app.hex:i\n```\n\n```\n$ man avrdude\nAVRDUDE(1)                BSD General Commands Manual               AVRDUDE(1)\n\nNAME\n     avrdude — driver program for ``simple'' Atmel AVR MCU programmer\n\nSYNOPSIS\n     avrdude -p partno [-b baudrate] [-B bitclock] [-c programmer-id]\n             [-C config-file] [-D] [-e] [-E exitspec[,exitspec]] [-F]\n             [-i delay] [-n -logfile] [-n] [-O] [-P port] [-q] [-s] [-t] [-u]\n             [-U memtype:op:filename:filefmt] [-v] [-x extended_param] [-V]\n...\n```\n\n### 💻 WokWi Simulator\n\n![WokWi – Online Arduino Simulator](media/wokwi.png)\n\n 1. Sign into \u003chttps://wokwi.com/\u003e.\n\n 2. Start from Scratch with Arduino Uno. You may rename the project \"Blinky\"\ninstead of \"sketch.ino\" and delete the `sketch.ino` file ; we won't need it.\n\n 3. In the editor, right-click and open the command palette (or press F1).\n\n 4. Select \"Load HEX File and Start Simulation ...\" and upload your `app.hex` file.\n\n 5. Profit! 🎉\n\n### 🚥 LED\n\nTo replicate the Blinky project, but with an external LED instead of the \nonboard one, we need little change in the `app.go` program; if we intend\nto connect the LED D4, we have:\n\n![](https://img.shields.io/static/v1?label=\u0026message=app.go\u0026logo=go\u0026color=white)\n```go\npackage main\n\nimport (\n    \"machine\"\n    \"time\"\n)\n\nvar Output = machine.PinConfig{Mode: machine.PinOutput}\n\nfunc main() {\n    led := machine.D4\n    led.Configure(Output)\n    for {\n        led.Low()\n        time.Sleep(1000 * time.Millisecond)\n        led.High()\n        time.Sleep(3000 * time.Millisecond)\n    }\n}\n```\n\n![WokWi – External LED](media/wokwi-LED.png)\n\n\n### 🔲 Toggle Button + LED\n\nTo switch the LED state, press the button during at least 0.1 seconds, \nthen release it.\n\n![](https://img.shields.io/static/v1?label=\u0026message=app.go\u0026logo=go\u0026color=white)\n```go\npackage main\n\nimport (\n    \"machine\"\n    \"time\"\n)\n\nvar Input = machine.PinConfig{Mode: machine.PinInput}\nvar Output = machine.PinConfig{Mode: machine.PinOutput}\n\nvar ButtonPin = machine.D2\nvar ButtonWasPressed = false\n\nvar LightPin = machine.D4\nvar LightOn = false\n\nfunc setup() {\n    LightPin.Configure(Output)\n    ButtonPin.Configure(Input)\n}\n\nfunc ButtonHandler() {\n    ButtonPressed := !ButtonPin.Get()\n    ButtonRelease := !ButtonPressed \u0026\u0026 ButtonWasPressed\n    if ButtonRelease {\n        LightOn = !LightOn\n    }\n    ButtonWasPressed = ButtonPressed\n}\n\nfunc LightHandler() {\n    if LightOn {\n        LightPin.High()\n    } else {\n        LightPin.Low()\n    }\n}\n\nfunc main() {\n    setup()\n    for {\n        ButtonHandler()\n        LightHandler()\n        time.Sleep(100 * time.Millisecond)\n    }\n}\n```\n\n![WokWi – External LED](media/wokwi-button-LED.png)\n\n\n### 📉 ADC\n\n![](https://img.shields.io/static/v1?label=\u0026message=app.go\u0026logo=go\u0026color=white)\n```go\npackage main\n\nimport (\n    \"machine\"\n    \"time\"\n)\n\nvar adc = machine.ADC{Pin: machine.ADC0}\n\nfunc setup() {\n    machine.InitADC()\n}\n\nfunc main() {\n    setup()\n    for {\n        println(adc.Get() \u003e\u003e 6)\n        time.Sleep(1 * time.Second)\n    }\n}\n```\n\n![WokWi – ADC](media/wokwi-ADC.png)\n\n`diagram.json`:\n```json\n{\n  \"version\": 1,\n  \"author\": \"Sébastien Boisgérault\",\n  \"editor\": \"wokwi\",\n  \"parts\": [\n    { \"type\": \"wokwi-arduino-uno\", \"id\": \"uno\", \"top\": 0, \"left\": 0, \"attrs\": {} },\n    {\n      \"type\": \"wokwi-slide-potentiometer\",\n      \"id\": \"pot1\",\n      \"top\": 223.8,\n      \"left\": 38.76,\n      \"attrs\": { \"travelLength\": \"30\" }\n    }\n  ],\n  \"connections\": [\n    [ \"uno:GND.2\", \"pot1:GND\", \"black\", [ \"v36.18\", \"h-178.04\" ] ],\n    [ \"uno:5V\", \"pot1:VCC\", \"red\", [ \"v38.57\", \"h-120.71\" ] ],\n    [ \"uno:A0\", \"pot1:SIG\", \"green\", [ \"v21.83\", \"h56.09\", \"v118.38\", \"h-229.59\" ] ]\n  ]\n}\n```\n\n### 📈 PWM\n\nSee [Using PWM](https://tinygo.org/docs/tutorials/pwm/).\n\n⚠️ Floating-point computations are not used here. They are not supported by\nthe hardware and thus have to be emulated in software and this is costly.\n\n![](https://img.shields.io/static/v1?label=\u0026message=app.go\u0026logo=go\u0026color=white)\n```go\npackage main\n\nimport (\n    \"machine\"\n    \"time\"\n)\n\nvar pwm machine.PWM\nvar pwmPin = machine.D5\nvar period uint64\nvar ch uint8\n\nfunc setup() {\n    pwm.Configure(machine.PWMConfig{})\n    period = pwm.Period() // 16_000 ns\n    var err error\n    ch, err = pwm.Channel(pwmPin)\n    if err != nil {\n        panic(err)\n    }\n}\n\nfunc main() {\n    setup()\n    top := pwm.Top()\n    x := top\n    for {\n        println(x)\n        pwm.Set(ch, x)\n        x = x - top/100\n        if x == 0 {\n            x = top\n        }\n        time.Sleep(10 * time.Duration(period))\n    }\n}\n```\n\n![WokWi – ADC](media/wokwi-PWM.png)\n\n`diagram.json`:\n```json\n{\n  \"version\": 1,\n  \"author\": \"Sébastien Boisgérault\",\n  \"editor\": \"wokwi\",\n  \"parts\": [\n    { \"type\": \"wokwi-arduino-uno\", \"id\": \"uno\", \"top\": 159.41, \"left\": 11.03, \"attrs\": {} },\n    {\n      \"type\": \"wokwi-led\",\n      \"id\": \"led1\",\n      \"top\": 80.49,\n      \"left\": 149.12,\n      \"attrs\": { \"color\": \"green\" }\n    }\n  ],\n  \"connections\": [ [ \"uno:GND.1\", \"led1:C\", \"black\", [ \"v0\" ] ], [ \"uno:5\", \"led1:A\", \"green\", [ \"v0\" ] ] ]\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboisgera%2Ftinygo-arduino","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fboisgera%2Ftinygo-arduino","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboisgera%2Ftinygo-arduino/lists"}