Compare commits

...

158 Commits

Author SHA1 Message Date
Ron Evans 08cc84ce48 Updates for version 0.11 release
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2020-03-07 09:16:59 -08:00
Ron Evans 0c7b6c0d3c docs: update readme to correct count of supported drivers
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2020-03-07 09:16:08 -08:00
Ron Evans 8b11387d30 license: update year to 2020
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2020-03-07 09:11:30 -08:00
Ron Evans 41c6e3be0b shifter: simplify API surface for PyBadge (#137)
* shifter: simplify API surface and use build directive to directly match the PyBadge

Signed-off-by: Ron Evans <ron@hybridgroup.com>

* shifter: further simplify API for PyBadge

Signed-off-by: Ron Evans <ron@hybridgroup.com>
2020-03-06 07:29:30 +01:00
Daniel Esteban 583e80026a new API for shifter driver.
this doesn't break existing code, but it might no longer work as expected
2020-03-06 01:30:27 +00:00
Jean François CASSAN c7cbd7c6cd Shiftregister implementation (#135)
* Basic support of SIPO shift register

* typo

* add example of shiftregister for arduino and nucleo

* Fix build flag for nucleof103rb

* Fix wrong data pin configuration

* Change README.md for Shift registers

* Add API for individual register's output pin

* Rewrite shift register example to show ShiftPin usage

* Fix target for shiftregister example smoke test

* Fix type in makefile

* Add shiftregister compatble IC

* Edit comment and readme
2020-03-04 18:48:06 +01:00
Ron Evans 12ac4c2c06 mqtt: use buffered channels for incoming messages to handle bursts
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2020-03-03 09:29:18 +01:00
Ayke van Laethem 6380ad5ed5 semihosting: add example 2020-02-26 19:56:13 +01:00
Daniel Esteban d61fe99ef1 fix typo on StartScanNetworks 2020-02-26 19:55:12 +01:00
Daniel Esteban 8c7eed8d38 some fixes on ili9341 driver 2020-02-24 08:28:15 +01:00
BCG fbe36b62fd Adding scroll functionality for ili9341 (#121)
* ili9341: Adding scroll functionality
2020-02-08 21:12:20 +01:00
Daniel Esteban 0519540d0c fix celsius symbol 2020-02-08 19:54:31 +01:00
Jordan Christiansen 2034f92d11 README: Use degree sign instead of ordinal
º is the masculine ordinal in Spanish. ° is the degree sign. They look different in some fonts.
2020-02-08 19:32:10 +01:00
Ron Evans 850df0a25c release: update for version 0.10.0
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2020-01-31 18:43:12 +01:00
Ron Evans 5f4806f0f9 ws2812: work-arounds to allow Digispark to control WS2812 LEDs
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2020-01-30 14:24:39 +01:00
Daniel Esteban c8e62562b5 added scroll functionality to st7735 2020-01-30 10:20:45 +01:00
Ron Evans 6842bdb424 docs: update README to include list of all 44 drivers
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2020-01-28 19:27:24 +01:00
BCG d43263f764 Adding driver for four-wire resistive touchscreen (#118)
* resistive: Adding driver for four-wire resistive touchscreen, as used on the Adafruit PyPortal.
2020-01-28 18:55:31 +01:00
BCG 6716bb6c0a ILI9341 TFT driver (#115)
* ILI9341: TFT display implementation
2020-01-07 20:11:46 +01:00
BCG f4bccd1fed Added nrf52840 tag to ws2812 2020-01-06 07:37:21 +01:00
Ron Evans d5aa295b76 l9110x: add support for L9110x h-bridge motor driver
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2020-01-03 10:37:30 +01:00
Ron Evans c6e8af3057 l293x: added support for h-bridge motor controller
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2020-01-03 10:05:23 +01:00
Ron Evans 38076352eb wifinina: update docs and add Dockerfile to build firmware
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-12-29 17:45:41 +01:00
Ron Evans 086415605e wifinina: update docs and info on how to install WiFiNINA driver
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-12-26 16:34:35 +01:00
BCG 1d0f04af6b Support for ADT7410 temperature sensor (#109)
* ADT7410: add support for i2c temperature sensor
2019-12-26 13:53:06 +01:00
Daniel Esteban dc883d913d remove stxx defaults offsets 2019-12-24 17:36:20 +01:00
Ron Evans 3bb5b4519b docs: correct driver count in README
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-12-23 17:32:07 +01:00
Ron Evans c12f78eb50 Release: v0.9.0
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-12-23 17:09:00 +01:00
Daniel Esteban adb0c2c261 added generic 8bit shift register (#107)
* shifter: added generic 8bit shift register driver with ShiftPin Pin-compatible GPIO interface
2019-12-22 21:32:49 +01:00
Daniel Esteban 18f0722728 Dual stepper (#101)
* easystepper: added _DualDevice_ to move two motors at the same time
2019-12-22 10:33:02 +01:00
BCG e80a22d0ba Client driver for WiFiNINA firmware (#98)
* wifinina: implementation of WiFiNINA driver, including:
   - TCP client example is working
   - reading sockets and mqtt working
   - switched over to common net package also used by espat package
   - smoke tests and updated README for wifinina
2019-12-22 10:25:10 +01:00
BCG cc5ecafacf Decoupled net package from espat 2019-12-17 22:09:23 +01:00
Ayke van Laethem 7b56e61d52 ws2812: add support for simulation
Call a special __tinygo_ws2812_write_byte function to send a single
byte.
2019-12-14 22:16:41 +01:00
Ayke van Laethem 514b436889 ws2812: fix "invalid symbol redefinition" error
Named local labels shouldn't be used in LLVM because they might get
duplicated resulting in multiple symbol definitions and a compiler
error. Instead, use numeric labels.
2019-12-14 22:11:10 +01:00
BCG 7233452819 Added Feather M0 and Trinket M0 to build tags for WS2812 2019-12-12 14:28:21 +01:00
Ayke van Laethem 7929aa10ea all: add md5sum to smoke tests
This makes it easier to quickly compare all smoke tests for any changes.
2019-12-11 22:13:48 +01:00
Daniel Esteban 02084fd8a5 improvements in st7735/st7789 drivers 2019-12-08 16:38:05 +01:00
Jonathan Basseri f822da51fe Add support for Cortex-M4 120MHz
This adjusts the timing for 120MHz as seen on atsamd51 boards. The
timing was kept as close as possible to the Cortex-M4 64MHz logic in
ws2812_m4_64m.go.

Tested: This works on ItsyBitsy-M4
2019-12-06 11:33:55 +01:00
Jonathan Basseri c62d7db35d Fix number in comment
assembly comment was counting the # of nops.
2019-12-06 11:33:55 +01:00
Ron Evans 93372474a2 release: prepare for v0.8.0
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-11-26 20:40:16 +01:00
Ron Evans 7dcbfbecc6 espat: implement MQTT subscribe functionality via blocking select/channels.
also refactor response processing for greater speed and efficiency.

Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-11-25 15:56:09 +01:00
Ayke van Laethem 2e606b090a semihosting: initial implementation of ARM semihosting
Useful for logging output to the host console.
2019-11-06 18:53:33 +01:00
Ron Evans e0cdc931e7 mcp3008: add implementation for MCP3008 ADC with SPI interface
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-10-31 11:49:49 +01:00
Daniel Esteban 130d9de03b Merge pull request #92 from tinygo-org/st7789-buffer-overflow
st7789: fix index out of bounds error
2019-10-28 12:30:44 +01:00
Ayke van Laethem 2c2f1d3db4 st7789: fix index out of bounds error
This commit adds the same check to the st7789 that also exists in the
st7735.
2019-10-28 12:23:56 +01:00
Ron Evans 2413eb86e0 release: update versions to 0.7.0
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-10-17 13:18:24 +02:00
Ron Evans c7555a1469 espat: change all examples to use Arduino Nano33 IoT by default
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-10-17 13:16:39 +02:00
Ron Evans 3fca96e0ef docs: complete missing GoDocs for main and sub-packages
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-10-17 11:50:03 +02:00
Ron Evans c7981f72ec core: add Version string for support purposes
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-10-16 23:23:10 +02:00
Ron Evans 5df157230f lis3dh: example uses I2C1 so requires config to specify pins since they are not default
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-10-16 21:44:58 +02:00
Daniel Esteban bcb291992c ssd1331: make SPI TX faster
same change as PR #89
2019-10-13 02:02:22 +02:00
Daniel Esteban 7b710e3a48 Merge pull request #89 from tinygo-org/st7735-shrink-tx
st7735: make SPI Tx faster
2019-10-11 18:12:20 +02:00
Ayke van Laethem dcfd9c066d st7735: make SPI Tx faster
Most of the ceremony around pin toggling was in fact unnecessary. This
improves performance measurably (rougly 6% in one measurement) and cuts
down on binary size by 80 bytes.
2019-10-10 20:35:50 +02:00
cn 955b3a56e8 veml6070: add Vishay UV light sensor 2019-09-21 10:58:28 +02:00
Ron Evans 21b8d953f4 Update for 0.6.0 release
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-09-09 12:48:57 +02:00
BCG d1b917b835 Support software SPI for APA102 (Itsy Bitsy M0 on-board "Dotstar" LED as example) (#86)
* Added implementation and example to support software-based SPI for APA102, for use with boards like Adafruit Itsy Bitsy M0 for instance.
2019-09-09 12:31:17 +02:00
Ron Evans 2cd73e3204 release: update changelog for 0.5.0
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-08-26 11:34:59 +02:00
Daniel Esteban 3ae5895183 Initial support for LSM6DS3 IMU (#83)
* Initial support for LSM6DS3 IMU
2019-08-26 08:56:48 +02:00
Ayke van Laethem d80f619c9f ws2812: fix timings for the nrf51
The timings needed to be changed slightly for ws2811 chips which are
slightly slower.
2019-08-19 10:55:00 +02:00
Brad Erickson c91888a099 ws2812: Add build tag for Arduino Nano33 IoT
Uses `arduino_nano33` to handle only this board. Other boards with
the same chip will need a separate tag.
2019-08-15 17:38:27 +02:00
Ron Evans b4dbac3a67 release: update CHANGELOG for v0.4.0 release
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-08-07 15:44:00 +02:00
Daniel Esteban bf077c8249 SSD1331 TFT color display (#77) 2019-08-05 17:54:23 +02:00
Daniel Esteban 4867abcbba added driver for ST7789 TFT color display (#76) 2019-08-05 14:52:39 +02:00
Daniel Esteban 45922f6524 Driver ST7735 for TFT color displays (#72)
* Driver ST7735 for TFT color displays
2019-08-03 11:13:15 +02:00
Daniel Esteban eb040dde9c Merge pull request #78 from conejoninja/typo
typo
2019-08-02 19:57:51 +02:00
Daniel Esteban 04bfa6fa70 typo 2019-08-02 19:49:19 +02:00
Ayke van Laethem 8453611d1f espat: update README with how to install dependencies 2019-07-24 15:48:19 -07:00
Ron Evans d64069a517 release: update CHANGELOG with 0.3.0 release info
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-07-16 12:14:05 -07:00
Ron Evans e4b80d8e0e espat: add firmware install info for Arduino Nano33 IoT NINA-W102 chip
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-07-16 12:12:53 -07:00
Ron Evans 50633f3e86 espat: refactor net and tls interface compatible code into separate sub-packages
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-07-15 17:54:26 +02:00
Ron Evans 7e78e2c998 espat: add built-in support for MQTT publish using the Paho library packets, alongside some modifications needed for the AT protocol.
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-07-15 17:54:26 +02:00
Ron Evans 40d9287ac4 espat: add README with information on how to flash ESP32 or ESP8266 with AT command set firmware.
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-07-15 17:54:26 +02:00
Ron Evans 59aece351a espat: change Response() method to use a passed-in timeout value instead of fixed pauses.
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-07-15 17:54:26 +02:00
Ron Evans 1b81b992c2 espat: add DialTLS and Dial methods, update MQTT example to allow both MQTT and MQTTS connections
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-07-15 17:54:26 +02:00
Ron Evans 506819c93c espat: update MQTT example for greater stability
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-07-15 17:54:26 +02:00
Ron Evans 1d9e393948 espat: add example that uses MQTT publish to open server
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-07-15 17:54:26 +02:00
Ron Evans 9c88d1fab4 espat: add ResolveUDPAddr and ResolveTCPAddr implementations using AT command for DNS lookup
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-07-15 17:54:26 +02:00
Ron Evans a267fdb8ce espat: improve error handling for key TCP functions
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-07-15 17:54:26 +02:00
Ron Evans 500f3d9813 espat: implement TCPConn using AT command set
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-07-15 17:54:26 +02:00
Ron Evans fe58e9b762 espat: use only AT commands that work on both ESP8266 and ESP32
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-07-15 17:54:26 +02:00
Daniel Esteban d8675515bc epd2in13: added rotation 2019-07-15 01:35:33 +02:00
Daniel Esteban 28dbbe2e65 typo in package name of examples 2019-07-14 22:21:37 +02:00
Ayke van Laethem 78fdaad9c0 mpu6050: properly scale the outputs of the accel/gyro
Units were unspecified before but were in practice the raw output from
the sensor. They have now been changed to sensible outputs
understandable to humans, like the other accelerometers.
2019-07-14 22:20:51 +02:00
Daniel Esteban cb49783f18 Error strings should not be capitalized (unless beginning with proper
nouns or acronyms) or end with punctuation, since they are usually
printed following other context.
2019-07-08 18:52:31 +02:00
Ron Evans 8534e67c83 buzzer: buzzer timbres sound better with more bass
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-07-06 16:35:09 +02:00
Ron Evans 95755ebae7 buzzer: add simple buzzer implementation
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-07-06 16:35:09 +02:00
Ron Evans f4583f5144 microphone: PDM MEMS microphone support using I2S interface
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-07-05 14:52:54 +02:00
Ron Evans 1e59a3970e docs: add note to current/future contributors to please start by opening a GH issue to avoid duplication of efforts
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-06-06 12:12:24 +02:00
Ron Evans e4f6fbcb52 release: update changelog for v0.2.0
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-06-04 07:47:44 +02:00
Ron Evans 7487c6b3a2 docs: correct badge and link in README for godocs to use custom domain
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-06-03 19:45:18 +02:00
Ron Evans d1553458f5 bme280: add package docs, and add bme280 to README
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-06-03 19:39:30 +02:00
Daniel Esteban 79d3609f76 Support for AT24C32/64 2-wire serial EEPROM 2019-06-03 19:38:04 +02:00
Ayke van Laethem 00a9b9db77 ws2812: better support the nrf52832
This has cost me _hours_ to find. There are many clones of the ws2812
and they have slightly different timing characteristics. Some don't work
so well when you get close to the minimum T1H time: a 1-bit may be
interpreted as a 0-bit.
2019-06-03 19:25:24 +02:00
Martin Treml f68388702d Implementation of the BME280 Sensor (#38)
* Driver for bme280
2019-06-03 19:03:53 +02:00
Ron Evans 0722fe7161 docs: add CHANGELOG for first official release of drivers
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-05-29 16:28:08 +02:00
Ron Evans c09f0a8075 all: switch to using custom domain for all drivers
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-05-29 13:33:50 +02:00
Ron Evans 7757122598 docs: add contribution guidelines link to README and also show dev branch status in CI build
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-05-27 08:58:41 +02:00
Ron Evans 93849555f3 docs: add contribution guidelines to repo
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-05-27 08:54:36 +02:00
Ron Evans 3f946868e1 all: refactor all current drivers to use new machine.Pin interface
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-05-26 21:46:33 +02:00
Daniel Esteban 2c0bde0dad microbitmatrix: fix for dev branch / volatile package/API (#63)
* microbitmatrix: fix for dev branch / volatile package/API
2019-05-25 18:02:47 +02:00
Ron Evans 848385d625 docs: just to make clear what the driver is for
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-05-24 15:52:47 +02:00
k-brk dce063e0c2 Support for DS1307 (#58)
* Support for DS1307
2019-05-24 12:56:26 +02:00
Daniel Esteban 30b118cf63 support for Waveshare EPD 2.13" display (black&white only) (#61)
* support for Waveshare EPD 2.13" display (black&white only)
2019-05-24 12:37:02 +02:00
Ron Evans 9127719933 docs: add GPS to README
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-05-23 15:36:00 +02:00
Anthony Elder a24657d1eb GPS driver (#55)
* u-blox GPS driver for both I2C and UART
2019-05-23 15:29:29 +02:00
Ron Evans c259da1f17 build: use Makefile test command for CI tests
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-05-17 21:16:13 +02:00
Daniel Esteban 374d3f6bec Support for Waveshare 2.13" (B & C versions) e-paper display (#56)
* Support for Waveshare 2.13" (B) e-paper display
2019-05-17 07:55:57 +02:00
Anthony Elder 5930c149d9 SHT3x driver (#53)
* SHT3x driver
2019-05-12 16:11:15 +02:00
Daniel Esteban d22cf7a3e1 Driver for BBC micro:bit on-board LED matrix (#48) 2019-05-05 16:51:04 +02:00
Ron Evans a9e5c8f710 build: use tinygo-dev docker container for CI
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-05-05 16:28:38 +02:00
Daniel Esteban ad2b76be8b support for SSD1306 displays using I2C or SPI, several screen sizes (#49)
supported too
2019-05-05 11:45:26 +02:00
k-brk ba4de1efb8 SetPixel removed, formatting 2019-05-05 11:42:38 +02:00
k-brk 4560c61c61 GPIO implements io readwriter interface, simplified display, smoke tests 2019-05-05 11:42:38 +02:00
k-brk 715829cdbd Support for HD44780 in 4 and 8 bit mode 2019-05-05 11:42:38 +02:00
Ron Evans 8ac1fa2b22 adxl345: update ADXL345 driver and example to make uniform with other accelerometers
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-05-03 20:30:03 +02:00
Ron Evans b7fe897b8c mag3110: change method name/signature for obtaining temperature to be uniform with other similar drivers
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-05-03 20:26:43 +02:00
Daniel Esteban 35a7590c2d clean commit, added smoke tests 2019-05-03 11:44:56 +02:00
Ron Evans de22b8839e ci: ensure all examples are included in smoke tests
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-04-26 09:28:16 +02:00
Daniel Esteban 38e0d39f48 Initial support for RGB led matrix, usually called hub75 2019-04-26 09:24:08 +02:00
Ron Evans 59db5fef76 thermistor: add support for thermistors such as the NTC 3950
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-04-25 11:30:10 +02:00
Ron Evans c0cadf8d82 lis3dh: implement accelerometer functionality
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-04-24 20:10:57 +02:00
Ron Evans 720097ebad ci: perform go fmt test on all files
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-04-24 19:07:41 +02:00
Daniel Esteban 772a1044c4 Define common display interface (#31)
* issue #27 definition of Displayer interface
2019-04-24 18:56:49 +02:00
Ron Evans cd992bd7d6 bmp180: change method names/signature for obtaining temperature and pressure uniform with other similar drivers
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-04-24 15:17:26 +02:00
Ron Evans f6b9080f9e ci: show CircleCI badge in README
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-04-22 22:21:30 +02:00
Ron Evans 137e667d5a ci: setup CircleCI to build an example per driver as a smoke test suite
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-04-22 22:16:47 +02:00
Ron Evans cc391102ff ci: put CircleCI config file under correct name
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-04-22 19:01:31 +02:00
Ron Evans df3b3aa1ca ci: first start at setting up CircleCI for smoke tests
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-04-22 19:00:40 +02:00
Ron Evans 84b1cd0bfb docs: improve godocs formatting
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-04-22 11:12:28 +02:00
Ron Evans 8e384a00f1 docs: improve godocs formatting
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-04-22 11:11:28 +02:00
Ron Evans 7006a675ad docs: improve godocs formatting
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-04-22 11:10:11 +02:00
Ron Evans 1895c84912 docs: improve godocs info used by main package to explain what the package is and how to use it properly
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-04-22 11:07:43 +02:00
Ron Evans 3c68510cbc docs: improve godocs info used by main package to explain what the package is and how to use it
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-04-22 10:56:22 +02:00
Daniel Esteban a332118087 added DS3231 driver to README.md 2019-04-08 08:18:42 +02:00
Daniel Esteban ed2d334d55 Driver for ADXL345 3-axis digital accelerometer (#33)
* Driver for ADXL345 3-axis digital accelerometer
2019-04-08 08:18:03 +02:00
Daniel Esteban f6bdc9734f ds3231: basic support for DS3231 RTC device 2019-04-07 16:55:46 +02:00
Ron Evans d9b426b90b i2c: refactor all i2c drivers to use Address property of Driver. Allows variations to override the default address as discussed in #14 (#30)
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-04-07 10:50:34 +02:00
Ron Evans b8e278e08f examples: add example code for BlinkM
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-03-14 16:34:11 +01:00
Ayke van Laethem b0c4f3e2ce mma8653: return acceleration in a standard unit: micro-G. 2019-03-11 17:14:04 +01:00
Ron Evans c83475d09d docs: add VL53L1X to list of supported devices
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-03-06 17:49:37 +01:00
Daniel Esteban f144bfed79 Basic support for VL53L1X time-of-flight distance sensor (#20)
* Basic support for VL53L1X time-of-flight distance sensor
2019-03-06 17:42:17 +01:00
Ron Evans 8e1df6d63a examples: add basic usage example for mma8653
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-03-04 21:42:02 +01:00
Ron Evans 239c10a6ab examples: add example for mag3110 magnetometer
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-03-04 21:33:32 +01:00
Ron Evans 55d12ce0a1 examples: add basic usage example for ws2812
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-02-28 14:22:14 +01:00
Ayke van Laethem 7116778235 ws2812: add support for M0 at 48MHz: most SAMD21 boards 2019-02-24 23:10:10 +01:00
Ron Evans 0f7b458d9c docs: update README for current list of drivers
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-02-24 13:33:40 +01:00
Ron Evans 0c2924cd77 espat: add support for esp8266/esp32 Wifi adaptor AT command set with net-compatible UDP support
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-02-24 12:54:11 +01:00
Daniel Esteban ae53ea7d81 easystepper: very simple 4-wire stepper driver 2019-02-23 13:41:52 +01:00
Ayke van Laethem 4ff437e5d4 ws2812: add nrf52 support, update timings for m0 and avr
This commit adds support for the nrf52, which is a Cortex-M4 running at
64MHz.
While implementing this, I discovered that the timings for AVR/16MHz and
Cortex-M0 at 16MHz weren't quite right. They do work, but were slightly
out of spec. So I fixed this as well.
2019-02-22 07:10:22 +01:00
Ron Evans 1475a63798 docs: add BH1750 to README
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-02-08 09:10:02 +01:00
Daniel Esteban 693e7a1db7 Added driver for BH1750 digital ambient light sensor (#15)
* Added driver for BH1750 digital ambient light sensor
2019-02-08 09:04:58 +01:00
Ron Evans 31bc74101d examples: add example for apa102 (#17)
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-02-07 14:52:05 +01:00
Ron Evans 7dfd72c1b1 examples: add example for mpu6050 (#16)
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-02-07 14:51:45 +01:00
Ron Evans bb56d49ce3 rename: make sure package name is consistent in all places after move to organization
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-02-07 09:41:24 +01:00
Ron Evans 96b5daee8e license: add BSD-3 license for the TinyGo Authors
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-02-07 09:18:27 +01:00
Ron Evans be048a35bf docs: commit initial version of README file
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2019-02-07 08:35:07 +01:00
Daniel Esteban 3af2f18437 Initial support for BMP180 digital pressure sensor (#11)
* Initial support for BMP180 digital pressure sensor
Note that Pressure & Temperature return int32 and millis unit (millidegrees
and mPa)
2019-02-06 08:50:40 +01:00
Ron Evans 773b01e911 apa102: add support for APA102 SPI controlled LEDs
Signed-off-by: Ron Evans <ron@hybridgroup.com>
2018-12-22 19:14:02 +01:00
182 changed files with 18565 additions and 70 deletions
+18
View File
@@ -0,0 +1,18 @@
# Golang CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-go/ for more details
version: 2
jobs:
build:
docker:
- image: tinygo/tinygo-dev
working_directory: /usr/local/go/src/tinygo.org/x/drivers
steps:
- checkout
- run: tinygo version
- run:
name: "Enforce Go Formatted Code"
command: make fmt-check
- run:
name: "Run build and smoke tests"
command: make smoke-test
+1
View File
@@ -0,0 +1 @@
build
+169
View File
@@ -0,0 +1,169 @@
0.11.0
---
- **new devices**
- shiftregister: Support for various shift register chips (#135)
- **enhancements**
- shifter: simplify API surface for PyBadge (#137)
- shifter: new API for shifter driver
- mqtt: use buffered channels for incoming messages to handle bursts
- ili9341: Adding scroll functionality (#121)
- **bugfixes**
- wifinina: fix typo on StartScanNetworks
- ili9341: various bugfixes for display
- **examples**
- semihosting: add example
- **docs**
- readme: Use degree sign instead of ordinal
- all: fix celsius symbol in all code comments
0.10.0
---
- **new devices**
- adt7410: Support for ADT7410 temperature sensor (#109)
- ili9341: ILI9341 TFT driver (#115)
- l293x: added support for h-bridge motor controller
- l9110x: add support for L9110x h-bridge motor driver
- resistive: Adding driver for four-wire resistive touchscreen (#118)
- **enhancements**
- st7735: added scroll functionality to st7735
- st7735: remove default offsets
- st7789: remove default offsets
- ws2812: Added nrf52840 tag to ws2812
- ws2812: work-arounds to allow Digispark to control WS2812 LEDs
- **docs**
- readme: update README to include list of all 44 drivers
- wifinina: update docs and add Dockerfile to build firmware
- wifinina: update docs and info on how to install WiFiNINA driver
0.9.0
---
- **new devices**
- net: shared implementation of net package for serial wifi devices
- shifter: add support for bit Parallel In Serial Out (PISO) shifter
- stepper: add support for dual stepper motor
- wifinina: add implementation for WiFiNINA firmware
- **enhancements**
- st7735: improvements in st7735 driver
- st7789: improvements in st7789 driver
- ws2812: add support for 120Mhz Cortex-M4
- ws2812: added Feather M0 and Trinket M0 to build tags for WS2812
- ws2812: add support for simulation
- **bugfixes**
- ws2812: fix "invalid symbol redefinition" error
- **examples**
- Add examples for wifinina drivers
0.8.0
---
- **new devices**
- mcp3008: add implementation for MCP3008 ADC with SPI interface
- semihosting: initial implementation of ARM semihosting
- **enhancements**
- espat: refactor response processing for greater speed and efficiency
- espat: implement mqtt subscribe functionality via blocking select/channels (experiemental)
- **bugfixes**
- st7789: fix index out of bounds error
- **examples**
- Add espat driver example for mqtt subscribe
0.7.0
---
- **new devices**
- veml6070: add Vishay UV light sensor
- **enhancements**
- lis3dh: example uses I2C1 so requires config to specify pins since they are not default
- ssd1331: make SPI TX faster
- st7735: make SPI Tx faster
- **docs**
- complete missing GoDocs for main and sub-packages
- **core**
- add Version string for support purposes
- **examples**
- Change all espat driver examples to use Arduino Nano33 IoT by default
0.6.0
---
- **new devices**
- Support software SPI for APA102 (Itsy Bitsy M0 on-board "Dotstar" LED as example)
0.5.0
---
- **new devices**
- LSM6DS3 accelerometer
- **bugfixes**
- ws2812: fix timings for the nrf51
- **enhancements**
- ws2812: Add build tag for Arduino Nano33 IoT
0.4.0
---
- **new devices**
- SSD1331 TFT color display
- ST7735 TFT color display
- ST7789 TFT color display
- **docs**
- espat
- complete list of dependencies for flashing NINA-W102 as used in Arduino Nano33 IoT board.
0.3.0
---
- **new devices**
- Buzzer for piezo or small speaker
- PDM MEMS microphone support using I2S interface
- **enhancements**
- epd2in13: added rotation
- espat
- add built-in support for MQTT publish using the Paho library packets, alongside some modifications needed for the AT protocol.
- add DialTLS and Dial methods, update MQTT example to allow both MQTT and MQTTS connections
- add example that uses MQTT publish to open server
- add README with information on how to flash ESP32 or ESP8266 with AT command set firmware.
- add ResolveUDPAddr and ResolveTCPAddr implementations using AT command for DNS lookup
- change Response() method to use a passed-in timeout value instead of fixed pauses.
- implement TCPConn using AT command set
- improve error handling for key TCP functions
- refactor net and tls interface compatible code into separate sub-packages
- update MQTT example for greater stability
- use only AT commands that work on both ESP8266 and ESP32
- add documentation on how to use Arduino Nano33 IoT built-in WiFi NINA-W102 chip.
- **bugfixes**
- core: Error strings should not be capitalized (unless beginning with proper nouns or acronyms) or end with punctuation, since they are usually printed following other context.
- docs: add note to current/future contributors to please start by opening a GH issue to avoid duplication of efforts
- examples: typo in package name of examples
- mpu6050: properly scale the outputs of the accel/gyro
0.2.0
---
- **new devices**
- AT24C32/64 2-wire serial EEPROM
- BME280 humidity/pressure sensor
- **bugfixes**
- ws2812: better support for nrf52832
0.1.0
---
- **first release**
- This is the first official release of the TinyGo drivers repo, matching TinyGo 0.6.0. The following devices are supported:
- ADXL345
- APA102
- BH1750
- BlinkM
- BMP180
- DS1307
- DS3231
- Easystepper
- ESP8266/ESP32
- GPS
- HUB75
- LIS3DH
- MAG3110
- microbit LED matrix
- MMA8653
- MPU6050
- PCD8544
- SHT3x
- SSD1306
- Thermistor
- VL53L1X
- Waveshare 2.13"
- Waveshare 2.13" (B & C)
- WS2812
+40
View File
@@ -0,0 +1,40 @@
# How to contribute
Thank you for your interest in improving the TinyGo drivers.
We would like your help to make this project better, so we appreciate any contributions. See if one of the following descriptions matches your situation:
### New to TinyGo
We'd love to get your feedback on getting started with TinyGo. Run into any difficulty, confusion, or anything else? You are not alone. We want to know about your experience, so we can help the next people. Please open a Github issue with your questions, or you can also get in touch directly with us on our Slack channel at [https://gophers.slack.com/messages/CDJD3SUP6](https://gophers.slack.com/messages/CDJD3SUP6).
### One of the TinyGo drivers is not working as you expect
Please open a Github issue with your problem, and we will be happy to assist.
### Some specific hardware you want to use does not appear to be in the TinyGo drivers
We probably have not implemented it yet. Your contribution adding the hardware support to TinyGo would be greatly appreciated.
Please first open a Github issue. We want to help, and also make sure that there is no duplications of efforts. Sometimes what you need is already being worked on by someone else.
## How to use our Github repository
The `master` branch of this repo will always have the latest released version of the TinyGo drivers. All of the active development work for the next release will take place in the `dev` branch. The TinyGo drivers will use semantic versioning and will create a tag/release for each release.
Here is how to contribute back some code or documentation:
- Fork repo
- Create a feature branch off of the `dev` branch
- Make some useful change
- Make sure the tests still pass
- Submit a pull request against the `dev` branch.
- Be kind
## How to run tests
To run the tests:
```
make test
```
+27
View File
@@ -0,0 +1,27 @@
Copyright (c) 2018-2020 The TinyGo Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+127
View File
@@ -0,0 +1,127 @@
clean:
@rm -rf build
FMT_PATHS = ./*.go ./examples/**/*.go
fmt-check:
@unformatted=$$(gofmt -l $(FMT_PATHS)); [ -z "$$unformatted" ] && exit 0; echo "Unformatted:"; for fn in $$unformatted; do echo " $$fn"; done; exit 1
smoke-test:
@mkdir -p build
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/adt7410/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/adxl345/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/apa102/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/apa102/itsybitsy-m0/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/at24cx/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bh1750/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/blinkm/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/bmp180/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=bluepill ./examples/ds1307/sram/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=bluepill ./examples/ds1307/time/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/ds3231/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/easystepper/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/espat/espconsole/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/espat/esphub/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/espat/espstation/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/gps/i2c/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/gps/uart/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/hd44780/customchar/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/hd44780/text/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/hub75/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/ili9341/basic/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/ili9341/scroll/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/lis3dh/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/lsm6ds3/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mag3110/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mcp3008/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/microbitmatrix/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mma8653/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/mpu6050/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setbuffer/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setpixel/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=pybadge ./examples/shifter/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/sht3x/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ssd1306/i2c_128x32/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ssd1306/spi_128x64/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ssd1331/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/st7735/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/st7789/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/thermistor/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/touch/resistive/fourwire/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=pyportal ./examples/touch/resistive/pyportal_touchpaint/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/vl53l1x/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/waveshare-epd/epd2in13/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=microbit ./examples/waveshare-epd/epd2in13x/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/wifinina/tcpclient/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/wifinina/webclient/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/ws2812
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=digispark ./examples/ws2812
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=trinket-m0 ./examples/bme280/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/microphone/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=circuitplay-express ./examples/buzzer/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=trinket-m0 ./examples/veml6070/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/l293x/simple/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/l293x/speed/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/l9110x/simple/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/l9110x/speed/main.go
@md5sum ./build/test.hex
tinygo build -size short -o ./build/test.hex -target=nucleo-f103rb ./examples/shiftregister/main.go
@md5sum ./build/test.hex
test: clean fmt-check smoke-test
+112
View File
@@ -0,0 +1,112 @@
# TinyGo Drivers
[![GoDoc](https://godoc.org/tinygo.org/x/drivers?status.svg)](https://godoc.org/tinygo.org/x/drivers) [![CircleCI](https://circleci.com/gh/tinygo-org/drivers/tree/dev.svg?style=svg)](https://circleci.com/gh/tinygo-org/drivers/tree/dev)
This package provides a collection of hardware drivers for devices that can be used together with [TinyGo](https://tinygo.org).
## Installing
```shell
go get tinygo.org/x/drivers
```
## How to use
Here is an example in TinyGo that uses the BMP180 digital barometer:
```go
package main
import (
"time"
"machine"
"tinygo.org/x/drivers/bmp180"
)
func main() {
machine.I2C0.Configure(machine.I2CConfig{})
sensor := bmp180.New(machine.I2C0)
sensor.Configure()
connected := sensor.Connected()
if !connected {
println("BMP180 not detected")
return
}
println("BMP180 detected")
for {
temp, _ := sensor.ReadTemperature()
println("Temperature:", float32(temp)/1000, "°C")
pressure, _ := sensor.ReadPressure()
println("Pressure", float32(pressure)/100000, "hPa")
time.Sleep(2 * time.Second)
}
}
```
## Currently supported devices
The following 45 devices are supported.
| Device Name | Interface Type |
|----------|-------------|
| [ADT7410 I2C Temperature Sensor](https://www.analog.com/media/en/technical-documentation/data-sheets/ADT7410.pdf) | I2C |
| [ADXL345 accelerometer](http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf) | I2C |
| [APA102 RGB LED](https://cdn-shop.adafruit.com/product-files/2343/APA102C.pdf) | SPI |
| [AT24CX 2-wire serial EEPROM](https://www.openimpulse.com/blog/wp-content/uploads/wpsc/downloadables/24C32-Datasheet.pdf) | I2C |
| [BH1750 ambient light sensor](https://www.mouser.com/ds/2/348/bh1750fvi-e-186247.pdf) | I2C |
| [BlinkM RGB LED](http://thingm.com/fileadmin/thingm/downloads/BlinkM_datasheet.pdf) | I2C |
| [BME280 humidity/pressure sensor](https://cdn-shop.adafruit.com/datasheets/BST-BME280_DS001-10.pdf) | I2C |
| [BMP180 barometer](https://cdn-shop.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf) | I2C |
| [Buzzer](https://en.wikipedia.org/wiki/Buzzer#Piezoelectric) | GPIO |
| [DS1307 real time clock](https://datasheets.maximintegrated.com/en/ds/DS1307.pdf) | I2C |
| [DS3231 real time clock](https://datasheets.maximintegrated.com/en/ds/DS3231.pdf) | I2C |
| ["Easystepper" stepper motor controller](https://en.wikipedia.org/wiki/Stepper_motor) | GPIO |
| [ESP32 as WiFi Coprocessor with Arduino nina-fw](https://github.com/arduino/nina-fw) | SPI |
| [ESP8266/ESP32 AT Command set for WiFi/TCP/UDP](https://github.com/espressif/esp32-at) | UART |
| [GPS module](https://www.u-blox.com/en/product/neo-6-series) | I2C/UART |
| [HD44780 LCD controller](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) | GPIO |
| [HUB75 RGB led matrix](https://cdn-learn.adafruit.com/downloads/pdf/32x16-32x32-rgb-led-matrix.pdf) | SPI |
| [ILI9341 TFT color display](https://cdn-shop.adafruit.com/datasheets/ILI9341.pdf) | SPI |
| [L293x motor driver](https://www.ti.com/lit/ds/symlink/l293d.pdf) | GPIO/PWM |
| [L9110x motor driver](https://www.elecrow.com/download/datasheet-l9110.pdf) | GPIO/PWM |
| [LIS3DH accelerometer](https://www.st.com/resource/en/datasheet/lis3dh.pdf) | I2C |
| [LSM6DS3 accelerometer](https://www.st.com/resource/en/datasheet/lsm6ds3.pdf) | I2C |
| [MAG3110 magnetometer](https://www.nxp.com/docs/en/data-sheet/MAG3110.pdf) | I2C |
| [MCP3008 analog to digital converter (ADC)](http://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf) | SPI |
| [BBC micro:bit LED matrix](https://github.com/bbcmicrobit/hardware/blob/master/SCH_BBC-Microbit_V1.3B.pdf) | GPIO |
| [Microphone - PDM](https://cdn-learn.adafruit.com/assets/assets/000/049/977/original/MP34DT01-M.pdf) | I2S/PDM |
| [MMA8653 accelerometer](https://www.nxp.com/docs/en/data-sheet/MMA8653FC.pdf) | I2C |
| [MPU6050 accelerometer/gyroscope](https://store.invensense.com/datasheets/invensense/MPU-6050_DataSheet_V3%204.pdf) | I2C |
| [PCD8544 display](http://eia.udg.edu/~forest/PCD8544_1.pdf) | SPI |
| [Resistive Touchscreen (4-wire)](http://ww1.microchip.com/downloads/en/Appnotes/doc8091.pdf) | GPIO |
| [Semihosting](https://wiki.segger.com/Semihosting) | Debug |
| [Shift register (PISO)](https://en.wikipedia.org/wiki/Shift_register#Parallel-in_serial-out_\(PISO\)) | GPIO |
| [Shift registers (SIPO)](https://en.wikipedia.org/wiki/Shift_register#Serial-in_parallel-out_(SIPO)) | GPIO |
| [SHT3x Digital Humidity Sensor](https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/0_Datasheets/Humidity/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf) | I2C |
| [SSD1306 OLED display](https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf) | I2C / SPI |
| [SSD1331 TFT color display](https://www.crystalfontz.com/controllers/SolomonSystech/SSD1331/381/) | SPI |
| [ST7735 TFT color display](https://www.crystalfontz.com/controllers/Sitronix/ST7735R/319/) | SPI |
| [ST7789 TFT color display](https://cdn-shop.adafruit.com/product-files/3787/3787_tft_QT154H2201__________20190228182902.pdf) | SPI |
| [Thermistor](https://www.farnell.com/datasheets/33552.pdf) | ADC |
| [VEML6070 UV light sensor](https://www.vishay.com/docs/84277/veml6070.pdf) | I2C |
| [VL53L1X time-of-flight distance sensor](https://www.st.com/resource/en/datasheet/vl53l1x.pdf) | I2C |
| [Waveshare 2.13" e-paper display](https://www.waveshare.com/w/upload/e/e6/2.13inch_e-Paper_Datasheet.pdf) | SPI |
| [Waveshare 2.13" (B & C) e-paper display](https://www.waveshare.com/w/upload/d/d3/2.13inch-e-paper-b-Specification.pdf) | SPI |
| [WS2812 RGB LED](https://cdn-shop.adafruit.com/datasheets/WS2812.pdf) | GPIO |
## Contributing
Your contributions are welcome!
Please take a look at our [CONTRIBUTING.md](./CONTRIBUTING.md) document for details.
## License
This project is licensed under the BSD 3-clause license, just like the [Go project](https://golang.org/LICENSE) itself.
+90
View File
@@ -0,0 +1,90 @@
package adt7410
import (
"machine"
"time"
)
type Error uint8
const (
ErrInvalidID Error = 0x1
)
func (e Error) Error() string {
switch e {
case ErrInvalidID:
return "Invalid chip ID"
default:
return "Unknown error"
}
}
type Device struct {
bus *machine.I2C
buf []byte
addr uint8
}
// New returns ADT7410 device for the provided I2C bus and address. The ADT7410
// has a default address of 0x48 (1001000). The last 2 bits of the address
// can be set using by connecting to the A1 and A0 pins to VDD or GND (for a
// total of up to 4 devices on a I2C bus). Also note that 10k pullups are
// recommended for the SDA and SCL lines.
func New(i2c *machine.I2C, addressBits uint8) *Device {
return &Device{
bus: i2c,
buf: make([]byte, 2),
addr: Address | (addressBits & 0x3),
}
}
func (dev *Device) Configure() (err error) {
// verify the chip ID
// TODO: According to datasheet, the check below should work; however
// this does not seem to be working right, but is not exactly
// necessary, so can revisit later to see if there is a bug
//id := dev.ReadByte(RegID) & 0xF8
//if id != 0xC8 {
// err = ErrInvalidID
//}
// reset the chip
dev.writeByte(RegReset, 0xFF)
time.Sleep(10 * time.Millisecond)
return
}
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000)
func (d *Device) ReadTemperature() (temperature int32, err error) {
return (int32(d.readUint16(RegTempValueMSB)) * 1000) / 128, nil
}
// ReadTempC returns the value in the temperature value register, in Celcius
func (d *Device) ReadTempC() float32 {
t := d.readUint16(RegTempValueMSB)
return float32(int(t)) / 128.0
}
// ReadTempF returns the value in the temperature value register, in Fahrenheit
func (d *Device) ReadTempF() float32 {
return d.ReadTempC()*1.8 + 32.0
}
func (d *Device) writeByte(reg uint8, data byte) {
d.buf[0] = reg
d.buf[1] = data
d.bus.Tx(uint16(d.addr), d.buf, nil)
}
func (d *Device) readByte(reg uint8) byte {
d.bus.ReadRegister(d.addr, reg, d.buf)
return d.buf[0]
}
func (d *Device) readUint16(reg uint8) uint16 {
d.bus.ReadRegister(d.addr, reg, d.buf)
return uint16(d.buf[0])<<8 | uint16(d.buf[1])
}
+24
View File
@@ -0,0 +1,24 @@
package adt7410
const (
// Default I2C address
Address = 0x48
// Temperature Value MSB Register
RegTempValueMSB = 0x0
// Temperature Value LSB Register
RegTempValueLSB = 0x1
// Status Register
RegStatus = 0x2
// Config Register
RegConfig = 0x3
// ID Register
RegID = 0x0B
// Software Reset Register
RegReset = 0x2F
)
+195
View File
@@ -0,0 +1,195 @@
// Package adxl345 provides a driver for the ADXL345 digital accelerometer.
//
// Datasheet EN: http://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf
//
// Datasheet JP: http://www.analog.com/media/jp/technical-documentation/data-sheets/ADXL345_jp.pdf
//
package adxl345 // import "tinygo.org/x/drivers/adxl345"
import (
"machine"
)
type Range uint8
type Rate uint8
// Internal structure for the power configuration
type powerCtl struct {
link uint8
autoSleep uint8
measure uint8
sleep uint8
wakeUp uint8
}
// Internal structure for the sensor's data format configuration
type dataFormat struct {
selfTest uint8
spi uint8
intInvert uint8
fullRes uint8
justify uint8
sensorRange Range
}
// Internal structure for the sampling rate configuration
type bwRate struct {
lowPower uint8
rate Rate
}
// Device wraps an I2C connection to a ADXL345 device.
type Device struct {
bus machine.I2C
Address uint16
powerCtl powerCtl
dataFormat dataFormat
bwRate bwRate
}
// New creates a new ADXL345 connection. The I2C bus must already be
// configured.
//
// This function only creates the Device object, it does not init the device.
// To do that you must call the Configure() method on the Device before using it.
func New(bus machine.I2C) Device {
return Device{
bus: bus,
powerCtl: powerCtl{
measure: 1,
},
dataFormat: dataFormat{
sensorRange: RANGE_2G,
},
bwRate: bwRate{
lowPower: 1,
rate: RATE_100HZ,
},
Address: AddressLow,
}
}
// Configure sets up the device for communication
func (d *Device) Configure() {
d.bus.WriteRegister(uint8(d.Address), REG_BW_RATE, []byte{d.bwRate.toByte()})
d.bus.WriteRegister(uint8(d.Address), REG_POWER_CTL, []byte{d.powerCtl.toByte()})
d.bus.WriteRegister(uint8(d.Address), REG_DATA_FORMAT, []byte{d.dataFormat.toByte()})
}
// Halt stops the sensor, values will not updated
func (d *Device) Halt() {
d.powerCtl.measure = 0
d.bus.WriteRegister(uint8(d.Address), REG_POWER_CTL, []byte{d.powerCtl.toByte()})
}
// Restart makes reading the sensor working again after a halt
func (d *Device) Restart() {
d.powerCtl.measure = 1
d.bus.WriteRegister(uint8(d.Address), REG_POWER_CTL, []byte{d.powerCtl.toByte()})
}
// ReadAcceleration reads the current acceleration from the device and returns
// it in µg (micro-gravity). When one of the axes is pointing straight to Earth
// and the sensor is not moving the returned value will be around 1000000 or
// -1000000.
func (d *Device) ReadAcceleration() (x int32, y int32, z int32, err error) {
rx, ry, rz := d.ReadRawAcceleration()
x = d.dataFormat.convertToIS(rx)
y = d.dataFormat.convertToIS(ry)
z = d.dataFormat.convertToIS(rz)
return
}
// ReadRawAcceleration reads the sensor values and returns the raw x, y and z axis
// from the adxl345.
func (d *Device) ReadRawAcceleration() (x int32, y int32, z int32) {
data := []byte{0, 0, 0, 0, 0, 0}
d.bus.ReadRegister(uint8(d.Address), REG_DATAX0, data)
x = readIntLE(data[0], data[1])
y = readIntLE(data[2], data[3])
z = readIntLE(data[4], data[5])
return
}
// UseLowPower sets the ADXL345 to use the low power mode.
func (d *Device) UseLowPower(power bool) {
if power {
d.bwRate.lowPower = 1
} else {
d.bwRate.lowPower = 0
}
d.bus.WriteRegister(uint8(d.Address), REG_BW_RATE, []byte{d.bwRate.toByte()})
}
// SetRate change the current rate of the sensor
func (d *Device) SetRate(rate Rate) bool {
d.bwRate.rate = rate & 0x0F
d.bus.WriteRegister(uint8(d.Address), REG_BW_RATE, []byte{d.bwRate.toByte()})
return true
}
// SetRange change the current range of the sensor
func (d *Device) SetRange(sensorRange Range) bool {
d.dataFormat.sensorRange = sensorRange & 0x03
d.bus.WriteRegister(uint8(d.Address), REG_DATA_FORMAT, []byte{d.dataFormat.toByte()})
return true
}
// convertToIS adjusts the raw values from the adxl345 with the range configuration
func (d *dataFormat) convertToIS(rawValue int32) int32 {
switch d.sensorRange {
case RANGE_2G:
return rawValue * 4 // rawValue * 2 * 1000 / 512
case RANGE_4G:
return rawValue * 8 // rawValue * 4 * 1000 / 512
case RANGE_8G:
return rawValue * 16 // rawValue * 8 * 1000 / 512
case RANGE_16G:
return rawValue * 32 // rawValue * 16 * 1000 / 512
default:
return 0
}
}
// toByte returns a byte from the powerCtl configuration
func (p *powerCtl) toByte() (bits uint8) {
bits = 0x00
bits = bits | (p.link << 5)
bits = bits | (p.autoSleep << 4)
bits = bits | (p.measure << 3)
bits = bits | (p.sleep << 2)
bits = bits | p.wakeUp
return bits
}
// toByte returns a byte from the dataFormat configuration
func (d *dataFormat) toByte() (bits uint8) {
bits = 0x00
bits = bits | (d.selfTest << 7)
bits = bits | (d.spi << 6)
bits = bits | (d.intInvert << 5)
bits = bits | (d.fullRes << 3)
bits = bits | (d.justify << 2)
bits = bits | uint8(d.sensorRange)
return bits
}
// toByte returns a byte from the bwRate configuration
func (b *bwRate) toByte() (bits uint8) {
bits = 0x00
bits = bits | (b.lowPower << 4)
bits = bits | uint8(b.rate)
return bits
}
// readInt converts two bytes to int16
func readIntLE(msb byte, lsb byte) int32 {
return int32(uint16(msb) | uint16(lsb)<<8)
}
+61
View File
@@ -0,0 +1,61 @@
package adxl345
const AddressLow = 0x53
const AddressHigh = 0x1D
const (
// Data rate
RATE_3200HZ Rate = 0x0F // 3200 Hz
RATE_1600HZ Rate = 0x0E // 1600 Hz
RATE_800HZ Rate = 0x0D // 800 Hz
RATE_400HZ Rate = 0x0C // 400 Hz
RATE_200HZ Rate = 0x0B // 200 Hz
RATE_100HZ Rate = 0x0A // 100 Hz
RATE_50HZ Rate = 0x09 // 50 Hz
RATE_25HZ Rate = 0x08 // 25 Hz
RATE_12_5HZ Rate = 0x07 // 12.5 Hz
RATE_6_25HZ Rate = 0x06 // 6.25 Hz
RATE_3_13HZ Rate = 0x05 // 3.13 Hz
RATE_1_56HZ Rate = 0x04 // 1.56 Hz
RATE_0_78HZ Rate = 0x03 // 0.78 Hz
RATE_0_39HZ Rate = 0x02 // 0.39 Hz
RATE_0_20HZ Rate = 0x01 // 0.20 Hz
RATE_0_10HZ Rate = 0x00 // 0.10 Hz
// Data range
RANGE_2G Range = 0x00 // +-2 g
RANGE_4G Range = 0x01 // +-4 g
RANGE_8G Range = 0x02 // +-8 g
RANGE_16G Range = 0x03 // +-16 g)
REG_DEVID = 0x00 // R, 11100101, Device ID
REG_THRESH_TAP = 0x1D // R/W, 00000000, Tap threshold
REG_OFSX = 0x1E // R/W, 00000000, X-axis offset
REG_OFSY = 0x1F // R/W, 00000000, Y-axis offset
REG_OFSZ = 0x20 // R/W, 00000000, Z-axis offset
REG_DUR = 0x21 // R/W, 00000000, Tap duration
REG_LATENT = 0x22 // R/W, 00000000, Tap latency
REG_WINDOW = 0x23 // R/W, 00000000, Tap window
REG_THRESH_ACT = 0x24 // R/W, 00000000, Activity threshold
REG_THRESH_INACT = 0x25 // R/W, 00000000, Inactivity threshold
REG_TIME_INACT = 0x26 // R/W, 00000000, Inactivity time
REG_ACT_INACT_CTL = 0x27 // R/W, 00000000, Axis enable control for activity and inactiv ity detection
REG_THRESH_FF = 0x28 // R/W, 00000000, Free-fall threshold
REG_TIME_FF = 0x29 // R/W, 00000000, Free-fall time
REG_TAP_AXES = 0x2A // R/W, 00000000, Axis control for single tap/double tap
REG_ACT_TAP_STATUS = 0x2B // R, 00000000, Source of single tap/double tap
REG_BW_RATE = 0x2C // R/W, 00001010, Data rate and power mode control
REG_POWER_CTL = 0x2D // R/W, 00000000, Power-saving features control
REG_INT_ENABLE = 0x2E // R/W, 00000000, Interrupt enable control
REG_INT_MAP = 0x2F // R/W, 00000000, Interrupt mapping control
REG_INT_SOUCE = 0x30 // R, 00000010, Source of interrupts
REG_DATA_FORMAT = 0x31 // R/W, 00000000, Data format control
REG_DATAX0 = 0x32 // R, 00000000, X-Axis Data 0
REG_DATAX1 = 0x33 // R, 00000000, X-Axis Data 1
REG_DATAY0 = 0x34 // R, 00000000, Y-Axis Data 0
REG_DATAY1 = 0x35 // R, 00000000, Y-Axis Data 1
REG_DATAZ0 = 0x36 // R, 00000000, Z-Axis Data 0
REG_DATAZ1 = 0x37 // R, 00000000, Z-Axis Data 1
REG_FIFO_CTL = 0x38 // R/W, 00000000, FIFO control
REG_FIFO_STATUS = 0x39 // R, 00000000, FIFO status
)
+99
View File
@@ -0,0 +1,99 @@
// Package apa102 implements a driver for the APA102 SPI LED.
//
// Datasheet: https://cdn-shop.adafruit.com/product-files/2343/APA102C.pdf
package apa102 // import "tinygo.org/x/drivers/apa102"
import (
"image/color"
"machine"
)
const (
// BGR aka "Blue Green Red" is the current APA102 LED color order.
BGR = iota
// BRG aka "Blue Red Green" is the typical APA102 color order from 2015-2017.
BRG
// GRB aka "Green Red Blue" is the typical APA102 color order from pre-2015.
GRB
)
// Device wraps APA102 SPI LEDs.
type Device struct {
bus SPI
Order int
}
// The SPI interface specifies the minimum functionality that a bus
// implementation needs to provide for use by the APA102 driver. Hardware
// SPI from the TinyGo "machine" package implements this already.
type SPI interface {
Tx(w, r []byte) error
}
// New returns a new APA102 driver. Pass in a fully configured SPI bus.
func New(b SPI) Device {
return Device{bus: b, Order: BGR}
}
// NewSoftwareSPI returns a new APA102 driver that will use a software based
// implementation of the SPI protocol.
func NewSoftwareSPI(sckPin, mosiPin machine.Pin, delay uint32) Device {
return New(&bbSPI{SCK: sckPin, MOSI: mosiPin, Delay: delay})
}
// WriteColors writes the given RGBA color slice out using the APA102 protocol.
// The A value (Alpha channel) is used for brightness, set to 0xff (255) for maximum.
func (d Device) WriteColors(cs []color.RGBA) (n int, err error) {
d.startFrame()
// write data
for _, c := range cs {
// brightness is scaled to 5 bit value
d.bus.Tx([]byte{0xe0 | (c.A >> 3)}, nil)
// set the colors
switch d.Order {
case BRG:
d.bus.Tx([]byte{c.B}, nil)
d.bus.Tx([]byte{c.R}, nil)
d.bus.Tx([]byte{c.G}, nil)
case GRB:
d.bus.Tx([]byte{c.G}, nil)
d.bus.Tx([]byte{c.R}, nil)
d.bus.Tx([]byte{c.B}, nil)
case BGR:
d.bus.Tx([]byte{c.B}, nil)
d.bus.Tx([]byte{c.G}, nil)
d.bus.Tx([]byte{c.R}, nil)
}
}
d.endFrame(len(cs))
return len(cs), nil
}
// Write the raw bytes using the APA102 protocol.
func (d Device) Write(buf []byte) (n int, err error) {
d.startFrame()
d.bus.Tx(buf, nil)
d.endFrame(len(buf) / 4)
return len(buf), nil
}
// startFrame sends the start bytes for a strand of LEDs.
func (d Device) startFrame() {
d.bus.Tx([]byte{0x00, 0x00, 0x00, 0x00}, nil)
}
// endFrame sends the end frame marker with one extra bit per LED so
// long strands of LEDs receive the necessary termination for updates.
// See https://cpldcpu.wordpress.com/2014/11/30/understanding-the-apa102-superled/
func (d Device) endFrame(count int) {
for i := 0; i < count/16; i++ {
d.bus.Tx([]byte{0xff}, nil)
}
}
+68
View File
@@ -0,0 +1,68 @@
package apa102
import "machine"
// bbSPI is a dumb bit-bang implementation of SPI protocol that is hardcoded
// to mode 0 and ignores trying to receive data. Just enough for the APA102.
// Note: making this unexported for now because it is probable not suitable
// most purposes other than the APA102 package. It might be desirable to make
// this more generic and include it in the TinyGo "machine" package instead.
type bbSPI struct {
SCK machine.Pin
MOSI machine.Pin
Delay uint32
}
// Configure sets up the SCK and MOSI pins as outputs and sets them low
func (s *bbSPI) Configure() {
s.SCK.Configure(machine.PinConfig{Mode: machine.PinOutput})
s.MOSI.Configure(machine.PinConfig{Mode: machine.PinOutput})
s.SCK.Low()
s.MOSI.Low()
if s.Delay == 0 {
s.Delay = 1
}
}
// Tx matches signature of machine.SPI.Tx() and is used to send multiple bytes.
// The r slice is ignored and no error will ever be returned.
func (s *bbSPI) Tx(w []byte, r []byte) error {
s.Configure()
for _, b := range w {
s.Transfer(b)
}
return nil
}
// delay represents a quarter of the clock cycle
func (s *bbSPI) delay() {
for i := uint32(0); i < s.Delay; {
i++
}
}
// Transfer is used to send a single byte.
func (s *bbSPI) Transfer(b byte) {
for i := uint8(0); i < 8; i++ {
// half clock cycle high to start
s.SCK.High()
s.delay()
// write the value to MOSI (MSB first)
if b&(1<<(7-i)) == 0 {
s.MOSI.Low()
} else {
s.MOSI.High()
}
s.delay()
// half clock cycle low
s.SCK.Low()
s.delay()
// for actual SPI would try to read the MISO value here
s.delay()
}
}
+171
View File
@@ -0,0 +1,171 @@
// Package at24cx provides a driver for the AT24C32/64/128/256/512 2-wire serial EEPROM
//
// Datasheet:
// https://www.openimpulse.com/blog/wp-content/uploads/wpsc/downloadables/24C32-Datasheet.pdf
package at24cx // import "tinygo.org/x/drivers/at24cx"
import (
"errors"
"machine"
"time"
)
// Device wraps an I2C connection to a DS3231 device.
type Device struct {
bus machine.I2C
Address uint16
pageSize uint16
currentRAMAddress uint16
startRAMAddress uint16
endRAMAddress uint16
}
type Config struct {
PageSize uint16
StartRAMAddress uint16
EndRAMAddress uint16
}
// New creates a new AT24C32/64 connection. The I2C bus must already be
// configured.
//
// This function only creates the Device object, it does not touch the device.
func New(bus machine.I2C) Device {
return Device{
bus: bus,
Address: Address,
}
}
// Configure sets up the device for communication
func (d *Device) Configure(cfg Config) {
if cfg.PageSize == 0 {
d.pageSize = 32
} else {
d.pageSize = cfg.PageSize
}
if cfg.EndRAMAddress == 0 {
d.endRAMAddress = 4096
} else {
d.endRAMAddress = cfg.EndRAMAddress
}
d.startRAMAddress = cfg.StartRAMAddress
}
// WriteByte writes a byte at the specified address
func (d *Device) WriteByte(eepromAddress uint16, value uint8) error {
address := []uint8{
uint8((eepromAddress >> 8) & 0xFF),
uint8(eepromAddress & 0xFF),
value,
}
return d.bus.Tx(d.Address, address, nil)
}
// ReadByte reads the byte at the specified address
func (d *Device) ReadByte(eepromAddress uint16) (uint8, error) {
address := []uint8{
uint8(eepromAddress >> 8),
uint8(eepromAddress & 0xFF),
}
data := make([]uint8, 1)
err := d.bus.Tx(d.Address, address, data)
return data[0], err
}
// WriteAt writes a byte array at the specified address
func (d *Device) WriteAt(data []byte, offset int64) (n int, err error) {
return d.writeAt(data, uint16(offset))
}
// writeAt writes a byte array at the specified address
func (d *Device) writeAt(data []byte, offset uint16) (n int, err error) {
values := make([]uint8, 32)
dataLeft := uint16(len(data))
d.currentRAMAddress = offset
offset = 0
var offsetPage uint16
var chunkLength uint16
for dataLeft > 0 {
offsetPage = d.currentRAMAddress % d.pageSize
if dataLeft < 30 { // The 32K/64K EEPROM is capable of 32-byte page writes and we're using 2 for the address
chunkLength = dataLeft
} else {
chunkLength = 30
}
if (d.pageSize - offsetPage) < chunkLength {
chunkLength = d.pageSize - offsetPage
}
for i := uint16(0); i < chunkLength; i++ {
values[2+i] = data[offset+i]
}
values[0] = uint8(d.currentRAMAddress >> 8)
values[1] = uint8(d.currentRAMAddress & 0xFF)
err := d.bus.Tx(d.Address, values[:chunkLength+2], nil)
if err != nil {
return 0, err
}
dataLeft -= chunkLength
offset += chunkLength
if d.endRAMAddress-chunkLength < d.currentRAMAddress {
d.currentRAMAddress = d.startRAMAddress + (d.currentRAMAddress+uint16(len(data)))%d.endRAMAddress
} else {
d.currentRAMAddress += chunkLength
}
time.Sleep(2 * time.Millisecond) // writing again too soon will block the device
}
return len(data), nil
}
// ReadAt reads the bytes at the specified address
func (d *Device) ReadAt(data []byte, offset int64) (n int, err error) {
return d.readAt(data, uint16(offset))
}
// readAt reads the bytes at the specified address
func (d *Device) readAt(data []byte, offset uint16) (n int, err error) {
address := []uint8{
uint8((offset >> 8) & 0xFF),
uint8(offset & 0xFF),
}
err = d.bus.Tx(d.Address, address, data)
if d.endRAMAddress-uint16(len(data)) < offset {
d.currentRAMAddress = d.startRAMAddress + (offset+uint16(len(data)))%d.endRAMAddress
} else {
d.currentRAMAddress = offset + uint16(len(data))
}
return len(data), err
}
// Seek sets the offset for the next Read or Write on SRAM to offset, interpreted
// according to whence: 0 means relative to the origin of the SRAM, 1 means
// relative to the current offset, and 2 means relative to the end.
// returns new offset and error, if any
func (d *Device) Seek(offset int64, whence int) (int64, error) {
w := uint16(0)
switch whence {
case 0:
w = d.startRAMAddress
case 1:
w = d.currentRAMAddress
case 2:
w = d.endRAMAddress
default:
return 0, errors.New("invalid whence")
}
d.currentRAMAddress = w + uint16(offset)
return int64(d.currentRAMAddress), nil
}
// Write writes len(data) bytes to SRAM
// returns number of bytes written and error, if any
func (d *Device) Write(data []byte) (n int, err error) {
return d.writeAt(data, d.currentRAMAddress)
}
// Read reads len(data) from SRAM
// returns number of bytes written and error, if any
func (d *Device) Read(data []uint8) (n int, err error) {
return d.readAt(data, d.currentRAMAddress)
}
+4
View File
@@ -0,0 +1,4 @@
package at24cx
// The I2C address which this device listens to.
const Address = 0x57
+72
View File
@@ -0,0 +1,72 @@
// Package bh1750 provides a driver for the BH1750 digital Ambient Light
//
// Datasheet:
// https://www.mouser.com/ds/2/348/bh1750fvi-e-186247.pdf
//
package bh1750 // import "tinygo.org/x/drivers/bh1750"
import (
"time"
"machine"
)
// SamplingMode is the sampling's resolution of the measurement
type SamplingMode byte
// Device wraps an I2C connection to a bh1750 device.
type Device struct {
bus machine.I2C
Address uint16
mode SamplingMode
}
// New creates a new bh1750 connection. The I2C bus must already be
// configured.
//
// This function only creates the Device object, it does not touch the device.
func New(bus machine.I2C) Device {
return Device{
bus: bus,
Address: Address,
mode: CONTINUOUS_HIGH_RES_MODE,
}
}
// Configure sets up the device for communication
func (d *Device) Configure() {
d.bus.Tx(d.Address, []byte{POWER_ON}, nil)
d.SetMode(d.mode)
}
// RawSensorData returns the raw value from the bh1750
func (d *Device) RawSensorData() uint16 {
buf := []byte{1, 0}
d.bus.Tx(d.Address, nil, buf)
return (uint16(buf[0]) << 8) | uint16(buf[1])
}
// Illuminance returns the adjusted value in mlx (milliLux)
func (d *Device) Illuminance() int32 {
lux := uint32(d.RawSensorData())
var coef uint32
if d.mode == CONTINUOUS_HIGH_RES_MODE || d.mode == ONE_TIME_HIGH_RES_MODE {
coef = HIGH_RES
} else if d.mode == CONTINUOUS_HIGH_RES_MODE_2 || d.mode == ONE_TIME_HIGH_RES_MODE_2 {
coef = HIGH_RES2
} else {
coef = LOW_RES
}
// 100 * coef * lux * (5/6)
// 5/6 = measurement accuracy as per the datasheet
return int32(250 * coef * lux / 3)
}
// SetMode changes the reading mode for the sensor
func (d *Device) SetMode(mode SamplingMode) {
d.mode = mode
d.bus.Tx(d.Address, []byte{byte(d.mode)}, nil)
time.Sleep(10 * time.Millisecond)
}
+24
View File
@@ -0,0 +1,24 @@
package bh1750
// Constants/addresses used for I2C.
// The I2C address which this device listens to.
const Address = 0x23
// Registers. Names, addresses and comments copied from the datasheet.
const (
POWER_DOWN = 0x00
POWER_ON = 0x01
RESET = 0x07
CONTINUOUS_HIGH_RES_MODE SamplingMode = 0x10
CONTINUOUS_HIGH_RES_MODE_2 SamplingMode = 0x11
CONTINUOUS_LOW_RES_MODE SamplingMode = 0x13
ONE_TIME_HIGH_RES_MODE SamplingMode = 0x20
ONE_TIME_HIGH_RES_MODE_2 SamplingMode = 0x21
ONE_TIME_LOW_RES_MODE SamplingMode = 0x23
// resolution in 10*lx
HIGH_RES = 10
HIGH_RES2 = 5
LOW_RES = 40
)
+14 -8
View File
@@ -1,7 +1,7 @@
// Package blinkm implements a driver for the BlinkM I2C RGB LED.
//
// Datasheet: http://thingm.com/fileadmin/thingm/downloads/BlinkM_datasheet.pdf
package blinkm
package blinkm // import "tinygo.org/x/drivers/blinkm"
import (
"machine"
@@ -9,7 +9,8 @@ import (
// Device wraps an I2C connection to a BlinkM device.
type Device struct {
bus machine.I2C
bus machine.I2C
Address uint16
}
// New creates a new BlinkM connection. The I2C bus must already be
@@ -17,38 +18,43 @@ type Device struct {
//
// This function only creates the Device object, it does not touch the device.
func New(bus machine.I2C) Device {
return Device{bus}
return Device{bus, Address}
}
// Configure sets up the device for communication
func (d *Device) Configure() {
d.bus.Tx(d.Address, []byte{'o'}, nil)
}
// Version returns the version of firmware on the BlinkM.
func (d Device) Version() (major, minor byte, err error) {
version := []byte{0, 0}
d.bus.ReadRegister(Address, GET_FIRMWARE, version)
d.bus.Tx(d.Address, []byte{GET_FIRMWARE}, version)
return version[0], version[1], nil
}
// SetRGB sets the RGB color on the BlinkM.
func (d Device) SetRGB(r, g, b byte) error {
d.bus.WriteRegister(Address, TO_RGB, []byte{r, g, b})
d.bus.Tx(d.Address, []byte{TO_RGB, r, g, b}, nil)
return nil
}
// GetRGB gets the current RGB color on the BlinkM.
func (d Device) GetRGB() (r, g, b byte, err error) {
color := []byte{0, 0, 0}
d.bus.ReadRegister(Address, GET_RGB, color)
d.bus.Tx(d.Address, []byte{GET_RGB}, color)
return color[0], color[1], color[2], nil
}
// FadeToRGB sets the RGB color on the BlinkM by fading from the current color
// to the new color.
func (d Device) FadeToRGB(r, g, b byte) error {
d.bus.WriteRegister(Address, FADE_TO_RGB, []byte{r, g, b})
d.bus.Tx(d.Address, []byte{FADE_TO_RGB, r, g, b}, nil)
return nil
}
// StopScript stops whatever script is currently running on the BlinkM.
func (d Device) StopScript() error {
d.bus.WriteRegister(Address, STOP_SCRIPT, nil)
d.bus.Tx(d.Address, []byte{STOP_SCRIPT}, nil)
return nil
}
+257
View File
@@ -0,0 +1,257 @@
// Package bme280 provides a driver for the BME280 digital combined
// humidity and pressure sensor by Bosch.
//
// Datasheet:
// https://cdn-shop.adafruit.com/datasheets/BST-BME280_DS001-10.pdf
//
package bme280
import (
"machine"
"math"
)
// calibrationCoefficients reads at startup and stores the calibration coefficients
type calibrationCoefficients struct {
t1 uint16
t2 int16
t3 int16
p1 uint16
p2 int16
p3 int16
p4 int16
p5 int16
p6 int16
p7 int16
p8 int16
p9 int16
h1 uint8
h2 int16
h3 uint8
h4 int16
h5 int16
h6 int8
}
// Device wraps an I2C connection to a BME280 device.
type Device struct {
bus machine.I2C
Address uint16
calibrationCoefficients calibrationCoefficients
}
// New creates a new BME280 connection. The I2C bus must already be
// configured.
//
// This function only creates the Device object, it does not touch the device.
func New(bus machine.I2C) Device {
return Device{
bus: bus,
Address: Address,
}
}
// Configure sets up the device for communication and
// read the calibration coefficientes.
func (d *Device) Configure() {
var data [24]byte
err := d.bus.ReadRegister(uint8(d.Address), REG_CALIBRATION, data[:])
if err != nil {
return
}
var h1 [1]byte
err = d.bus.ReadRegister(uint8(d.Address), REG_CALIBRATION_H1, h1[:])
if err != nil {
return
}
var h2lsb [7]byte
err = d.bus.ReadRegister(uint8(d.Address), REG_CALIBRATION_H2LSB, h2lsb[:])
if err != nil {
return
}
d.calibrationCoefficients.t1 = readUintLE(data[0], data[1])
d.calibrationCoefficients.t2 = readIntLE(data[2], data[3])
d.calibrationCoefficients.t3 = readIntLE(data[4], data[5])
d.calibrationCoefficients.p1 = readUintLE(data[6], data[7])
d.calibrationCoefficients.p2 = readIntLE(data[8], data[9])
d.calibrationCoefficients.p3 = readIntLE(data[10], data[11])
d.calibrationCoefficients.p4 = readIntLE(data[12], data[13])
d.calibrationCoefficients.p5 = readIntLE(data[14], data[15])
d.calibrationCoefficients.p6 = readIntLE(data[16], data[17])
d.calibrationCoefficients.p7 = readIntLE(data[18], data[19])
d.calibrationCoefficients.p8 = readIntLE(data[20], data[21])
d.calibrationCoefficients.p9 = readIntLE(data[22], data[23])
d.calibrationCoefficients.h1 = h1[0]
d.calibrationCoefficients.h2 = readIntLE(h2lsb[0], h2lsb[1])
d.calibrationCoefficients.h3 = h2lsb[2]
d.calibrationCoefficients.h6 = int8(h2lsb[6])
d.calibrationCoefficients.h4 = 0 + (int16(h2lsb[3]) << 4) | (int16(h2lsb[4] & 0x0F))
d.calibrationCoefficients.h5 = 0 + (int16(h2lsb[5]) << 4) | (int16(h2lsb[4]) >> 4)
d.bus.WriteRegister(uint8(d.Address), CTRL_HUMIDITY_ADDR, []byte{0x3f})
d.bus.WriteRegister(uint8(d.Address), CTRL_MEAS_ADDR, []byte{0xB7})
d.bus.WriteRegister(uint8(d.Address), CTRL_CONFIG, []byte{0x00})
}
// Connected returns whether a BME280 has been found.
// It does a "who am I" request and checks the response.
func (d *Device) Connected() bool {
data := []byte{0}
d.bus.ReadRegister(uint8(d.Address), WHO_AM_I, data)
return data[0] == CHIP_ID
}
// Reset the device
func (d *Device) Reset() {
d.bus.WriteRegister(uint8(d.Address), CMD_RESET, []byte{0xB6})
}
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000)
func (d *Device) ReadTemperature() (int32, error) {
data, err := d.readData()
if err != nil {
return 0, err
}
temp, _ := d.calculateTemp(data)
return temp, nil
}
// ReadPressure returns the pressure in milli pascals mPa
func (d *Device) ReadPressure() (int32, error) {
data, err := d.readData()
if err != nil {
return 0, err
}
_, tFine := d.calculateTemp(data)
pressure := d.calculatePressure(data, tFine)
return pressure, nil
}
// ReadHumidity returns the relative humidity in hundredths of a percent
func (d *Device) ReadHumidity() (int32, error) {
data, err := d.readData()
if err != nil {
return 0, err
}
_, tFine := d.calculateTemp(data)
humidity := d.calculateHumidity(data, tFine)
return humidity, nil
}
// ReadAltitude returns the current altitude in meters based on the
// current barometric pressure and estimated pressure at sea level.
// Calculation is based on code from Adafruit BME280 library
// https://github.com/adafruit/Adafruit_BME280_Library
func (d *Device) ReadAltitude() (alt int32, err error) {
mPa, _ := d.ReadPressure()
atmP := float32(mPa) / 100000
alt = int32(44330.0 * (1.0 - math.Pow(float64(atmP/SEALEVEL_PRESSURE), 0.1903)))
return
}
// convert2Bytes converts two bytes to int32
func convert2Bytes(msb byte, lsb byte) int32 {
return int32(readUint(msb, lsb))
}
// convert3Bytes converts three bytes to int32
func convert3Bytes(msb byte, b1 byte, lsb byte) int32 {
return int32(((((uint32(msb) << 8) | uint32(b1)) << 8) | uint32(lsb)) >> 4)
}
// readUint converts two bytes to uint16
func readUint(msb byte, lsb byte) uint16 {
return (uint16(msb) << 8) | uint16(lsb)
}
// readUintLE converts two little endian bytes to uint16
func readUintLE(msb byte, lsb byte) uint16 {
temp := readUint(msb, lsb)
return (temp >> 8) | (temp << 8)
}
// readIntLE converts two little endian bytes to int16
func readIntLE(msb byte, lsb byte) int16 {
return int16(readUintLE(msb, lsb))
}
// readData does a burst read from 0xF7 to 0xF0 according to the datasheet
// resulting in an slice with 8 bytes 0-2 = pressure / 3-5 = temperature / 6-7 = humidity
func (d *Device) readData() (data [8]byte, err error) {
err = d.bus.ReadRegister(uint8(d.Address), REG_PRESSURE, data[:])
if err != nil {
println(err)
return
}
return
}
// calculateTemp uses the data slice and applies calibrations values on it to convert the value to milli degrees
// it also calculates the variable tFine which is used by the pressure and humidity calculation
func (d *Device) calculateTemp(data [8]byte) (int32, int32) {
rawTemp := convert3Bytes(data[3], data[4], data[5])
var1 := (((rawTemp >> 3) - (int32(d.calibrationCoefficients.t1) << 1)) * int32(d.calibrationCoefficients.t2)) >> 11
var2 := (((((rawTemp >> 4) - int32(d.calibrationCoefficients.t1)) * ((rawTemp >> 4) - int32(d.calibrationCoefficients.t1))) >> 12) * int32(d.calibrationCoefficients.t3)) >> 14
tFine := var1 + var2
T := (tFine*5 + 128) >> 8
return (10 * T), tFine
}
// calculatePressure uses the data slice and applies calibrations values on it to convert the value to milli pascals mPa
func (d *Device) calculatePressure(data [8]byte, tFine int32) int32 {
rawPressure := convert3Bytes(data[0], data[1], data[2])
var1 := int64(tFine) - 128000
var2 := var1 * var1 * int64(d.calibrationCoefficients.p6)
var2 = var2 + ((var1 * int64(d.calibrationCoefficients.p5)) << 17)
var2 = var2 + (int64(d.calibrationCoefficients.p4) << 35)
var1 = ((var1 * var1 * int64(d.calibrationCoefficients.p3)) >> 8) + ((var1 * int64(d.calibrationCoefficients.p2)) << 12)
var1 = ((int64(1) << 47) + var1) * int64(d.calibrationCoefficients.p1) >> 33
if var1 == 0 {
return 0 // avoid exception caused by division by zero
}
p := int64(1048576 - rawPressure)
p = (((p << 31) - var2) * 3125) / var1
var1 = (int64(d.calibrationCoefficients.p9) * (p >> 13) * (p >> 13)) >> 25
var2 = (int64(d.calibrationCoefficients.p8) * p) >> 19
p = ((p + var1 + var2) >> 8) + (int64(d.calibrationCoefficients.p7) << 4)
p = (p / 256)
return int32(1000 * p)
}
// calculateHumidity uses the data slice and applies calibrations values on it to convert the value to relative humidity in hundredths of a percent
func (d *Device) calculateHumidity(data [8]byte, tFine int32) int32 {
rawHumidity := convert2Bytes(data[6], data[7])
h := float32(tFine) - 76800
if h == 0 {
println("invalid value")
}
var1 := float32(rawHumidity) - (float32(d.calibrationCoefficients.h4)*64.0 +
(float32(d.calibrationCoefficients.h5) / 16384.0 * h))
var2 := float32(d.calibrationCoefficients.h2) / 65536.0 *
(1.0 + float32(d.calibrationCoefficients.h6)/67108864.0*h*
(1.0+float32(d.calibrationCoefficients.h3)/67108864.0*h))
h = var1 * var2
h = h * (1 - float32(d.calibrationCoefficients.h1)*h/524288)
return int32(100 * h)
}
+25
View File
@@ -0,0 +1,25 @@
package bme280
// Constants/addresses used for I2C.
// The I2C address which this device listens to.
const Address = 0x76
// Registers. Names, addresses and comments copied from the datasheet.
const (
CTRL_MEAS_ADDR = 0xF4
CTRL_HUMIDITY_ADDR = 0xF2
CTRL_CONFIG = 0xF5
REG_PRESSURE = 0xF7
REG_CALIBRATION = 0x88
REG_CALIBRATION_H1 = 0xA1
REG_CALIBRATION_H2LSB = 0xE1
CMD_RESET = 0xE0
WHO_AM_I = 0xD0
CHIP_ID = 0x60
)
const (
SEALEVEL_PRESSURE float32 = 1013.25 // in hPa
)
+183
View File
@@ -0,0 +1,183 @@
// Package bmp180 provides a driver for the BMP180 digital pressure sensor
// by Bosch.
//
// Datasheet:
// https://cdn-shop.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf
//
package bmp180 // import "tinygo.org/x/drivers/bmp180"
import (
"time"
"machine"
)
// OversamplingMode is the oversampling ratio of the pressure measurement.
type OversamplingMode uint
// calibrationCoefficients reads at startup and stores the calibration coefficients
type calibrationCoefficients struct {
ac1 int16
ac2 int16
ac3 int16
ac4 uint16
ac5 uint16
ac6 uint16
b1 int16
b2 int16
mb int16
mc int16
md int16
}
// Device wraps an I2C connection to a BMP180 device.
type Device struct {
bus machine.I2C
Address uint16
mode OversamplingMode
calibrationCoefficients calibrationCoefficients
}
// New creates a new BMP180 connection. The I2C bus must already be
// configured.
//
// This function only creates the Device object, it does not initialize the device.
// You must call Configure() first in order to use the device itself.
func New(bus machine.I2C) Device {
return Device{
bus: bus,
Address: Address,
mode: ULTRAHIGHRESOLUTION,
}
}
// Connected returns whether a BMP180 has been found.
// It does a "who am I" request and checks the response.
func (d *Device) Connected() bool {
data := []byte{0}
d.bus.ReadRegister(uint8(d.Address), WHO_AM_I, data)
return data[0] == CHIP_ID
}
// Configure sets up the device for communication and
// read the calibration coefficients.
func (d *Device) Configure() {
data := make([]byte, 22)
err := d.bus.ReadRegister(uint8(d.Address), AC1_MSB, data)
if err != nil {
return
}
d.calibrationCoefficients.ac1 = readInt(data[0], data[1])
d.calibrationCoefficients.ac2 = readInt(data[2], data[3])
d.calibrationCoefficients.ac3 = readInt(data[4], data[5])
d.calibrationCoefficients.ac4 = readUint(data[6], data[7])
d.calibrationCoefficients.ac5 = readUint(data[8], data[9])
d.calibrationCoefficients.ac6 = readUint(data[10], data[11])
d.calibrationCoefficients.b1 = readInt(data[12], data[13])
d.calibrationCoefficients.b2 = readInt(data[14], data[15])
d.calibrationCoefficients.mb = readInt(data[16], data[17])
d.calibrationCoefficients.mc = readInt(data[18], data[19])
d.calibrationCoefficients.md = readInt(data[20], data[21])
}
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000).
func (d *Device) ReadTemperature() (temperature int32, err error) {
rawTemp, err := d.rawTemp()
if err != nil {
return
}
b5 := d.calculateB5(rawTemp)
t := (b5 + 8) >> 4
return 100 * t, nil
}
// ReadPressure returns the pressure in milli pascals (mPa).
func (d *Device) ReadPressure() (pressure int32, err error) {
rawTemp, err := d.rawTemp()
if err != nil {
return
}
rawPressure, err := d.rawPressure(d.mode)
if err != nil {
return
}
b5 := d.calculateB5(rawTemp)
b6 := b5 - 4000
x1 := (int32(d.calibrationCoefficients.b2) * (b6 * b6 >> 12)) >> 11
x2 := (int32(d.calibrationCoefficients.ac2) * b6) >> 11
x3 := x1 + x2
b3 := (((int32(d.calibrationCoefficients.ac1)*4 + x3) << uint(d.mode)) + 2) >> 2
x1 = (int32(d.calibrationCoefficients.ac3) * b6) >> 13
x2 = (int32(d.calibrationCoefficients.b1) * ((b6 * b6) >> 12)) >> 16
x3 = ((x1 + x2) + 2) >> 2
b4 := (uint32(d.calibrationCoefficients.ac4) * uint32(x3+32768)) >> 15
b7 := uint32(rawPressure-b3) * (50000 >> uint(d.mode))
var p int32
if b7 < 0x80000000 {
p = int32((b7 << 1) / b4)
} else {
p = int32((b7 / b4) << 1)
}
x1 = (p >> 8) * (p >> 8)
x1 = (x1 * 3038) >> 16
x2 = (-7357 * p) >> 16
return 1000 * (p + ((x1 + x2 + 3791) >> 4)), nil
}
// rawTemp returns the sensor's raw values of the temperature
func (d *Device) rawTemp() (int16, error) {
d.bus.WriteRegister(uint8(d.Address), REG_CTRL, []byte{CMD_TEMP})
time.Sleep(5 * time.Millisecond)
data := make([]byte, 2)
err := d.bus.ReadRegister(uint8(d.Address), REG_TEMP_MSB, data)
if err != nil {
return 0, err
}
return readInt(data[0], data[1]), nil
}
// calculateB5 calculates intermediate value B5 as per page 15 of datasheet
func (d *Device) calculateB5(rawTemp int16) int32 {
x1 := (int32(rawTemp) - int32(d.calibrationCoefficients.ac6)) * int32(d.calibrationCoefficients.ac5) >> 15
x2 := int32(d.calibrationCoefficients.mc) << 11 / (x1 + int32(d.calibrationCoefficients.md))
return x1 + x2
}
// rawPressure returns the sensor's raw values of the pressure
func (d *Device) rawPressure(mode OversamplingMode) (int32, error) {
d.bus.WriteRegister(uint8(d.Address), REG_CTRL, []byte{CMD_PRESSURE + byte(mode<<6)})
time.Sleep(pauseForReading(mode))
data := make([]byte, 3)
err := d.bus.ReadRegister(uint8(d.Address), REG_PRESSURE_MSB, data)
if err != nil {
return 0, err
}
rawPressure := int32((uint32(data[0])<<16 + uint32(data[1])<<8 + uint32(data[2])) >> (8 - uint(mode)))
return rawPressure, nil
}
// pauseForReading returns the pause duration depending on the sampling mode
func pauseForReading(mode OversamplingMode) time.Duration {
var d time.Duration
switch mode {
case ULTRALOWPOWER:
d = 5 * time.Millisecond
case STANDARD:
d = 8 * time.Millisecond
case HIGHRESOLUTION:
d = 14 * time.Millisecond
case ULTRAHIGHRESOLUTION:
d = 26 * time.Millisecond
}
return d
}
// readInt converts two bytes to int16
func readInt(msb byte, lsb byte) int16 {
return int16(uint16(msb)<<8 | uint16(lsb))
}
// readUint converts two bytes to uint16
func readUint(msb byte, lsb byte) uint16 {
return (uint16(msb) << 8) | uint16(lsb)
}
+30
View File
@@ -0,0 +1,30 @@
package bmp180
// Constants/addresses used for I2C.
// The I2C address which this device listens to.
const Address = 0x77
// Registers. Names, addresses and comments copied from the datasheet.
const (
AC1_MSB = 0xAA // Calibration coefficients start at 0xAA ends at 0xBF
CMD_TEMP = 0x2E
CMD_PRESSURE = 0x34
REG_CTRL = 0xF4
REG_TEMP_MSB = 0xF6
REG_PRESSURE_MSB = 0xF6
WHO_AM_I = 0xD0
CHIP_ID = 0x55
)
const (
// ULTRALOWPOWER is the lowest oversampling mode of the pressure measurement.
ULTRALOWPOWER OversamplingMode = iota
// BSTANDARD is the standard oversampling mode of the pressure measurement.
STANDARD
// HIGHRESOLUTION is a high oversampling mode of the pressure measurement.
HIGHRESOLUTION
// ULTRAHIGHRESOLUTION is the highest oversampling mode of the pressure measurement.
ULTRAHIGHRESOLUTION
)
+71
View File
@@ -0,0 +1,71 @@
// Package buzzer provides a very simplistic driver for a connected buzzer or low-fidelity speaker.
//
package buzzer // import "tinygo.org/x/drivers/buzzer"
import (
"machine"
"time"
)
// Device wraps a GPIO connection to a buzzer.
type Device struct {
pin machine.Pin
High bool
BPM float64
}
// New returns a new buzzer driver given which pin to use
func New(pin machine.Pin) Device {
return Device{
pin: pin,
High: false,
BPM: 96.0,
}
}
// On sets the buzzer to a high state.
func (l *Device) On() (err error) {
l.pin.Set(true)
l.High = true
return
}
// Off sets the buzzer to a low state.
func (l *Device) Off() (err error) {
l.pin.Set(false)
l.High = false
return
}
// Toggle sets the buzzer to the opposite of it's current state
func (l *Device) Toggle() (err error) {
if l.High {
err = l.Off()
} else {
err = l.On()
}
return
}
// Tone plays a tone of the requested frequency and duration.
func (l *Device) Tone(hz, duration float64) (err error) {
// calculation based off https://www.arduino.cc/en/Tutorial/Melody
tone := (1.0 / (2.0 * hz)) * 1000000.0
tempo := ((60 / l.BPM) * (duration * 1000))
for i := 0.0; i < tempo*1000; i += tone * 2.0 {
if err = l.On(); err != nil {
return
}
time.Sleep(time.Duration(tone) * time.Microsecond)
if err = l.Off(); err != nil {
return
}
time.Sleep(time.Duration(tone) * time.Microsecond)
}
return
}
+121
View File
@@ -0,0 +1,121 @@
package buzzer
const (
Whole = 4
Half = 2
Quarter = 1
Eighth = 0.500
)
// The values seem like they are little off, so feel free to make corrections, as needed.
const (
Rest = 0
C0 = 16.35
Db0 = 17.32
D0 = 18.35
Eb0 = 19.45
E0 = 20.60
F0 = 21.83
Gb0 = 23.12
G0 = 24.50
Ab0 = 25.96
A0 = 27.50
Bb0 = 29.14
B0 = 30.87
C1 = 32.70
Db1 = 34.65
D1 = 36.71
Eb1 = 38.89
E1 = 41.20
F1 = 43.65
Gb1 = 46.25
G1 = 49.00
Ab1 = 51.91
A1 = 55.00
Bb1 = 58.27
B1 = 61.74
C2 = 65.41
Db2 = 69.30
D2 = 73.42
Eb2 = 77.78
E2 = 82.41
F2 = 87.31
Gb2 = 92.50
G2 = 98.00
Ab2 = 103.83
A2 = 110.00
Bb2 = 116.54
B2 = 123.47
C3 = 130.81
Db3 = 138.59
D3 = 146.83
Eb3 = 155.56
E3 = 164.81
F3 = 174.61
Gb3 = 185.00
G3 = 196.00
Ab3 = 207.65
A3 = 220.00
Bb3 = 233.08
B3 = 246.94
C4 = 261.63
Db4 = 277.18
D4 = 293.66
Eb4 = 311.13
E4 = 329.63
F4 = 349.23
Gb4 = 369.99
G4 = 392.00
Ab4 = 415.30
A4 = 440.00
Bb4 = 466.16
B4 = 493.88
C5 = 523.25
Db5 = 554.37
D5 = 587.33
Eb5 = 622.25
E5 = 659.25
F5 = 698.46
Gb5 = 739.99
G5 = 783.99
Ab5 = 830.61
A5 = 880.00
Bb5 = 932.33
B5 = 987.77
C6 = 1046.50
Db6 = 1108.73
D6 = 1174.66
Eb6 = 1244.51
E6 = 1318.51
F6 = 1396.91
Gb6 = 1479.98
G6 = 1567.98
Ab6 = 1661.22
A6 = 1760.00
Bb6 = 1864.66
B6 = 1975.53
C7 = 2093.00
Db7 = 2217.46
D7 = 2349.32
Eb7 = 2489.02
E7 = 2637.02
F7 = 2793.83
Gb7 = 2959.96
G7 = 3135.96
Ab7 = 3322.44
A7 = 3520.00
Bb7 = 3729.31
B7 = 3951.07
C8 = 4186.01
Db8 = 4434.92
D8 = 4698.63
Eb8 = 4978.03
E8 = 5274.04
F8 = 5587.65
Gb8 = 5919.91
G8 = 6271.93
Ab8 = 6644.88
A8 = 7040.00
Bb8 = 7458.62
B8 = 7902.13
)
+14
View File
@@ -0,0 +1,14 @@
package drivers
import "image/color"
type Displayer interface {
// Size returns the current size of the display.
Size() (x, y int16)
// SetPizel modifies the internal buffer.
SetPixel(x, y int16, c color.RGBA)
// Display sends the buffer (if any) to the screen.
Display() error
}
+42 -4
View File
@@ -1,4 +1,42 @@
// Package drivers is just a placeholder for the sub-packages.
// It is here just to be able to install the package without errors using
// go get -d github.com/ayke/tinygo-drivers
package drivers
// Package drivers provides a collection of hardware drivers for TinyGo (https://tinygo.org)
// for devices such as sensors and displays.
//
// Here is an example in TinyGo that uses the BMP180 digital barometer:
//
// package main
//
// import (
// "time"
// "machine"
//
// "tinygo.org/x/drivers/bmp180"
// )
//
// func main() {
// machine.I2C0.Configure(machine.I2CConfig{})
// sensor := bmp180.New(machine.I2C0)
// sensor.Configure()
//
// connected := sensor.Connected()
// if !connected {
// println("BMP180 not detected")
// return
// }
// println("BMP180 detected")
//
// for {
// temp, _ := sensor.ReadTemperature()
// println("Temperature:", float32(temp)/1000, "°C")
//
// pressure, _ := sensor.ReadPressure()
// println("Pressure", float32(pressure)/100000, "hPa")
//
// time.Sleep(2 * time.Second)
// }
// }
//
// Each individual driver is contained within its own sub-package within this package and
// there are no interdependencies in order to minimize the final size of compiled code that
// uses any of these drivers.
//
package drivers // import "tinygo.org/x/drivers"
+173
View File
@@ -0,0 +1,173 @@
// Package ds1307 provides a driver for the DS1307 RTC
//
// Datasheet:
// https://datasheets.maximintegrated.com/en/ds/DS1307.pdf
//
package ds1307 // import "tinygo.org/x/drivers/ds1307"
import (
"errors"
"time"
"machine"
)
// Device wraps an I2C connection to a DS1307 device.
type Device struct {
bus machine.I2C
Address uint8
AddressSRAM uint8
}
// New creates a new DS1307 connection. I2C bus must be already configured.
func New(bus machine.I2C) Device {
return Device{bus: bus,
Address: uint8(I2CAddress),
AddressSRAM: SRAMBeginAddres,
}
}
// SetTime sets the time and date
func (d *Device) SetTime(t time.Time) error {
data := make([]byte, 8)
data[0] = uint8(TimeDate)
data[1] = decToBcd(t.Second())
data[2] = decToBcd(t.Minute())
data[3] = decToBcd(t.Hour())
data[4] = decToBcd(int(t.Weekday() + 1))
data[5] = decToBcd(t.Day())
data[6] = decToBcd(int(t.Month()))
data[7] = decToBcd(t.Year() - 2000)
err := d.bus.Tx(uint16(d.Address), data, nil)
return err
}
// Time returns the time and date
func (d *Device) Time() (time.Time, error) {
data := make([]byte, 8)
err := d.bus.ReadRegister(d.Address, uint8(TimeDate), data)
if err != nil {
return time.Time{}, err
}
seconds := bcdToDec(data[0] & 0x7F)
minute := bcdToDec(data[1])
hour := hoursBCDToInt(data[2])
day := bcdToDec(data[4])
month := time.Month(bcdToDec(data[5]))
year := bcdToDec(data[6])
year += 2000
t := time.Date(year, month, day, hour, minute, seconds, 0, time.UTC)
return t, nil
}
// Seek sets the offset for the next Read or Write on SRAM to offset, interpreted
// according to whence: 0 means relative to the origin of the SRAM, 1 means
// relative to the current offset, and 2 means relative to the end.
// returns new offset and error, if any
func (d *Device) Seek(offset int64, whence int) (int64, error) {
switch whence {
case 0:
whence = SRAMBeginAddres
case 1:
whence = int(d.AddressSRAM)
case 2:
whence = SRAMEndAddress
default:
return 0, errors.New("invalid starting point")
}
d.AddressSRAM = uint8(whence) + uint8(offset)
if d.AddressSRAM > SRAMEndAddress {
return 0, errors.New("EOF")
}
return int64(d.AddressSRAM), nil
}
// Write writes len(data) bytes to SRAM
// returns number of bytes written and error, if any
func (d *Device) Write(data []byte) (n int, err error) {
if int(d.AddressSRAM)+len(data)-1 > SRAMEndAddress {
return 0, errors.New("writing outside of SRAM")
}
buffer := make([]byte, len(data)+1)
buffer[0] = d.AddressSRAM
copy(buffer[1:], data)
err = d.bus.Tx(uint16(d.Address), buffer, nil)
if err != nil {
return 0, err
}
d.Seek(int64(len(data)), 1)
return len(data), nil
}
// Read reads len(data) from SRAM
// returns number of bytes written and error, if any
func (d *Device) Read(data []uint8) (n int, err error) {
if int(d.AddressSRAM)+len(data)-1 > SRAMEndAddress {
return 0, errors.New("EOF")
}
err = d.bus.ReadRegister(d.Address, d.AddressSRAM, data)
if err != nil {
return 0, err
}
d.Seek(int64(len(data)), 1)
return len(data), nil
}
// SetOscillatorFrequency sets output oscillator frequency
// Available modes: SQW_OFF, SQW_1HZ, SQW_4KHZ, SQW_8KHZ, SQW_32KHZ
func (d *Device) SetOscillatorFrequency(sqw uint8) error {
data := []byte{uint8(Control), sqw}
err := d.bus.Tx(uint16(d.Address), data, nil)
return err
}
// IsOscillatorRunning returns if the oscillator is running
func (d *Device) IsOscillatorRunning() bool {
data := []byte{0}
err := d.bus.ReadRegister(d.Address, uint8(TimeDate), data)
if err != nil {
return false
}
return (data[0] & (1 << CH)) == 0
}
// SetOscillatorRunning starts/stops internal oscillator by toggling halt bit
func (d *Device) SetOscillatorRunning(running bool) error {
data := make([]byte, 3)
err := d.bus.ReadRegister(d.Address, uint8(TimeDate), data)
if err != nil {
return err
}
if running {
data[0] &^= (1 << CH)
} else {
data[0] |= (1 << CH)
}
data[1], data[0] = data[0], uint8(TimeDate)
err = d.bus.Tx(uint16(d.Address), data[:2], nil)
return err
}
// decToBcd converts int to BCD
func decToBcd(dec int) uint8 {
return uint8(dec + 6*(dec/10))
}
// bcdToDec converts BCD to int
func bcdToDec(bcd uint8) int {
return int(bcd - 6*(bcd>>4))
}
// hoursBCDToInt converts the BCD hours to int
func hoursBCDToInt(value uint8) (hour int) {
if value&0x40 != 0x00 {
hour = bcdToDec(value & 0x1F)
if (value & 0x20) != 0x00 {
hour += 12
}
} else {
hour = bcdToDec(value)
}
return
}
+19
View File
@@ -0,0 +1,19 @@
package ds1307
const (
I2CAddress = 0x68
TimeDate = 0x00
Control = 0x7
//CH is oscillator halt bit
CH = 0x7
SRAMBeginAddres = 0x8
SRAMEndAddress = 0x3F
)
const (
SQW_OFF = 0x0
SQW_1HZ = 0x10
SQW_4KHZ = 0x11
SQW_8KHZ = 0x12
SQW_32KHZ = 0x13
)
+166
View File
@@ -0,0 +1,166 @@
// Package ds3231 provides a driver for the DS3231 RTC
//
// Datasheet:
// https://datasheets.maximintegrated.com/en/ds/DS3231.pdf
package ds3231 // import "tinygo.org/x/drivers/ds3231"
import (
"machine"
"time"
)
type Mode uint8
// Device wraps an I2C connection to a DS3231 device.
type Device struct {
bus machine.I2C
Address uint16
}
// New creates a new DS3231 connection. The I2C bus must already be
// configured.
//
// This function only creates the Device object, it does not touch the device.
func New(bus machine.I2C) Device {
return Device{
bus: bus,
Address: Address,
}
}
// Configure sets up the device for communication
func (d *Device) Configure() bool {
return true
}
// IsTimeValid return true/false is the time in the device is valid
func (d *Device) IsTimeValid() bool {
data := []byte{0}
err := d.bus.ReadRegister(uint8(d.Address), REG_STATUS, data)
if err != nil {
return false
}
return (data[0] & (1 << OSF)) == 0x00
}
// IsRunning returns if the oscillator is running
func (d *Device) IsRunning() bool {
data := []uint8{0}
err := d.bus.ReadRegister(uint8(d.Address), REG_CONTROL, data)
if err != nil {
return false
}
return (data[0] & (1 << EOSC)) == 0x00
}
// SetRunning starts the internal oscillator
func (d *Device) SetRunning(isRunning bool) error {
data := []uint8{0}
err := d.bus.ReadRegister(uint8(d.Address), REG_CONTROL, data)
if err != nil {
return err
}
if isRunning {
data[0] &^= uint8(1 << EOSC)
} else {
data[0] |= 1 << EOSC
}
err = d.bus.WriteRegister(uint8(d.Address), REG_CONTROL, data)
if err != nil {
return err
}
return nil
}
// SetTime sets the date and time in the DS3231
func (d *Device) SetTime(dt time.Time) error {
data := []byte{0}
err := d.bus.ReadRegister(uint8(d.Address), REG_STATUS, data)
if err != nil {
return err
}
data[0] &^= 1 << OSF
err = d.bus.WriteRegister(uint8(d.Address), REG_STATUS, data)
if err != nil {
return err
}
data = make([]uint8, 7)
data[0] = uint8ToBCD(uint8(dt.Second()))
data[1] = uint8ToBCD(uint8(dt.Minute()))
data[2] = uint8ToBCD(uint8(dt.Hour()))
year := uint8(dt.Year() - 2000)
centuryFlag := uint8(0)
if year >= 100 {
year -= 100
centuryFlag = 1 << 7
}
data[3] = uint8ToBCD(uint8(dt.Weekday()))
data[4] = uint8ToBCD(uint8(dt.Day()))
data[5] = uint8ToBCD(uint8(dt.Month()) | centuryFlag)
data[6] = uint8ToBCD(year)
err = d.bus.WriteRegister(uint8(d.Address), REG_TIMEDATE, data)
if err != nil {
return err
}
return nil
}
// ReadTime returns the date and time
func (d *Device) ReadTime() (dt time.Time, err error) {
data := make([]uint8, 7)
err = d.bus.ReadRegister(uint8(d.Address), REG_TIMEDATE, data)
if err != nil {
return
}
second := bcdToInt(data[0] & 0x7F)
minute := bcdToInt(data[1])
hour := hoursBCDToInt(data[2])
day := bcdToInt(data[4])
monthRaw := data[5]
year := bcdToInt(data[6]) + 2000
if monthRaw&(1<<7) != 0x00 {
year += 100
}
month := time.Month(bcdToInt(monthRaw & 0x7F))
dt = time.Date(year, month, day, hour, minute, second, 0, time.UTC)
return
}
// ReadTemperature returns the temperature in millicelsius (mC)
func (d *Device) ReadTemperature() (int32, error) {
data := make([]uint8, 2)
err := d.bus.ReadRegister(uint8(d.Address), REG_TEMP, data)
if err != nil {
return 0, err
}
return int32(data[0])*1000 + int32((data[1]>>6)*25)*10, nil
}
// uint8ToBCD converts a byte to BCD for the DS3231
func uint8ToBCD(value uint8) uint8 {
return value + 6*(value/10)
}
// bcdToInt converts BCD from the DS3231 to int
func bcdToInt(value uint8) int {
return int(value - 6*(value>>4))
}
// hoursBCDToInt converts the BCD hours to int
func hoursBCDToInt(value uint8) (hour int) {
if value&0x40 != 0x00 {
hour = bcdToInt(value & 0x1F)
if (value & 0x20) != 0x00 {
hour += 12
}
} else {
hour = bcdToInt(value)
}
return
}
+48
View File
@@ -0,0 +1,48 @@
package ds3231
// The I2C address which this device listens to.
const Address = 0x68
// Registers
const (
REG_TIMEDATE = 0x00
REG_ALARMONE = 0x07
REG_ALARMTWO = 0x0B
REG_CONTROL = 0x0E
REG_STATUS = 0x0F
REG_AGING = 0x10
REG_TEMP = 0x11
REG_ALARMONE_SIZE = 4
REG_ALARMTWO_SIZE = 3
// DS3231 Control Register Bits
A1IE = 0
A2IE = 1
INTCN = 2
RS1 = 3
RS2 = 4
CONV = 5
BBSQW = 6
EOSC = 7
// DS3231 Status Register Bits
A1F = 0
A2F = 1
BSY = 2
EN32KHZ = 3
OSF = 7
AlarmFlag_Alarm1 = 0x01
AlarmFlag_Alarm2 = 0x02
AlarmFlag_AlarmBoth = 0x03
None Mode = 0
BatteryBackup Mode = 1
Clock Mode = 2
AlarmOne Mode = 3
AlarmTwo Mode = 4
ModeAlarmBoth Mode = 5
)
+162
View File
@@ -0,0 +1,162 @@
// Package easystepper provides a simple driver to rotate a 4-wire stepper motor.
package easystepper // import "tinygo.org/x/drivers/easystepper"
import (
"machine"
"time"
)
// Device holds the pins and the delay between steps
type Device struct {
pins [4]machine.Pin
stepDelay int32
stepNumber uint8
}
// DualDevice holds information for controlling 2 motors
type DualDevice struct {
devices [2]Device
}
// New returns a new easystepper driver given 4 pins numbers (not pin object),
// number of steps and rpm
func New(pin1, pin2, pin3, pin4 machine.Pin, steps int32, rpm int32) Device {
return Device{
pins: [4]machine.Pin{pin1, pin2, pin3, pin4},
stepDelay: 60000000 / (steps * rpm),
}
}
// Configure configures the pins of the Device
func (d *Device) Configure() {
for _, pin := range d.pins {
pin.Configure(machine.PinConfig{Mode: machine.PinOutput})
}
}
// NewDual returns a new dual easystepper driver given 8 pins numbers (not pin object),
// number of steps and rpm
func NewDual(pin1, pin2, pin3, pin4, pin5, pin6, pin7, pin8 machine.Pin, steps int32, rpm int32) DualDevice {
var dual DualDevice
dual.devices[0] = Device{
pins: [4]machine.Pin{pin1, pin2, pin3, pin4},
stepDelay: 60000000 / (steps * rpm),
}
dual.devices[1] = Device{
pins: [4]machine.Pin{pin5, pin6, pin7, pin8},
stepDelay: 60000000 / (steps * rpm),
}
return dual
}
// Configure configures the pins of the DualDevice
func (d *DualDevice) Configure() {
d.devices[0].Configure()
d.devices[1].Configure()
}
// Move rotates the motor the number of given steps
// (negative steps will rotate it the opposite direction)
func (d *Device) Move(steps int32) {
direction := steps > 0
if steps < 0 {
steps = -steps
}
steps += int32(d.stepNumber)
var s int32
d.stepMotor(d.stepNumber)
for s = int32(d.stepNumber); s < steps; s++ {
time.Sleep(time.Duration(d.stepDelay) * time.Microsecond)
d.moveDirectionSteps(direction, s)
}
}
// Off turns off all motor pins
func (d *Device) Off() {
for _, pin := range d.pins {
pin.Low()
}
}
// Move rotates the motors the number of given steps
// (negative steps will rotate it the opposite direction)
func (d *DualDevice) Move(stepsA, stepsB int32) {
min := uint8(1)
max := uint8(0)
var directions [2]bool
var minStep int32
directions[0] = stepsA > 0
directions[1] = stepsB > 0
if stepsA < 0 {
stepsA = -stepsA
}
if stepsB < 0 {
stepsB = -stepsB
}
if stepsB > stepsA {
stepsA, stepsB = stepsB, stepsA
max, min = min, max
}
d.devices[0].stepMotor(d.devices[0].stepNumber)
d.devices[1].stepMotor(d.devices[1].stepNumber)
stepsA += int32(d.devices[max].stepNumber)
minStep = int32(d.devices[min].stepNumber)
for s := int32(d.devices[max].stepNumber); s < stepsA; s++ {
time.Sleep(time.Duration(d.devices[0].stepDelay) * time.Microsecond)
d.devices[max].moveDirectionSteps(directions[max], s)
if ((s * stepsB) / stepsA) > minStep {
minStep++
d.devices[min].moveDirectionSteps(directions[min], minStep)
}
}
}
// Off turns off all motor pins
func (d *DualDevice) Off() {
d.devices[0].Off()
d.devices[1].Off()
}
// stepMotor changes the pins' state to the correct step
func (d *Device) stepMotor(step uint8) {
switch step {
case 0:
d.pins[0].High()
d.pins[1].Low()
d.pins[2].High()
d.pins[3].Low()
break
case 1:
d.pins[0].Low()
d.pins[1].High()
d.pins[2].High()
d.pins[3].Low()
break
case 2:
d.pins[0].Low()
d.pins[1].High()
d.pins[2].Low()
d.pins[3].High()
break
case 3:
d.pins[0].High()
d.pins[1].Low()
d.pins[2].Low()
d.pins[3].High()
break
}
d.stepNumber = step
}
// moveDirectionSteps uses the direction to calculate the correct step and change the motor to it.
// Direction true: 0, 1, 2, 3, 0, 1, 2, ...
// Direction false: 0, 3, 2, 1, 0, 3, 2, ...
func (d *Device) moveDirectionSteps(direction bool, step int32) {
if direction {
d.stepMotor(uint8(step % 4))
} else {
d.stepMotor(uint8((step + 2*(step%2)) % 4))
}
}
+84
View File
@@ -0,0 +1,84 @@
# ESP-AT Driver
This package provides a driver to use a separate connected WiFi processor either the ESP8266 or the ESP32 from Espressif.
The way this driver works is by using the UART interface to communicate with the WiFi chip using the Espressif AT command set.
## ESP-AT Firmware Installation
In order to use this driver, you must have the ESP-AT firmware installed on the ESP8266/ESP32 chip.
### Installing on Arduino Nano33 IoT
In order to install the needed firmware on the Arduino Nano33 IoT board's built-in NINA W102 chip, you will need to use the `arduino-nano33-iot` branch of this fork of the firmware:
https://github.com/hybridgroup/esp32-at
To flash this firmware on the Arduino Nano33 IoT you will need to follow the following procedure:
- Install _Arduino SAMD Boards_ from the Boards Manager.
- Install _WiFiNANO_ from the Library Manager.
- Using the normal Arduino software, load the `SerialNINAPassthrough` sketch on to the board (in File -> Examples -> WiFiNINA-> Tools).
- Flash the NINA 102 firmware using the `make flash` command in the https://github.com/hybridgroup/esp32-at repo.
You only need to do this one time, and then the correct ESP-AT firmware will be on the NINA chip, and you can just flash the Arduino Nano33 IoT board using TinyGo. We should be able to remove some of these step in a future release of this software.
### Installing on ESP32
The official repository for the ESP-AT for the ESP32 processor is located here:
https://github.com/espressif/esp32-at
Your best option is to follow the instructions in the official repo.
### Installing on ESP8266
The official repository for the AT command set firmware for the ESP8266 processor is located here:
https://github.com/espressif/ESP8266_NONOS_SDK
First clone the repo:
```shell
git clone https://github.com/espressif/ESP8266_NONOS_SDK.git
```
You will also need to install the Espressif `esptool` to flash this firmware on your ESP8266:
https://github.com/espressif/esptool
Once you have obtained the binary code, and installed `esptool`, you can flash the ESP8266.
Here is an example shell script that flashes a Wemos D1 Mini board:
```python
#!/bin/sh
SPToolDir="$HOME/.local/lib/python2.7/site-packages"
FirmwareDir="$HOME/Development/ESP8266_NONOS_SDK"
cd "$SPToolDir"
port=/dev/ttyUSB0
if [ ! -c $port ]; then
port=/dev/ttyUSB0
fi
if [ ! -c $port ]; then
echo "No device appears to be plugged in. Stopping."
fi
printf "Writing AT firmware to the Wemos D1 Mini in 3..."
sleep 1; printf "2..."
sleep 1; printf "1..."
sleep 1; echo "done."
echo "Erasing the flash first"
esptool.py --port $port erase_flash
esptool.py --port /dev/ttyUSB0 --baud 115200 \
write_flash -fm dio -ff 20m -fs detect \
0x0000 "$FirmwareDir/bin/boot_v1.7.bin" \
0x01000 "$FirmwareDir/bin/at/512+512/user1.1024.new.2.bin" \
0x3fc000 "$FirmwareDir/bin/esp_init_data_default_v05.bin" \
0x7e000 "$FirmwareDir/bin/blank.bin" \
0x3fe000 "$FirmwareDir/bin/blank.bin"
echo "Check the boot by typing: miniterm $port 74800"
echo " and then resetting. Use Ctrl-] to quit miniterm."
```
+111
View File
@@ -0,0 +1,111 @@
package espat
// Basic AT commands
const (
// Test that the device is working.
Test = ""
// Restart module
Restart = "+RST"
// Version show info about the current software version.
Version = "+GMR"
// Enter deep-sleep mode
Sleep = "+GSLP"
// Configure echo.
EchoConfig = "E"
// EchoConfigOn
EchoConfigOn = EchoConfig + "1"
// EchoConfigOff
EchoConfigOff = EchoConfig + "0"
// Configure UART
UARTConfig = "+UART"
)
// WiFi commands.
const (
// WiFi mode (sta/AP/sta+AP)
WifiMode = "+CWMODE"
// Connect to an access point.
ConnectAP = "+CWJAP"
// List available AP's
ListAP = "+CWLAP"
// Disconnect from the current AP
Disconnect = "+CWQAP"
// Set softAP configuration. This also activates the ESP8266/ESP32 to act as an access point.
// On the ESP8266 the settings will not be saved in flash memory, so they will be forgotten on next reset.
// On the ESP32 the settings WILL be saved in flash memory, so they will be used on next reset.
SoftAPConfigCurrent = "+CWSAP"
// Set softAP configuration. This also activates the ESP8266/ESP32 to act as an access point.
// On the ESP8266 the settings will not be saved in flash memory, so they will be forgotten on next reset.
// On the ESP32 the settings WILL be saved in flash memory, so they will be used on next reset.
SoftAPConfigFlash = "+CWSAP"
// List station IP's connected to softAP
ListConnectedIP = "+CWLIF"
// Enable/disable DHCP
DHCPConfig = "+CWDHCP"
// Set MAC address of station
SetStationMACAddress = "+CIPSTAMAC"
// Set MAC address of softAP
SetAPMACAddress = "+CIPAPMAC"
// Set IP address of ESP8266/ESP32 station
SetStationIP = "+CIPSTA"
// Set IP address of ESP8266/ESP32 when acting as access point.
// On the ESP8266 the IP address will not be saved in flash memory, so it will be forgotten on next reset.
// On the ESP32 the IP address WILL be saved in flash memory, so it will be used on next reset.
SetSoftAPIPCurrent = "+CIPAP"
// Set IP address of ESP8266/ESP32 when acting as access point.
// On the ESP8266 the IP address will not be saved in flash memory, so it will be forgotten on next reset.
// On the ESP32 the IP address WILL be saved in flash memory, so it will be used on next reset.
SetSoftAPIPFlash = "+CIPAP"
)
// TCP/IP commands
const (
// Get connection status
TCPStatus = "+CIPSTATUS"
// Establish TCP connection or register UDP port
TCPConnect = "+CIPSTART"
// DNS Lookup
TCPDNSLookup = "+CIPDOMAIN"
// Send Data
TCPSend = "+CIPSEND"
// Close TCP/UDP connection
TCPClose = "+CIPCLOSE"
// Get local IP address
GetLocalIP = "+CIFSR"
// Set multiple connections mode
TCPMultiple = "+CIPMUX"
// Configure as server
ServerConfig = "+CIPSERVER"
// Set transmission mode
TransmissionMode = "+CIPMODE"
// Set timeout when ESP8266/ESP32 runs as TCP server
SetServerTimeout = "+CIPSTO"
)
+222
View File
@@ -0,0 +1,222 @@
// Package espat implements TCP/UDP wireless communication over serial
// with a separate ESP8266 or ESP32 board using the Espressif AT command set
// across a UART interface.
//
// In order to use this driver, the ESP8266/ESP32 must be flashed with firmware
// supporting the AT command set. Many ESP8266/ESP32 chips already have this firmware
// installed by default. You will need to install this firmware if you have an
// ESP8266 that has been flashed with NodeMCU (Lua) or Arduino firmware.
//
// AT Command Core repository:
// https://github.com/espressif/esp32-at
//
// Datasheet:
// https://www.espressif.com/sites/default/files/documentation/0a-esp8266ex_datasheet_en.pdf
//
// AT command set:
// https://www.espressif.com/sites/default/files/documentation/4a-esp8266_at_instruction_set_en.pdf
//
package espat // import "tinygo.org/x/drivers/espat"
import (
"errors"
"machine"
"strconv"
"strings"
"time"
"tinygo.org/x/drivers/net"
)
// Device wraps UART connection to the ESP8266/ESP32.
type Device struct {
bus machine.UART
// command responses that come back from the ESP8266/ESP32
response []byte
// data received from a TCP/UDP connection forwarded by the ESP8266/ESP32
socketdata []byte
}
// ActiveDevice is the currently configured Device in use. There can only be one.
var ActiveDevice *Device
// New returns a new espat driver. Pass in a fully configured UART bus.
func New(b machine.UART) *Device {
return &Device{bus: b, response: make([]byte, 512), socketdata: make([]byte, 0, 1024)}
}
// Configure sets up the device for communication.
func (d Device) Configure() {
ActiveDevice = &d
net.ActiveDevice = ActiveDevice
}
// Connected checks if there is communication with the ESP8266/ESP32.
func (d *Device) Connected() bool {
d.Execute(Test)
// handle response here, should include "OK"
_, err := d.Response(100)
if err != nil {
return false
}
return true
}
// Write raw bytes to the UART.
func (d *Device) Write(b []byte) (n int, err error) {
return d.bus.Write(b)
}
// Read raw bytes from the UART.
func (d *Device) Read(b []byte) (n int, err error) {
return d.bus.Read(b)
}
// how long in milliseconds to pause after sending AT commands
const pause = 300
// Execute sends an AT command to the ESP8266/ESP32.
func (d Device) Execute(cmd string) error {
_, err := d.Write([]byte("AT" + cmd + "\r\n"))
return err
}
// Query sends an AT command to the ESP8266/ESP32 that returns the
// current value for some configuration parameter.
func (d Device) Query(cmd string) (string, error) {
_, err := d.Write([]byte("AT" + cmd + "?\r\n"))
return "", err
}
// Set sends an AT command with params to the ESP8266/ESP32 for a
// configuration value to be set.
func (d Device) Set(cmd, params string) error {
_, err := d.Write([]byte("AT" + cmd + "=" + params + "\r\n"))
return err
}
// Version returns the ESP8266/ESP32 firmware version info.
func (d Device) Version() []byte {
d.Execute(Version)
r, err := d.Response(100)
if err != nil {
return []byte("unknown")
}
return r
}
// Echo sets the ESP8266/ESP32 echo setting.
func (d Device) Echo(set bool) {
if set {
d.Execute(EchoConfigOn)
} else {
d.Execute(EchoConfigOff)
}
// TODO: check for success
d.Response(100)
}
// Reset restarts the ESP8266/ESP32 firmware. Due to how the baud rate changes,
// this messes up communication with the ESP8266/ESP32 module. So make sure you know
// what you are doing when you call this.
func (d Device) Reset() {
d.Execute(Restart)
d.Response(100)
}
// ReadSocket returns the data that has already been read in from the responses.
func (d *Device) ReadSocket(b []byte) (n int, err error) {
// make sure no data in buffer
d.Response(300)
count := len(b)
if len(b) >= len(d.socketdata) {
// copy it all, then clear socket data
count = len(d.socketdata)
copy(b, d.socketdata[:count])
d.socketdata = d.socketdata[:0]
} else {
// copy all we can, then keep the remaining socket data around
copy(b, d.socketdata[:count])
copy(d.socketdata, d.socketdata[count:])
d.socketdata = d.socketdata[:len(d.socketdata)-count]
}
return count, nil
}
// Response gets the next response bytes from the ESP8266/ESP32.
// The call will retry for up to timeout milliseconds before returning nothing.
func (d *Device) Response(timeout int) ([]byte, error) {
// read data
var size int
var start, end int
pause := 100 // pause to wait for 100 ms
retries := timeout / pause
for {
size = d.bus.Buffered()
if size > 0 {
end += size
d.bus.Read(d.response[start:end])
// if "+IPD" then read socket data
if strings.Contains(string(d.response[:end]), "+IPD") {
// handle socket data
return nil, d.parseIPD(end)
}
// if "OK" then the command worked
if strings.Contains(string(d.response[:end]), "OK") {
return d.response[start:end], nil
}
// if "Error" then the command failed
if strings.Contains(string(d.response[:end]), "ERROR") {
return d.response[start:end], errors.New("response error:" + string(d.response[start:end]))
}
// if anything else, then keep reading data in?
start = end
}
// wait longer?
retries--
if retries == 0 {
return nil, errors.New("response timeout error:" + string(d.response[start:end]))
}
time.Sleep(time.Duration(pause) * time.Millisecond)
}
}
func (d *Device) parseIPD(end int) error {
// find the "+IPD," to get length
s := strings.Index(string(d.response[:end]), "+IPD,")
// find the ":"
e := strings.Index(string(d.response[:end]), ":")
// find the data length
val := string(d.response[s+5 : e])
// TODO: verify count
_, err := strconv.Atoi(val)
if err != nil {
// not expected data here. what to do?
return err
}
// load up the socket data
d.socketdata = append(d.socketdata, d.response[e+1:end]...)
return nil
}
// IsSocketDataAvailable returns of there is socket data available
func (d *Device) IsSocketDataAvailable() bool {
return len(d.socketdata) > 0 || d.bus.Buffered() > 0
}
+147
View File
@@ -0,0 +1,147 @@
package espat
import (
"errors"
"strconv"
"strings"
)
const (
TCPMuxSingle = 0
TCPMuxMultiple = 1
TCPTransferModeNormal = 0
TCPTransferModeUnvarnished = 1
)
// GetDNS returns the IP address for a domain name.
func (d *Device) GetDNS(domain string) (string, error) {
d.Set(TCPDNSLookup, "\""+domain+"\"")
resp, err := d.Response(1000)
if err != nil {
return "", err
}
if !strings.Contains(string(resp), ":") {
return "", errors.New("GetDNS error:" + string(resp))
}
r := strings.Split(string(resp), ":")
if len(r) != 2 {
return "", errors.New("Invalid domain lookup result")
}
res := strings.Split(r[1], "\r\n")
return res[0], nil
}
// ConnectTCPSocket creates a new TCP socket connection for the ESP8266/ESP32.
// Currently only supports single connection mode.
func (d *Device) ConnectTCPSocket(addr, port string) error {
protocol := "TCP"
val := "\"" + protocol + "\",\"" + addr + "\"," + port + ",120"
err := d.Set(TCPConnect, val)
if err != nil {
return err
}
_, e := d.Response(3000)
if e != nil {
return e
}
return nil
}
// ConnectUDPSocket creates a new UDP connection for the ESP8266/ESP32.
func (d *Device) ConnectUDPSocket(addr, sendport, listenport string) error {
protocol := "UDP"
val := "\"" + protocol + "\",\"" + addr + "\"," + sendport + "," + listenport + ",2"
err := d.Set(TCPConnect, val)
if err != nil {
return err
}
_, e := d.Response(3000)
if e != nil {
return e
}
return nil
}
// ConnectSSLSocket creates a new SSL socket connection for the ESP8266/ESP32.
// Currently only supports single connection mode.
func (d *Device) ConnectSSLSocket(addr, port string) error {
protocol := "SSL"
val := "\"" + protocol + "\",\"" + addr + "\"," + port + ",120"
d.Set(TCPConnect, val)
// this operation takes longer, so wait up to 6 seconds to complete.
_, err := d.Response(6000)
if err != nil {
return err
}
return nil
}
// DisconnectSocket disconnects the ESP8266/ESP32 from the current TCP/UDP connection.
func (d *Device) DisconnectSocket() error {
err := d.Execute(TCPClose)
if err != nil {
return err
}
_, e := d.Response(pause)
if e != nil {
return e
}
return nil
}
// SetMux sets the ESP8266/ESP32 current client TCP/UDP configuration for concurrent connections
// either single TCPMuxSingle or multiple TCPMuxMultiple (up to 4).
func (d *Device) SetMux(mode int) error {
val := strconv.Itoa(mode)
d.Set(TCPMultiple, val)
_, err := d.Response(pause)
return err
}
// GetMux returns the ESP8266/ESP32 current client TCP/UDP configuration for concurrent connections.
func (d *Device) GetMux() ([]byte, error) {
d.Query(TCPMultiple)
return d.Response(pause)
}
// SetTCPTransferMode sets the ESP8266/ESP32 current client TCP/UDP transfer mode.
// Either TCPTransferModeNormal or TCPTransferModeUnvarnished.
func (d *Device) SetTCPTransferMode(mode int) error {
val := strconv.Itoa(mode)
d.Set(TransmissionMode, val)
_, err := d.Response(pause)
return err
}
// GetTCPTransferMode returns the ESP8266/ESP32 current client TCP/UDP transfer mode.
func (d *Device) GetTCPTransferMode() ([]byte, error) {
d.Query(TransmissionMode)
return d.Response(pause)
}
// StartSocketSend gets the ESP8266/ESP32 ready to receive TCP/UDP socket data.
func (d *Device) StartSocketSend(size int) error {
val := strconv.Itoa(size)
d.Set(TCPSend, val)
// when ">" is received, it indicates
// ready to receive data
r, err := d.Response(2000)
if err != nil {
return err
}
if strings.Contains(string(r), ">") {
return nil
}
return errors.New("StartSocketSend error:" + string(r))
}
// EndSocketSend tell the ESP8266/ESP32 the TCP/UDP socket data sending is complete,
// and to return to command mode. This is only used in "unvarnished" raw mode.
func (d *Device) EndSocketSend() error {
d.Write([]byte("+++"))
_, err := d.Response(pause)
return err
}
+154
View File
@@ -0,0 +1,154 @@
package espat
import (
"strconv"
)
const (
WifiModeClient = 1
WifiModeAP = 2
WifiModeDual = 3
WifiAPSecurityOpen = 1
WifiAPSecurityWPA_PSK = 2
WifiAPSecurityWPA2_PSK = 3
WifiAPSecurityWPA_WPA2_PSK = 4
)
// GetWifiMode returns the ESP8266/ESP32 wifi mode.
func (d *Device) GetWifiMode() ([]byte, error) {
d.Query(WifiMode)
return d.Response(100)
}
// SetWifiMode sets the ESP8266/ESP32 wifi mode.
func (d *Device) SetWifiMode(mode int) error {
val := strconv.Itoa(mode)
d.Set(WifiMode, val)
_, err := d.Response(pause)
return err
}
// Wifi Client
// GetConnectedAP returns the ESP8266/ESP32 is currently connected to as a client.
func (d *Device) GetConnectedAP() ([]byte, error) {
d.Query(ConnectAP)
return d.Response(100)
}
// ConnectToAP connects the ESP8266/ESP32 to an access point.
// ws is the number of seconds to wait for connection.
func (d *Device) ConnectToAP(ssid, pwd string, ws int) error {
val := "\"" + ssid + "\",\"" + pwd + "\""
d.Set(ConnectAP, val)
_, err := d.Response(ws * 1000)
if err != nil {
return err
}
return nil
}
// DisconnectFromAP disconnects the ESP8266/ESP32 from the current access point.
func (d *Device) DisconnectFromAP() error {
d.Execute(Disconnect)
_, err := d.Response(1000)
return err
}
// GetClientIP returns the ESP8266/ESP32 current client IP addess when connected to an Access Point.
func (d *Device) GetClientIP() (string, error) {
d.Query(SetStationIP)
r, err := d.Response(1000)
return string(r), err
}
// SetClientIP sets the ESP8266/ESP32 current client IP addess when connected to an Access Point.
func (d *Device) SetClientIP(ipaddr string) error {
val := "\"" + ipaddr + "\""
d.Set(ConnectAP, val)
_, err := d.Response(500)
return err
}
// Access Point
// GetAPConfig returns the ESP8266/ESP32 current configuration when acting as an Access Point.
func (d *Device) GetAPConfig() (string, error) {
d.Query(SoftAPConfigCurrent)
r, err := d.Response(100)
return string(r), err
}
// SetAPConfig sets the ESP8266/ESP32 current configuration when acting as an Access Point.
// ch indicates which radiochannel to use. security should be one of the const values
// such as WifiAPSecurityOpen etc.
func (d *Device) SetAPConfig(ssid, pwd string, ch, security int) error {
chval := strconv.Itoa(ch)
ecnval := strconv.Itoa(security)
val := "\"" + ssid + "\",\"" + pwd + "\"," + chval + "," + ecnval
d.Set(SoftAPConfigCurrent, val)
_, err := d.Response(1000)
return err
}
// GetAPClients returns the ESP8266/ESP32 current clients when acting as an Access Point.
func (d *Device) GetAPClients() (string, error) {
d.Query(ListConnectedIP)
r, err := d.Response(100)
return string(r), err
}
// GetAPIP returns the ESP8266/ESP32 current IP addess when configured as an Access Point.
func (d *Device) GetAPIP() (string, error) {
d.Query(SetSoftAPIPCurrent)
r, err := d.Response(100)
return string(r), err
}
// SetAPIP sets the ESP8266/ESP32 current IP addess when configured as an Access Point.
func (d *Device) SetAPIP(ipaddr string) error {
val := "\"" + ipaddr + "\""
d.Set(SetSoftAPIPCurrent, val)
_, err := d.Response(500)
return err
}
// GetAPConfigFlash returns the ESP8266/ESP32 current configuration acting as an Access Point
// from flash storage. These settings are those used after a reset.
func (d *Device) GetAPConfigFlash() (string, error) {
d.Query(SoftAPConfigFlash)
r, err := d.Response(100)
return string(r), err
}
// SetAPConfigFlash sets the ESP8266/ESP32 current configuration acting as an Access Point,
// and saves them to flash storage. These settings will be used after a reset.
// ch indicates which radiochannel to use. security should be one of the const values
// such as WifiAPSecurityOpen etc.
func (d *Device) SetAPConfigFlash(ssid, pwd string, ch, security int) error {
chval := strconv.Itoa(ch)
ecnval := strconv.Itoa(security)
val := "\"" + ssid + "\",\"" + pwd + "\"," + chval + "," + ecnval
d.Set(SoftAPConfigFlash, val)
_, err := d.Response(1000)
return err
}
// GetAPIPFlash returns the ESP8266/ESP32 IP address as saved to flash storage.
// This is the IP address that will be used after a reset.
func (d *Device) GetAPIPFlash() (string, error) {
d.Query(SetSoftAPIPFlash)
r, err := d.Response(100)
return string(r), err
}
// SetAPIPFlash sets the ESP8266/ESP32 current IP addess when configured as an Access Point.
// The IP will be saved to flash storage, and will be used after a reset.
func (d *Device) SetAPIPFlash(ipaddr string) error {
val := "\"" + ipaddr + "\""
d.Set(SetSoftAPIPFlash, val)
_, err := d.Response(500)
return err
}
+27
View File
@@ -0,0 +1,27 @@
package main
import (
"fmt"
"machine"
"time"
"tinygo.org/x/drivers/adt7410"
)
var (
i2c = &machine.I2C0
sensor = adt7410.New(i2c, 0)
)
func main() {
i2c.Configure(machine.I2CConfig{Frequency: machine.TWI_FREQ_400KHZ})
sensor.Configure()
for {
temp := sensor.ReadTempF()
fmt.Printf("temperature: %f\r\n", temp)
time.Sleep(time.Second)
}
}
+25
View File
@@ -0,0 +1,25 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/adxl345"
)
func main() {
machine.I2C0.Configure(machine.I2CConfig{})
sensor := adxl345.New(machine.I2C0)
sensor.Configure()
println("ADXL345 starts")
for {
x, y, z, _ := sensor.ReadAcceleration()
println("X:", x, "Y:", y, "Z:", z)
rx, ry, rz := sensor.ReadRawAcceleration()
println("X (raw):", rx, "Y (raw):", ry, "Z (raw):", rz)
time.Sleep(100 * time.Millisecond)
}
}
+84
View File
@@ -0,0 +1,84 @@
// This example demostrates how to control the "Dotstar" (APA102) LED included
// on the Adafruit Itsy Bitsy M0 board. It implements a "rainbow effect" based
// on the following example:
// https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/master/CircuitPython_Essentials/CircuitPython_Internal_RGB_LED_rainbow.py
package main
import (
"image/color"
"machine"
"time"
"tinygo.org/x/drivers/apa102"
)
var (
apa apa102.Device
led = machine.PWM{machine.LED}
leds = make([]color.RGBA, 1)
wheel = &Wheel{Brightness: 0x10}
)
func init() {
// APA102 on Itsy Bitsy is connected to pins that require a software-based
// SPI implementation.
apa = apa102.NewSoftwareSPI(machine.PA00, machine.PA01, 1)
// Configure the regular on-board LED for PWM fading
machine.InitPWM()
led.Configure()
}
func main() {
// We'll fade the on-board LED in a goroutine to show/ensure that the APA102
// works fine with the scheduler enabled. Comment this out to test this code
// with the scheduler disabled.
go func() {
for i, brightening := uint8(0), false; ; i++ {
if i == 0 {
brightening = !brightening
continue
}
var brightness uint16 = uint16(i) << 8
if !brightening {
brightness = 0xFFFF - brightness
}
led.Set(brightness)
time.Sleep(5 * time.Millisecond)
}
}()
// Use the "wheel" function from Adafruit's example to cycle the APA102
for {
leds[0] = wheel.Next()
apa.WriteColors(leds)
time.Sleep(25 * time.Millisecond)
}
}
// Wheel is a port of Adafruit's Circuit Python example referenced above.
type Wheel struct {
Brightness uint8
pos uint8
}
// Next increments the internal state of the color and returns the new RGBA
func (w *Wheel) Next() (c color.RGBA) {
pos := w.pos
if w.pos < 85 {
c = color.RGBA{R: 0xFF - pos*3, G: pos * 3, B: 0x0, A: w.Brightness}
} else if w.pos < 170 {
pos -= 85
c = color.RGBA{R: 0x0, G: 0xFF - pos*3, B: pos * 3, A: w.Brightness}
} else {
pos -= 170
c = color.RGBA{R: pos * 3, G: 0x0, B: 0xFF - pos*3, A: w.Brightness}
}
w.pos++
return
}
+35
View File
@@ -0,0 +1,35 @@
// Connects to an APA102 SPI RGB LED strip with 30 LEDS.
package main
import (
"image/color"
"machine"
"time"
"tinygo.org/x/drivers/apa102"
)
func main() {
machine.SPI0.Configure(machine.SPIConfig{
Frequency: 500000,
Mode: 0})
a := apa102.New(machine.SPI0)
leds := make([]color.RGBA, 30)
rg := false
for {
rg = !rg
for i := range leds {
rg = !rg
if rg {
leds[i] = color.RGBA{R: 0xff, G: 0x00, B: 0x00, A: 0x77}
} else {
leds[i] = color.RGBA{R: 0x00, G: 0xff, B: 0x00, A: 0x77}
}
}
a.WriteColors(leds)
time.Sleep(100 * time.Millisecond)
}
}
+122
View File
@@ -0,0 +1,122 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/at24cx"
)
func main() {
machine.I2C0.Configure(machine.I2CConfig{})
eeprom := at24cx.New(machine.I2C0)
eeprom.Configure(at24cx.Config{})
values := make([]uint8, 100)
for i := uint16(0); i < 100; i++ {
values[i] = uint8(65 + i%26)
}
_, err := eeprom.WriteAt(values, 0)
if err != nil {
println("There was an error in WriteAt:", err)
return
}
for i := uint16(0); i < 26; i++ {
err = eeprom.WriteByte(100+i, uint8(90-i))
if err != nil {
println("There was an error in WriteByte:", i, err)
return
}
time.Sleep(2 * time.Millisecond)
}
println("\n\r\n\rRead 26 bytes one by one from address 0")
println("Expected: ABCDEFGHIJKLMNOPQRSTUVWXYZ")
print("Real: ")
for i := uint16(0); i < 26; i++ {
char, err := eeprom.ReadByte(i)
print(string(char))
if err != nil {
println("There was an error in ReadByte:", i, err)
return
}
}
println("")
println("\n\r\n\rRead 100 bytes from address 26")
println("Expected: ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVZYXWVUTSRQPONMLKJIHGFEDCBA")
print("Real: ")
data := make([]byte, 100)
_, err = eeprom.ReadAt(data, 26)
if err != nil {
println("There was an error in ReadAt:", err)
return
}
for i := 0; i < 100; i++ {
print(string(data[i]))
}
println("")
// Move to the beginning of memory
eeprom.Seek(0, 0)
_, err = eeprom.Write([]uint8{88, 88, 88})
if err != nil {
println("There was an error in Write:", err)
return
}
println("\n\r\n\rRead 3 bytes")
println("Expected: DEF")
print("Real: ")
data = make([]byte, 3)
_, err = eeprom.Read(data)
if err != nil {
println("There was an error in Read:", err)
return
}
for _, char := range data {
print(string(char))
}
println("")
println("\n\r\n\rRead another 3 bytes (from the beginning this time)")
eeprom.Seek(-6, 1)
println("Expected: XXX")
print("Real: ")
data = make([]byte, 3)
_, err = eeprom.Read(data)
if err != nil {
println("There was an error in Read:", err)
return
}
for _, char := range data {
print(string(char))
}
println("")
// Move to the end of memory
eeprom.Seek(-4, 2)
_, err = eeprom.Write([]uint8{89, 90, 89, 90})
if err != nil {
println("There was an error in Write:", err)
return
}
println("\n\r\n\rRead the last 4 bytes of the memory and the 3 of the beginning")
eeprom.Seek(-4, 1)
println("Expected: YZYZXXX")
print("Real: ")
data = make([]byte, 7)
_, err = eeprom.Read(data)
if err != nil {
println("There was an error in Read:", err)
return
}
for _, char := range data {
print(string(char))
}
println("")
}
+22
View File
@@ -0,0 +1,22 @@
package main
import (
"time"
"machine"
"tinygo.org/x/drivers/bh1750"
)
func main() {
machine.I2C0.Configure(machine.I2CConfig{})
sensor := bh1750.New(machine.I2C0)
sensor.Configure()
for {
lux := sensor.Illuminance()
println("Illuminance:", lux, "lx")
time.Sleep(500 * time.Millisecond)
}
}
+41
View File
@@ -0,0 +1,41 @@
// Connects to an BlinkM I2C RGB LED.
// http://thingm.com/fileadmin/thingm/downloads/BlinkM_datasheet.pdf
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/blinkm"
)
func main() {
machine.I2C0.Configure(machine.I2CConfig{})
bm := blinkm.New(machine.I2C0)
bm.Configure()
maj, min, _ := bm.Version()
println("Firmware version:", string(maj), string(min))
count := 0
for {
switch count {
case 0:
// Crimson
bm.SetRGB(0xdc, 0x14, 0x3c)
count = 1
case 1:
// MediumPurple
bm.SetRGB(0x93, 0x70, 0xdb)
count = 2
case 2:
// MediumSeaGreen
bm.SetRGB(0x3c, 0xb3, 0x71)
count = 0
}
time.Sleep(100 * time.Millisecond)
}
}
+35
View File
@@ -0,0 +1,35 @@
package main
import (
"machine"
"strconv"
"time"
"tinygo.org/x/drivers/bme280"
)
func main() {
machine.I2C0.Configure(machine.I2CConfig{})
sensor := bme280.New(machine.I2C0)
sensor.Configure()
connected := sensor.Connected()
if !connected {
println("BME280 not detected")
}
println("BME280 detected")
for {
temp, _ := sensor.ReadTemperature()
println("Temperature:", strconv.FormatFloat(float64(temp)/1000, 'f', 2, 64), "°C")
press, _ := sensor.ReadPressure()
println("Pressure:", strconv.FormatFloat(float64(press)/100000, 'f', 2, 64), "hPa")
hum, _ := sensor.ReadHumidity()
println("Humidity:", strconv.FormatFloat(float64(hum)/100, 'f', 2, 64), "%")
alt, _ := sensor.ReadAltitude()
println("Altitude:", alt, "m")
time.Sleep(2 * time.Second)
}
}
+32
View File
@@ -0,0 +1,32 @@
package main
import (
"time"
"machine"
"tinygo.org/x/drivers/bmp180"
)
func main() {
machine.I2C0.Configure(machine.I2CConfig{})
sensor := bmp180.New(machine.I2C0)
sensor.Configure()
connected := sensor.Connected()
if !connected {
println("BMP180 not detected")
return
}
println("BMP180 detected")
for {
temp, _ := sensor.ReadTemperature()
println("Temperature:", float32(temp)/1000, "°C")
pressure, _ := sensor.ReadPressure()
println("Pressure", float32(pressure)/100000, "hPa")
time.Sleep(2 * time.Second)
}
}
+40
View File
@@ -0,0 +1,40 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/buzzer"
)
type note struct {
tone float64
duration float64
}
func main() {
speaker := machine.PA30
speaker.Configure(machine.PinConfig{Mode: machine.PinOutput})
speaker.Set(true)
bzrPin := machine.A0
bzrPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
bzr := buzzer.New(bzrPin)
song := []note{
{buzzer.C3, buzzer.Quarter},
{buzzer.D3, buzzer.Quarter},
{buzzer.E3, buzzer.Quarter},
{buzzer.F3, buzzer.Quarter},
{buzzer.G3, buzzer.Quarter},
{buzzer.A3, buzzer.Quarter},
{buzzer.B3, buzzer.Quarter},
{buzzer.C3, buzzer.Quarter},
}
for _, val := range song {
bzr.Tone(val.tone, val.duration)
time.Sleep(10 * time.Millisecond)
}
}
+32
View File
@@ -0,0 +1,32 @@
package main
import (
"machine"
"tinygo.org/x/drivers/ds1307"
)
func main() {
machine.I2C0.Configure(machine.I2CConfig{})
rtc := ds1307.New(machine.I2C0)
read := make([]byte, 5)
for {
rtc.Seek(0, 0)
_, err := rtc.Write([]byte{1, 2, 3, 4, 5})
if err != nil {
println("Error while writing data:", err)
break
}
rtc.Seek(0, 0)
_, err = rtc.Read(read)
if err != nil {
println("Error while reading data:", err)
break
}
for data := range read {
println(data, " ")
}
}
}
+25
View File
@@ -0,0 +1,25 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/ds1307"
)
func main() {
machine.I2C0.Configure(machine.I2CConfig{})
rtc := ds1307.New(machine.I2C0)
rtc.SetTime(time.Date(2019, 5, 15, 20, 34, 12, 0, time.UTC))
for {
t, err := rtc.Time()
if err != nil {
println("Error reading date:", err)
break
}
println(t.Hour(), ":", t.Minute(), ":", t.Second(), " ", t.Day(), "/", t.Month(), "/", t.Year())
}
}
+45
View File
@@ -0,0 +1,45 @@
// Connects to an MAG3110 I2C magnetometer.
package main
import (
"machine"
"time"
"fmt"
"tinygo.org/x/drivers/ds3231"
)
func main() {
machine.I2C0.Configure(machine.I2CConfig{})
rtc := ds3231.New(machine.I2C0)
rtc.Configure()
valid := rtc.IsTimeValid()
if !valid {
date := time.Date(2019, 12, 05, 20, 34, 12, 0, time.UTC)
rtc.SetTime(date)
}
running := rtc.IsRunning()
if !running {
err := rtc.SetRunning(true)
if err != nil {
fmt.Println("Error configuring RTC")
}
}
for {
dt, err := rtc.ReadTime()
if err != nil {
fmt.Println("Error reading date:", err)
} else {
fmt.Printf("Date: %d/%s/%02d %02d:%02d:%02d \r\n", dt.Year(), dt.Month(), dt.Day(), dt.Hour(), dt.Minute(), dt.Second())
}
temp, _ := rtc.ReadTemperature()
fmt.Printf("Temperature: %.2f °C \r\n", float32(temp)/1000)
time.Sleep(time.Second * 1)
}
}
+23
View File
@@ -0,0 +1,23 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/easystepper"
)
func main() {
motor := easystepper.New(machine.P13, machine.P15, machine.P14, machine.P16, 200, 75)
motor.Configure()
for {
println("CLOCKWISE")
motor.Move(2050)
time.Sleep(time.Millisecond * 1000)
println("COUNTERCLOCKWISE")
motor.Move(-2050)
time.Sleep(time.Millisecond * 1000)
}
}
+143
View File
@@ -0,0 +1,143 @@
// This is a console to a ESP8266/ESP32 running on the device UART1.
// Allows you to type AT commands from your computer via the microcontroller.
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266 <--> INTERNET
//
// More information on the Espressif AT command set at:
// https://www.espressif.com/sites/default/files/documentation/4a-esp8266_at_instruction_set_en.pdf
//
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/espat"
)
// change actAsAP to true to act as an access point instead of connecting to one.
const actAsAP = false
// access point info
const ssid = "YOURSSID"
const pass = "YOURPASS"
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
uart = machine.UART1
tx = machine.PA22
rx = machine.PA23
console = machine.UART0
adaptor *espat.Device
)
func main() {
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
// Init esp8266
adaptor = espat.New(uart)
adaptor.Configure()
// first check if connected
if connectToESP() {
println("Connected to wifi adaptor.")
adaptor.Echo(false)
connectToAP()
} else {
println("")
failMessage("Unable to connect to wifi adaptor.")
return
}
println("Type an AT command then press enter:")
prompt()
input := make([]byte, 64)
i := 0
for {
if console.Buffered() > 0 {
data, _ := console.ReadByte()
switch data {
case 13:
// return key
console.Write([]byte("\r\n"))
// send command to ESP8266
input[i] = byte('\r')
input[i+1] = byte('\n')
adaptor.Write(input[:i+2])
// display response
r, _ := adaptor.Response(500)
console.Write(r)
// prompt
prompt()
i = 0
continue
default:
// just echo the character
console.WriteByte(data)
input[i] = data
i++
}
}
time.Sleep(10 * time.Millisecond)
}
}
func prompt() {
print("ESPAT>")
}
// connect to ESP8266/ESP32
func connectToESP() bool {
for i := 0; i < 5; i++ {
println("Connecting to wifi adaptor...")
if adaptor.Connected() {
return true
}
time.Sleep(1 * time.Second)
}
return false
}
// connect to access point
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
adaptor.SetWifiMode(espat.WifiModeClient)
adaptor.ConnectToAP(ssid, pass, 10)
println("Connected.")
ip, err := adaptor.GetClientIP()
if err != nil {
failMessage(err.Error())
}
println(ip)
}
// provide access point
func provideAP() {
println("Starting wifi network as access point '" + ssid + "'...")
adaptor.SetWifiMode(espat.WifiModeAP)
adaptor.SetAPConfig(ssid, pass, 7, espat.WifiAPSecurityWPA2_PSK)
println("Ready.")
ip, _ := adaptor.GetAPIP()
println(ip)
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
+129
View File
@@ -0,0 +1,129 @@
// This is a sensor hub that uses a ESP8266/ESP32 running on the device UART1.
// It creates a UDP "server" you can use to get info to/from your computer via the microcontroller.
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266 <--> INTERNET
//
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/espat"
"tinygo.org/x/drivers/net"
)
// change actAsAP to true to act as an access point instead of connecting to one.
const actAsAP = false
// access point info
const ssid = "YOURSSID"
const pass = "YOURPASS"
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
uart = machine.UART1
tx = machine.PA22
rx = machine.PA23
adaptor *espat.Device
)
func main() {
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
// Init esp8266
adaptor = espat.New(uart)
adaptor.Configure()
readyled := machine.LED
readyled.Configure(machine.PinConfig{Mode: machine.PinOutput})
readyled.High()
// first check if connected
if connectToESP() {
println("Connected to wifi adaptor.")
adaptor.Echo(false)
connectToAP()
} else {
println("")
failMessage("Unable to connect to wifi adaptor.")
return
}
// now make UDP connection
laddr := &net.UDPAddr{Port: 2222}
println("Loading UDP listener...")
conn, _ := net.ListenUDP("UDP", laddr)
println("Waiting for data...")
data := make([]byte, 50)
blink := true
for {
n, _ := conn.Read(data)
if n > 0 {
println(string(data[:n]))
conn.Write([]byte("hello back\r\n"))
}
blink = !blink
if blink {
readyled.High()
} else {
readyled.Low()
}
time.Sleep(500 * time.Millisecond)
}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting UDP...")
conn.Close()
println("Done.")
}
// connect to ESP8266/ESP32
func connectToESP() bool {
for i := 0; i < 5; i++ {
println("Connecting to wifi adaptor...")
if adaptor.Connected() {
return true
}
time.Sleep(1 * time.Second)
}
return false
}
// connect to access point
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
adaptor.SetWifiMode(espat.WifiModeClient)
adaptor.ConnectToAP(ssid, pass, 10)
println("Connected.")
ip, err := adaptor.GetClientIP()
if err != nil {
failMessage(err.Error())
}
println(ip)
}
// provide access point
func provideAP() {
println("Starting wifi network as access point '" + ssid + "'...")
adaptor.SetWifiMode(espat.WifiModeAP)
adaptor.SetAPConfig(ssid, pass, 7, espat.WifiAPSecurityWPA2_PSK)
println("Ready.")
ip, _ := adaptor.GetAPIP()
println(ip)
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
+108
View File
@@ -0,0 +1,108 @@
// This is a sensor station that uses a ESP8266 or ESP32 running on the device UART1.
// It creates a UDP connection you can use to get info to/from your computer via the microcontroller.
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266
//
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/espat"
"tinygo.org/x/drivers/net"
)
// access point info
const ssid = "YOURSSID"
const pass = "YOURPASS"
// IP address of the listener aka "hub". Replace with your own info.
const hubIP = "0.0.0.0"
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
uart = machine.UART1
tx = machine.PA22
rx = machine.PA23
adaptor *espat.Device
)
func main() {
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
// Init esp8266/esp32
adaptor = espat.New(uart)
adaptor.Configure()
// first check if connected
if connectToESP() {
println("Connected to wifi adaptor.")
adaptor.Echo(false)
connectToAP()
} else {
println("")
failMessage("Unable to connect to wifi adaptor.")
return
}
// now make UDP connection
ip := net.ParseIP(hubIP)
raddr := &net.UDPAddr{IP: ip, Port: 2222}
laddr := &net.UDPAddr{Port: 2222}
println("Dialing UDP connection...")
conn, _ := net.DialUDP("udp", laddr, raddr)
for {
// send data
println("Sending data...")
conn.Write([]byte("hello\r\n"))
time.Sleep(1000 * time.Millisecond)
}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting UDP...")
conn.Close()
println("Done.")
}
// connect to ESP8266/ESP32
func connectToESP() bool {
for i := 0; i < 5; i++ {
println("Connecting to wifi adaptor...")
if adaptor.Connected() {
return true
}
time.Sleep(1 * time.Second)
}
return false
}
// connect to access point
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
adaptor.SetWifiMode(espat.WifiModeClient)
adaptor.ConnectToAP(ssid, pass, 10)
println("Connected.")
ip, err := adaptor.GetClientIP()
if err != nil {
failMessage(err.Error())
}
println(ip)
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
+142
View File
@@ -0,0 +1,142 @@
// This is a sensor station that uses a ESP8266 or ESP32 running on the device UART1.
// It creates an MQTT connection that publishes a message every second
// to an MQTT broker.
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266 <--> Internet <--> MQTT broker.
//
// You must install the Paho MQTT package to build this program:
//
// go get -u github.com/eclipse/paho.mqtt.golang
//
package main
import (
"machine"
"math/rand"
"time"
"tinygo.org/x/drivers/espat"
"tinygo.org/x/drivers/net/mqtt"
)
// access point info
const ssid = "YOURSSID"
const pass = "YOURPASS"
// IP address of the MQTT broker to use. Replace with your own info.
const server = "tcp://test.mosquitto.org:1883"
//const server = "ssl://test.mosquitto.org:8883"
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
uart = machine.UART2
tx = machine.PA22
rx = machine.PA23
console = machine.UART0
adaptor *espat.Device
topic = "tinygo"
)
func main() {
time.Sleep(3000 * time.Millisecond)
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
rand.Seed(time.Now().UnixNano())
// Init esp8266/esp32
adaptor = espat.New(uart)
adaptor.Configure()
// first check if connected
if connectToESP() {
println("Connected to wifi adaptor.")
adaptor.Echo(false)
connectToAP()
} else {
println("")
failMessage("Unable to connect to wifi adaptor.")
return
}
opts := mqtt.NewClientOptions()
opts.AddBroker(server).SetClientID("tinygo-client-" + randomString(10))
println("Connecting to MQTT broker at", server)
cl := mqtt.NewClient(opts)
if token := cl.Connect(); token.Wait() && token.Error() != nil {
failMessage(token.Error().Error())
}
for {
println("Publishing MQTT message...")
data := []byte("{\"e\":[{ \"n\":\"hello\", \"v\":101 }]}")
token := cl.Publish(topic, 0, false, data)
token.Wait()
if token.Error() != nil {
println(token.Error().Error())
}
time.Sleep(1000 * time.Millisecond)
}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting MQTT...")
cl.Disconnect(100)
println("Done.")
}
// connect to ESP8266/ESP32
func connectToESP() bool {
for i := 0; i < 5; i++ {
println("Connecting to wifi adaptor...")
if adaptor.Connected() {
return true
}
time.Sleep(1 * time.Second)
}
return false
}
// connect to access point
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
adaptor.SetWifiMode(espat.WifiModeClient)
adaptor.ConnectToAP(ssid, pass, 10)
println("Connected.")
ip, err := adaptor.GetClientIP()
if err != nil {
failMessage(err.Error())
}
println(ip)
}
// Returns an int >= min, < max
func randomInt(min, max int) int {
return min + rand.Intn(max-min)
}
// Generate a random string of A-Z chars with len = l
func randomString(len int) string {
bytes := make([]byte, len)
for i := 0; i < len; i++ {
bytes[i] = byte(randomInt(65, 90))
}
return string(bytes)
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
+163
View File
@@ -0,0 +1,163 @@
// This is a sensor station that uses a ESP8266 or ESP32 running on the device UART1.
// It creates an MQTT connection that publishes a message every second
// to an MQTT broker.
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266 <--> Internet <--> MQTT broker.
//
// You must also install the Paho MQTT package to build this program:
//
// go get -u github.com/eclipse/paho.mqtt.golang
//
package main
import (
"fmt"
"machine"
"math/rand"
"time"
"tinygo.org/x/drivers/espat"
"tinygo.org/x/drivers/net/mqtt"
)
// access point info
const ssid = "YOURSSID"
const pass = "YOURPASS"
// IP address of the MQTT broker to use. Replace with your own info.
//const server = "tcp://test.mosquitto.org:1883"
const server = "ssl://test.mosquitto.org:8883"
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
// these are defaults for the Arduino Nano33 IoT.
uart = machine.UART1
tx = machine.PA22
rx = machine.PA23
console = machine.UART0
adaptor *espat.Device
cl mqtt.Client
topicTx = "tinygo/tx"
topicRx = "tinygo/rx"
)
func subHandler(client mqtt.Client, msg mqtt.Message) {
fmt.Printf("[%s] ", msg.Topic())
fmt.Printf("%s\r\n", msg.Payload())
}
func main() {
time.Sleep(3000 * time.Millisecond)
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
rand.Seed(time.Now().UnixNano())
// Init esp8266/esp32
adaptor = espat.New(uart)
adaptor.Configure()
// first check if connected
if connectToESP() {
println("Connected to wifi adaptor.")
adaptor.Echo(false)
connectToAP()
} else {
println("")
failMessage("Unable to connect to wifi adaptor.")
return
}
opts := mqtt.NewClientOptions()
opts.AddBroker(server).SetClientID("tinygo-client-" + randomString(10))
println("Connecting to MQTT broker at", server)
cl = mqtt.NewClient(opts)
if token := cl.Connect(); token.Wait() && token.Error() != nil {
failMessage(token.Error().Error())
}
// subscribe
token := cl.Subscribe(topicRx, 0, subHandler)
token.Wait()
if token.Error() != nil {
failMessage(token.Error().Error())
}
go publishing()
select {}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting MQTT...")
cl.Disconnect(100)
println("Done.")
}
func publishing() {
for {
println("Publishing MQTT message...")
data := []byte("{\"e\":[{ \"n\":\"hello\", \"v\":101 }]}")
token := cl.Publish(topicTx, 0, false, data)
token.Wait()
if token.Error() != nil {
println(token.Error().Error())
}
time.Sleep(1000 * time.Millisecond)
}
}
// connect to ESP8266/ESP32
func connectToESP() bool {
for i := 0; i < 5; i++ {
println("Connecting to wifi adaptor...")
if adaptor.Connected() {
return true
}
time.Sleep(1 * time.Second)
}
return false
}
// connect to access point
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
adaptor.SetWifiMode(espat.WifiModeClient)
adaptor.ConnectToAP(ssid, pass, 10)
println("Connected.")
ip, err := adaptor.GetClientIP()
if err != nil {
failMessage(err.Error())
}
println(ip)
}
// Returns an int >= min, < max
func randomInt(min, max int) int {
return min + rand.Intn(max-min)
}
// Generate a random string of A-Z chars with len = l
func randomString(len int) string {
bytes := make([]byte, len)
for i := 0; i < len; i++ {
bytes[i] = byte(randomInt(65, 90))
}
return string(bytes)
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
+111
View File
@@ -0,0 +1,111 @@
// This is a sensor station that uses a ESP8266 or ESP32 running on the device UART1.
// It creates a UDP connection you can use to get info to/from your computer via the microcontroller.
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266
//
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/espat"
"tinygo.org/x/drivers/net"
)
// access point info
const ssid = "YOURSSID"
const pass = "YOURPASS"
// IP address of the server aka "hub". Replace with your own info.
const serverIP = "0.0.0.0"
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
uart = machine.UART1
tx = machine.PA22
rx = machine.PA23
adaptor *espat.Device
)
func main() {
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
// Init esp8266/esp32
adaptor = espat.New(uart)
adaptor.Configure()
// first check if connected
if connectToESP() {
println("Connected to wifi adaptor.")
adaptor.Echo(false)
connectToAP()
} else {
println("")
failMessage("Unable to connect to wifi adaptor.")
return
}
// now make TCP connection
ip := net.ParseIP(serverIP)
raddr := &net.TCPAddr{IP: ip, Port: 8080}
laddr := &net.TCPAddr{Port: 8080}
println("Dialing TCP connection...")
conn, err := net.DialTCP("tcp", laddr, raddr)
if err != nil {
failMessage(err.Error())
}
for {
// send data
println("Sending data...")
conn.Write([]byte("hello\r\n"))
time.Sleep(1000 * time.Millisecond)
}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting TCP...")
conn.Close()
println("Done.")
}
// connect to ESP8266/ESP32
func connectToESP() bool {
for i := 0; i < 5; i++ {
println("Connecting to wifi adaptor...")
if adaptor.Connected() {
return true
}
time.Sleep(1 * time.Second)
}
return false
}
// connect to access point
func connectToAP() {
println("Connecting to wifi network '" + ssid + "'")
adaptor.SetWifiMode(espat.WifiModeClient)
adaptor.ConnectToAP(ssid, pass, 10)
println("Connected.")
ip, err := adaptor.GetClientIP()
if err != nil {
failMessage(err.Error())
}
println(ip)
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
+29
View File
@@ -0,0 +1,29 @@
package main
import (
"fmt"
"machine"
"tinygo.org/x/drivers/gps"
)
func main() {
println("GPS I2C Example")
machine.I2C0.Configure(machine.I2CConfig{})
ublox := gps.NewI2C(&machine.I2C0)
parser := gps.Parser(ublox)
var fix gps.Fix
for {
fix = parser.NextFix()
if fix.Valid {
print(fix.Time.Format("15:04:05"))
print(", lat=", fmt.Sprintf("%f", fix.Latitude))
print(", long=", fmt.Sprintf("%f", fix.Longitude))
print(", altitude:=", fix.Altitude)
print(", satellites=", fix.Satellites)
println()
} else {
println("No fix")
}
}
}
+29
View File
@@ -0,0 +1,29 @@
package main
import (
"fmt"
"machine"
"tinygo.org/x/drivers/gps"
)
func main() {
println("GPS UART Example")
machine.UART1.Configure(machine.UARTConfig{BaudRate: 9600})
ublox := gps.NewUART(&machine.UART1)
parser := gps.Parser(ublox)
var fix gps.Fix
for {
fix = parser.NextFix()
if fix.Valid {
print(fix.Time.Format("15:04:05"))
print(", lat=", fmt.Sprintf("%f", fix.Latitude))
print(", long=", fmt.Sprintf("%f", fix.Longitude))
print(", altitude:=", fix.Altitude)
print(", satellites=", fix.Satellites)
println()
} else {
println("No fix")
}
}
}
+31
View File
@@ -0,0 +1,31 @@
package main
import (
"machine"
"tinygo.org/x/drivers/hd44780"
)
func main() {
lcd, _ := hd44780.NewGPIO4Bit(
[]machine.Pin{machine.P0, machine.P1, machine.P2, machine.P3},
machine.P4,
machine.P5,
machine.P6,
)
lcd.Configure(hd44780.Config{
Width: 16,
Height: 2,
CursorOnOff: true,
CursorBlink: true,
})
lcd.CreateCharacter(0x0, []byte{0x04, 0x0E, 0x0E, 0x0E, 0x0E, 0x1F, 0x04, 0x0})
lcd.Write([]byte{0x0})
lcd.Display()
for {
}
}
+31
View File
@@ -0,0 +1,31 @@
package main
import (
"machine"
"tinygo.org/x/drivers/hd44780"
)
func main() {
lcd, _ := hd44780.NewGPIO4Bit(
[]machine.Pin{machine.P0, machine.P1, machine.P2, machine.P3},
machine.P4,
machine.P5,
machine.P6,
)
lcd.Configure(hd44780.Config{
Width: 16,
Height: 2,
CursorOnOff: true,
CursorBlink: true,
})
lcd.Write([]byte("This is a long line"))
lcd.Display()
for {
}
}
+142
View File
@@ -0,0 +1,142 @@
package gopherimg
import "image/color"
var ImageArray = []uint32{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6015176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 0, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 0,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 0, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 0,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 16777215,
16777215, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176,
16777215, 16777215, 0, 0, 0, 0, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 6015176, 6015176, 6015176,
6015176, 16777215, 16777215, 16777215, 0, 0, 0, 0, 0, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 6015176,
6015176, 6015176, 16777215, 16777215, 16777215, 16777215, 0, 0, 0, 0, 0, 16777215, 16777215, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0,
0, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 16777215, 16777215, 0, 0, 0, 0, 0, 16777215, 16777215,
16777215, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 16777215, 16777215, 16777215, 0,
0, 0, 16777215, 16777215, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 16777215,
16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 16777215, 16777215, 16777215,
16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 6015176, 6015176, 6015176, 6015176,
6015176, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215,
16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 16777215,
16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215,
16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 8145949, 8145949, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 6015176, 6015176, 6015176,
8145949, 8145949, 8145949, 8145949, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215,
16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 8145949, 8145949, 8145949, 8145949, 8145949, 16777215,
16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 8145949, 8145949, 8145949, 8145949, 8145949, 15267831, 16645886, 16777215, 16777215, 6015176, 6015176,
6015176, 6015176, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 8145949, 8145949, 8145949, 8145949, 16777215,
16777215, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 0, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0,
8145949, 8145949, 8145949, 8145949, 6868429, 7786961, 7327695, 6015176, 6015176, 6015176, 6015176, 6015176, 0,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 8145949, 8145949, 8145949, 8145949, 16777215, 16777215,
16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 16777215, 16777215, 16777215, 16777215, 16777215, 6015176, 6015176, 6015176, 0, 0,
8145949, 8145949, 8145949, 8145949, 15530489, 16121084, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 0,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 0, 0, 0, 0, 16777215,
6015176, 6015176, 6015176, 8145949, 8145949, 8145949, 8145949, 8145949, 16777215, 16777215, 16777215, 6015176,
6015176, 6015176, 6015176, 6015176, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 16777215,
16777215, 0, 0, 0, 0, 0, 16777215, 16777215, 6015176, 6015176, 6015176, 8145949, 8145949, 8145949, 8145949,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 16777215, 16777215, 16777215, 0, 0, 0, 0, 0, 16777215, 16777215, 6015176, 6015176, 6015176,
6015176, 8145949, 8145949, 8145949, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 16777215, 0, 0, 0, 0, 0, 16777215,
16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 16777215,
16777215, 16777215, 16777215, 0, 0, 16777215, 16777215, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 6015176, 6015176,
6015176, 6015176, 6015176, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215,
16777215, 16777215, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215,
16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 0, 0, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215,
16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 6015176, 6015176, 6015176, 6015176,
6015176, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 16777215, 16777215,
16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 6015176, 6015176,
6015176, 6015176, 6015176, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 16777215,
16777215, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0,
0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0,
0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0,
0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176,
6015176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}
func Int2Color(intColor uint32) (col color.RGBA) {
blue := uint8(intColor & 0xFF)
green := uint8((intColor >> 8) & 0xFF)
red := uint8((intColor >> 16) & 0xFF)
return color.RGBA{R: red, G: green, B: blue}
}
+103
View File
@@ -0,0 +1,103 @@
package main
import (
"machine"
"image/color"
"time"
"tinygo.org/x/drivers/examples/hub75/gopherimg"
"tinygo.org/x/drivers/hub75"
)
var display hub75.Device
func main() {
machine.SPI0.Configure(machine.SPIConfig{
Frequency: 8000000,
Mode: 0},
)
display = hub75.New(machine.SPI0, 11, 12, 6, 10, 18, 20)
display.Configure(hub75.Config{
Width: 64,
Height: 32,
RowPattern: 16,
ColorDepth: 6,
})
colors := []color.RGBA{
{255, 0, 0, 255},
{255, 255, 0, 255},
{0, 255, 0, 255},
{0, 255, 255, 255},
{0, 0, 255, 255},
{255, 0, 255, 255},
{255, 255, 255, 255},
}
display.ClearDisplay()
display.SetBrightness(100)
step := 0
then := time.Now()
size := int16(8)
x := int16(0)
y := int16(0)
dx := int16(1)
dy := int16(1)
c := 0
for {
if time.Since(then).Nanoseconds() > 800000000 {
then = time.Now()
step++
if step < 23 {
showRect(size, x*size, y*size, colors[c])
c = (c + 1) % 7
x += dx
y += dy
if x >= (64 / size) {
dx = -1
x += 2 * dx
}
if y >= (32 / size) {
dy = -1
y += 2 * dy
}
if x < 0 {
dx = 1
x += 2 * dx
}
if y < 0 {
dy = 1
y += 2 * dy
}
} else if step == 23 {
showGopher()
} else if step == 30 {
display.ClearDisplay()
step = 0
x = 0
y = 0
}
}
display.Display()
}
}
func showGopher() {
for i := int16(0); i < 64; i++ {
for j := int16(0); j < 32; j++ {
display.SetPixel(i, j, gopherimg.Int2Color(gopherimg.ImageArray[32*i+j]))
}
}
}
func showRect(size int16, x int16, y int16, c color.RGBA) {
for i := x; i < x+size; i++ {
for j := y; j < y+size; j++ {
display.SetPixel(i, j, c)
}
}
}
+47
View File
@@ -0,0 +1,47 @@
package main
import (
"image/color"
"machine"
"time"
"tinygo.org/x/drivers/ili9341"
)
var (
display = ili9341.NewParallel(
machine.LCD_DATA0,
machine.TFT_WR,
machine.TFT_DC,
machine.TFT_CS,
machine.TFT_RESET,
machine.TFT_RD,
)
black = color.RGBA{0, 0, 0, 255}
white = color.RGBA{255, 255, 255, 255}
red = color.RGBA{255, 0, 0, 255}
blue = color.RGBA{0, 0, 255, 255}
green = color.RGBA{0, 255, 0, 255}
)
func main() {
machine.TFT_BACKLIGHT.Configure(machine.PinConfig{machine.PinOutput})
display.Configure(ili9341.Config{})
width, height := display.Size()
display.FillScreen(black)
machine.TFT_BACKLIGHT.High()
display.FillRectangle(0, 0, width/2, height/2, white)
display.FillRectangle(width/2, 0, width/2, height/2, red)
display.FillRectangle(0, height/2, width/2, height/2, green)
display.FillRectangle(width/2, height/2, width/2, height/2, blue)
display.FillRectangle(width/4, height/4, width/2, height/2, black)
for {
time.Sleep(time.Hour)
}
}
File diff suppressed because it is too large Load Diff
+234
View File
@@ -0,0 +1,234 @@
// Port of Adafruit's "pyportal_boing" demo found here:
// https://github.com/adafruit/Adafruit_ILI9341/blob/master/examples/pyportal_boing
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/examples/ili9341/pyportal_boing/graphics"
"tinygo.org/x/drivers/ili9341"
)
const (
BGCOLOR = 0xAD75
GRIDCOLOR = 0xA815
BGSHADOW = 0x5285
GRIDSHADOW = 0x600C
RED = 0xF800
WHITE = 0xFFFF
YBOTTOM = 123 // Ball Y coord at bottom
YBOUNCE = -3.5 // Upward velocity on ball bounce
_debug = false
)
var (
display = ili9341.NewParallel(
machine.LCD_DATA0,
machine.TFT_WR,
machine.TFT_DC,
machine.TFT_CS,
machine.TFT_RESET,
machine.TFT_RD,
)
frameBuffer = [(graphics.BALLHEIGHT + 8) * (graphics.BALLWIDTH + 8)]uint16{}
startTime int64
frame int64
// Ball coordinates are stored floating-point because screen refresh
// is so quick, whole-pixel movements are just too fast!
ballx float32
bally float32
ballvx float32
ballvy float32
ballframe float32
balloldx float32
balloldy float32
// Color table for ball rotation effect
palette [16]uint16
)
func main() {
// configure backlight
machine.TFT_BACKLIGHT.Configure(machine.PinConfig{machine.PinOutput})
// configure display
display.Configure(ili9341.Config{})
print("width, height == ")
width, height := display.Size()
println(width, height)
machine.TFT_BACKLIGHT.High()
display.SetRotation(ili9341.Rotation270)
DrawBackground()
startTime = time.Now().UnixNano()
frame = 0
ballx = 20.0
bally = YBOTTOM // Current ball position
ballvx = 0.8
ballvy = YBOUNCE // Ball velocity
ballframe = 3 // Ball animation frame #
balloldx = ballx
balloldy = bally // Prior ball position
for {
balloldx = ballx // Save prior position
balloldy = bally
ballx += ballvx // Update position
bally += ballvy
ballvy += 0.06 // Update Y velocity
if (ballx <= 15) || (ballx >= graphics.SCREENWIDTH-graphics.BALLWIDTH) {
ballvx *= -1 // Left/right bounce
}
if bally >= YBOTTOM { // Hit ground?
bally = YBOTTOM // Clip and
ballvy = YBOUNCE // bounce up
}
// Determine screen area to update. This is the bounds of the ball's
// prior and current positions, so the old ball is fully erased and new
// ball is fully drawn.
var minx, miny, maxx, maxy, width, height int16
// Determine bounds of prior and new positions
minx = int16(ballx)
if int16(balloldx) < minx {
minx = int16(balloldx)
}
miny = int16(bally)
if int16(balloldy) < miny {
miny = int16(balloldy)
}
maxx = int16(ballx + graphics.BALLWIDTH - 1)
if int16(balloldx+graphics.BALLWIDTH-1) > maxx {
maxx = int16(balloldx + graphics.BALLWIDTH - 1)
}
maxy = int16(bally + graphics.BALLHEIGHT - 1)
if int16(balloldy+graphics.BALLHEIGHT-1) > maxy {
maxy = int16(balloldy + graphics.BALLHEIGHT - 1)
}
width = maxx - minx + 1
height = maxy - miny + 1
// Ball animation frame # is incremented opposite the ball's X velocity
ballframe -= ballvx * 0.5
if ballframe < 0 {
ballframe += 14 // Constrain from 0 to 13
} else if ballframe >= 14 {
ballframe -= 14
}
// Set 7 palette entries to white, 7 to red, based on frame number.
// This makes the ball spin
for i := 0; i < 14; i++ {
if (int(ballframe)+i)%14 < 7 {
palette[i+2] = WHITE
} else {
palette[i+2] = RED
} // Palette entries 0 and 1 aren't used (clear and shadow, respectively)
}
// Only the changed rectangle is drawn into the 'renderbuf' array...
var c uint16 //, *destPtr;
bx := minx - int16(ballx) // X relative to ball bitmap (can be negative)
by := miny - int16(bally) // Y relative to ball bitmap (can be negative)
bgx := minx // X relative to background bitmap (>= 0)
bgy := miny // Y relative to background bitmap (>= 0)
var bx1, bgx1 int16 // Loop counters and working vars
var p uint8 // 'packed' value of 2 ball pixels
var bufIdx int8 = 0
//tft.setAddrWindow(minx, miny, width, height)
for y := 0; y < int(height); y++ { // For each row...
//destPtr = &renderbuf[bufIdx][0];
bx1 = bx // Need to keep the original bx and bgx values,
bgx1 = bgx // so copies of them are made here (and changed in loop below)
for x := 0; x < int(width); x++ {
var bgidx = int(bgy)*(graphics.SCREENWIDTH/8) + int(bgx1/8)
if (bx1 >= 0) && (bx1 < graphics.BALLWIDTH) && // Is current pixel row/column
(by >= 0) && (by < graphics.BALLHEIGHT) { // inside the ball bitmap area?
// Yes, do ball compositing math...
p = graphics.Ball[int(by*(graphics.BALLWIDTH/2))+int(bx1/2)] // Get packed value (2 pixels)
if (bx1 & 1) != 0 {
c = uint16(p & 0xF)
} else {
c = uint16(p >> 4)
} // Unpack high or low nybble
if c == 0 { // Outside ball - just draw grid
if graphics.Background[bgidx]&(0x80>>(bgx1&7)) != 0 {
c = GRIDCOLOR
} else {
c = BGCOLOR
}
} else if c > 1 { // In ball area...
c = palette[c]
} else { // In shadow area...
if graphics.Background[bgidx]&(0x80>>(bgx1&7)) != 0 {
c = GRIDSHADOW
} else {
c = BGSHADOW
}
}
} else { // Outside ball bitmap, just draw background bitmap...
if graphics.Background[bgidx]&(0x80>>(bgx1&7)) != 0 {
c = GRIDCOLOR
} else {
c = BGCOLOR
}
}
frameBuffer[y*int(width)+x] = c
bx1++ // Increment bitmap position counters (X axis)
bgx1++
}
//tft.dmaWait(); // Wait for prior line to complete
//tft.writePixels(&renderbuf[bufIdx][0], width, false); // Non-blocking write
bufIdx = 1 - bufIdx
by++ // Increment bitmap position counters (Y axis)
bgy++
}
display.DrawRGBBitmap(minx, miny, frameBuffer[:width*height], width, height)
// Show approximate frame rate
frame++
if frame&255 == 0 { // Every 256 frames...
elapsed := (time.Now().UnixNano() - startTime) / int64(time.Second)
if elapsed > 0 {
println(frame/elapsed, " fps")
}
}
}
}
func DrawBackground() {
w, h := display.Size()
byteWidth := (w + 7) / 8 // Bitmap scanline pad = whole byte
var b uint8
for j := int16(0); j < h; j++ {
for k := int16(0); k < w; k++ {
if k&7 > 0 {
b <<= 1
} else {
b = graphics.Background[j*byteWidth+k/8]
}
if b&0x80 == 0 {
frameBuffer[k] = BGCOLOR
} else {
frameBuffer[k] = GRIDCOLOR
}
}
display.DrawRGBBitmap(0, j, frameBuffer[0:w], w, 1)
}
}
+49
View File
@@ -0,0 +1,49 @@
package main
import (
"image/color"
"machine"
"time"
"tinygo.org/x/drivers/ili9341"
)
var (
display = ili9341.NewParallel(
machine.LCD_DATA0,
machine.TFT_WR,
machine.TFT_DC,
machine.TFT_CS,
machine.TFT_RESET,
machine.TFT_RD,
)
red = color.RGBA{255, 0, 0, 255}
blue = color.RGBA{0, 0, 255, 255}
green = color.RGBA{0, 255, 0, 255}
black = color.RGBA{0, 0, 0, 255}
white = color.RGBA{255, 255, 255, 255}
)
func main() {
machine.TFT_BACKLIGHT.Configure(machine.PinConfig{machine.PinOutput})
display.Configure(ili9341.Config{})
width, height := display.Size()
display.FillScreen(black)
machine.TFT_BACKLIGHT.High()
display.FillRectangle(0, 0, width/2, height/2, white)
display.FillRectangle(width/2, 0, width/2, height/2, red)
display.FillRectangle(0, height/2, width/2, height/2, green)
display.FillRectangle(width/2, height/2, width/2, height/2, blue)
display.FillRectangle(width/4, height/4, width/2, height/2, black)
for scroll := int16(0); ; scroll = (scroll + 1) % 320 {
time.Sleep(7500 * time.Microsecond)
display.SetScroll(scroll)
}
}
+34
View File
@@ -0,0 +1,34 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/l293x"
)
func main() {
wheel := l293x.New(machine.D10, machine.D11, machine.D12)
wheel.Configure()
for i := 0; i <= 10; i++ {
println("Forward")
wheel.Forward()
time.Sleep(time.Millisecond * 1000)
println("Stop")
wheel.Stop()
time.Sleep(time.Millisecond * 1000)
println("Backward")
wheel.Backward()
time.Sleep(time.Millisecond * 1000)
println("Stop")
wheel.Stop()
time.Sleep(time.Millisecond * 1000)
}
println("Stop")
wheel.Stop()
}
+45
View File
@@ -0,0 +1,45 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/l293x"
)
const (
maxSpeed = 30000
)
func main() {
machine.InitPWM()
wheel := l293x.NewWithSpeed(machine.D10, machine.D11, machine.PWM{machine.D12})
wheel.Configure()
for i := 0; i <= 10; i++ {
println("Forward")
var i uint16
for i = 0; i < maxSpeed; i += 1000 {
wheel.Forward(i)
time.Sleep(time.Millisecond * 100)
}
println("Stop")
wheel.Stop()
time.Sleep(time.Millisecond * 1000)
println("Backward")
for i = 0; i < maxSpeed; i += 1000 {
wheel.Backward(i)
time.Sleep(time.Millisecond * 100)
}
println("Stop")
wheel.Stop()
time.Sleep(time.Millisecond * 1000)
}
println("Stop")
wheel.Stop()
}
+34
View File
@@ -0,0 +1,34 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/l9110x"
)
func main() {
wheel := l9110x.New(machine.D10, machine.D11)
wheel.Configure()
for i := 0; i <= 10; i++ {
println("Forward")
wheel.Forward()
time.Sleep(time.Millisecond * 1000)
println("Stop")
wheel.Stop()
time.Sleep(time.Millisecond * 1000)
println("Backward")
wheel.Backward()
time.Sleep(time.Millisecond * 1000)
println("Stop")
wheel.Stop()
time.Sleep(time.Millisecond * 1000)
}
println("Stop")
wheel.Stop()
}
+45
View File
@@ -0,0 +1,45 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/l9110x"
)
const (
maxSpeed = 30000
)
func main() {
machine.InitPWM()
wheel := l9110x.NewWithSpeed(machine.PWM{machine.D11}, machine.PWM{machine.D12})
wheel.Configure()
for i := 0; i <= 10; i++ {
println("Forward")
var i uint16
for i = 0; i < maxSpeed; i += 1000 {
wheel.Forward(i)
time.Sleep(time.Millisecond * 100)
}
println("Stop")
wheel.Stop()
time.Sleep(time.Millisecond * 1000)
println("Backward")
for i = 0; i < maxSpeed; i += 1000 {
wheel.Backward(i)
time.Sleep(time.Millisecond * 100)
}
println("Stop")
wheel.Stop()
time.Sleep(time.Millisecond * 1000)
}
println("Stop")
wheel.Stop()
}
+32
View File
@@ -0,0 +1,32 @@
// Connects to a LIS3DH I2C accelerometer on the Adafruit Circuit Playground Express.
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/lis3dh"
)
var i2c = machine.I2C1
func main() {
i2c.Configure(machine.I2CConfig{SCL: machine.SCL1_PIN, SDA: machine.SDA1_PIN})
accel := lis3dh.New(i2c)
accel.Address = lis3dh.Address1 // address on the Circuit Playground Express
accel.Configure()
accel.SetRange(lis3dh.RANGE_2_G)
println(accel.Connected())
for {
x, y, z, _ := accel.ReadAcceleration()
println("X:", x, "Y:", y, "Z:", z)
rx, ry, rz := accel.ReadRawAcceleration()
println("X (raw):", rx, "Y (raw):", ry, "Z (raw):", rz)
time.Sleep(time.Millisecond * 100)
}
}
+30
View File
@@ -0,0 +1,30 @@
// Connects to an LSM6DS3 I2C a 6 axis Inertial Measurement Unit (IMU)
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/lsm6ds3"
)
func main() {
machine.I2C0.Configure(machine.I2CConfig{})
accel := lsm6ds3.New(machine.I2C0)
accel.Configure(lsm6ds3.Configuration{})
if !accel.Connected() {
println("LSM6DS3 not connected")
return
}
for {
x, y, z := accel.ReadAcceleration()
println("Acceleration:", float32(x)/1000000, float32(y)/1000000, float32(z)/1000000)
x, y, z = accel.ReadRotation()
println("Gyroscope:", float32(x)/1000000, float32(y)/1000000, float32(z)/1000000)
x, _ = accel.ReadTemperature()
println("Degrees C", float32(x)/1000, "\n\n")
time.Sleep(time.Millisecond * 1000)
}
}
+26
View File
@@ -0,0 +1,26 @@
// Connects to an MAG3110 I2C magnetometer.
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/mag3110"
)
func main() {
machine.I2C0.Configure(machine.I2CConfig{})
mag := mag3110.New(machine.I2C0)
mag.Configure()
for {
x, y, z := mag.ReadMagnetic()
println("Magnetic readings:", x, y, z)
c, _ := mag.ReadTemperature()
println("Temperature:", float32(c)/1000, "°C")
time.Sleep(time.Millisecond * 100)
}
}
+32
View File
@@ -0,0 +1,32 @@
// Connects to a MCP3008 ADC via SPI.
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/mcp3008"
)
var (
spi = machine.SPI0
csPin = machine.D12
)
func main() {
spi.Configure(machine.SPIConfig{
Frequency: 4000000,
Mode: 3})
adc := mcp3008.New(spi, csPin)
adc.Configure()
// get "CH0" aka "machine.ADC" interface to channel 0 from ADC.
p := adc.CH0
for {
val := p.Get()
println(val)
time.Sleep(50 * time.Millisecond)
}
}
+59
View File
@@ -0,0 +1,59 @@
package main
import (
"image/color"
"math/rand"
"time"
"tinygo.org/x/drivers/microbitmatrix"
)
var display microbitmatrix.Device
func main() {
display = microbitmatrix.New()
display.Configure(microbitmatrix.Config{})
display.ClearDisplay()
x := int16(1)
y := int16(2)
deltaX := int16(1)
deltaY := int16(1)
then := time.Now()
c := color.RGBA{255, 255, 255, 255}
for {
if time.Since(then).Nanoseconds() > 80000000 {
then = time.Now()
pixel := display.GetPixel(x, y)
if pixel {
display.ClearDisplay()
x = 1 + int16(rand.Int31n(3))
y = 1 + int16(rand.Int31n(3))
deltaX = 1
deltaY = 1
if rand.Int31n(2) == 0 {
deltaX = -1
}
if rand.Int31n(2) == 0 {
deltaY = -1
}
}
display.SetPixel(x, y, c)
x += deltaX
y += deltaY
if x == 0 || x == 4 {
deltaX = -deltaX
}
if y == 0 || y == 4 {
deltaY = -deltaY
}
}
display.Display()
}
}
+37
View File
@@ -0,0 +1,37 @@
// Example using the i2s hardware interface on the Adafruit Circuit Playground Express
// to read data from the onboard MEMS microphone.
//
// Uses ideas from the https://github.com/adafruit/Adafruit_CircuitPlayground repo.
//
package main
import (
"machine"
"tinygo.org/x/drivers/microphone"
)
const (
defaultSampleRate = 22000
quantizeSteps = 64
msForSPLSample = 50
defaultSampleCountForSPL = (defaultSampleRate / 1000) * msForSPLSample
)
func main() {
machine.I2S0.Configure(machine.I2SConfig{
Mode: machine.I2SModePDM,
AudioFrequency: defaultSampleRate * quantizeSteps / 16,
ClockSource: machine.I2SClockSourceExternal,
Stereo: true,
})
mic := microphone.New(machine.I2S0)
mic.SampleCountForSPL = defaultSampleCountForSPL
mic.Configure()
for {
spl, maxval := mic.GetSoundPressure()
println("C", spl, "max", maxval)
}
}
+22
View File
@@ -0,0 +1,22 @@
// Connects to an MMA8653 I2C accelerometer.
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/mma8653"
)
func main() {
machine.I2C0.Configure(machine.I2CConfig{})
accel := mma8653.New(machine.I2C0)
accel.Configure(mma8653.DataRate200Hz, mma8653.Sensitivity2G)
for {
x, y, z, _ := accel.ReadAcceleration()
println(x, y, z)
time.Sleep(time.Millisecond * 100)
}
}
+22
View File
@@ -0,0 +1,22 @@
// Connects to an MPU6050 I2C accelerometer/gyroscope.
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/mpu6050"
)
func main() {
machine.I2C0.Configure(machine.I2CConfig{})
accel := mpu6050.New(machine.I2C0)
accel.Configure()
for {
x, y, z := accel.ReadAcceleration()
println(x, y, z)
time.Sleep(time.Millisecond * 100)
}
}
+57
View File
@@ -0,0 +1,57 @@
package data
// example images
var Images = [2][]byte{
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0x60, 0x60, 0x60, 0x60, 0xe0, 0x60, 0x30, 0x18, 0x98,
0x70, 0x70, 0x60, 0x60, 0x60, 0xe0, 0x10, 0x08, 0x08, 0x04, 0x02, 0x02, 0xf2, 0xf2, 0x72, 0x72, 0x72, 0x04, 0x08, 0x10,
0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x20,
0x20, 0x20, 0xe0, 0x18, 0x1c, 0x07, 0x07, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00,
0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x87, 0x18, 0x60, 0x80, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03,
0x03, 0x00, 0x80, 0x40, 0x38, 0x07, 0x03, 0x07, 0x47, 0x47, 0x07, 0x9f, 0x87, 0xfc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x02, 0x02, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x3f, 0x20, 0x30, 0x0f, 0x0b, 0x80, 0x40, 0x41, 0x41, 0x42,
0x42, 0x42, 0x42, 0x42, 0x42, 0x41, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf9, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40, 0x7f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x40, 0x40, 0x40, 0x00, 0x00, 0xf8, 0x06, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x01, 0x00, 0x06, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x71,
0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x1b, 0x20, 0x60, 0xc0, 0x80,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x05, 0x05, 0x84, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
0x03, 0x1c, 0x10, 0x10, 0x20, 0x40, 0x40, 0x40, 0x47, 0x47, 0x44, 0x44, 0x44, 0x20, 0x20, 0x98, 0x84, 0xc3, 0x60, 0x20,
0x1c, 0x1c, 0x1b, 0x1b, 0x18, 0x18, 0x1f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x03, 0x07, 0x07, 0x0f, 0x3f, 0x3f, 0x3f, 0x1b, 0x03, 0x03, 0x01, 0x01, 0x01,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x03, 0x03, 0x01,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0x7e, 0x63, 0x63, 0xc1, 0x01, 0x81, 0x63, 0x23, 0x26, 0x3c,
0x20, 0x20, 0x20, 0xa0, 0x60, 0x10, 0x08, 0x08, 0x04, 0x02, 0xe2, 0xe2, 0xe2, 0x62, 0xe4, 0xec, 0x10, 0x20, 0x60, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20,
0x20, 0x20, 0x20, 0xf8, 0x38, 0x06, 0x06, 0x03, 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1c, 0x60, 0x80, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x02, 0x01, 0x01,
0x00, 0x80, 0x60, 0x1f, 0x03, 0x06, 0x0c, 0x16, 0x16, 0x16, 0x06, 0x06, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x03, 0x02, 0xfe, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x3f, 0x21, 0x1f, 0x0a, 0x80, 0x40, 0x41, 0x42, 0x42, 0x22, 0x22,
0x22, 0x42, 0x42, 0x82, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xfd, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x7f, 0x7f, 0x7f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0e, 0x1e, 0x61, 0x81, 0x01, 0x01, 0x82, 0x42, 0x24, 0x18, 0x00, 0xf8, 0x06, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0x01, 0x02, 0x9c, 0x60, 0x00, 0x00, 0x00, 0x2f, 0x2f, 0x30, 0x20, 0x20,
0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x08, 0x08, 0x08, 0x08, 0x38, 0x3f, 0xc0, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
0x0c, 0x10, 0x20, 0x20, 0x40, 0x40, 0x43, 0x47, 0x47, 0x24, 0x23, 0x23, 0x18, 0x84, 0x83, 0xc0, 0x60, 0x30, 0x18, 0x18,
0x18, 0x19, 0x1a, 0x1a, 0x0f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x06, 0x06, 0x1c, 0x1c, 0x7e, 0x7e, 0x7e, 0x36, 0x06, 0x06, 0x02, 0x02, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00},
}
+35
View File
@@ -0,0 +1,35 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/examples/pcd8544/setbuffer/data"
"tinygo.org/x/drivers/pcd8544"
)
func main() {
dcPin := machine.P3
dcPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
rstPin := machine.P4
rstPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
scePin := machine.P5
scePin.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.SPI0.Configure(machine.SPIConfig{})
lcd := pcd8544.New(machine.SPI0, dcPin, rstPin, scePin)
lcd.Configure(pcd8544.Config{})
i := 0
for {
err := lcd.SetBuffer(data.Images[i])
if err != nil {
println(err.Error())
}
lcd.Display()
i = (i + 1) % 2
time.Sleep(800 * time.Millisecond)
}
}
+49
View File
@@ -0,0 +1,49 @@
package main
import (
"image/color"
"machine"
"time"
"tinygo.org/x/drivers/pcd8544"
)
func main() {
dcPin := machine.P3
dcPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
rstPin := machine.P4
rstPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
scePin := machine.P5
scePin.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.SPI0.Configure(machine.SPIConfig{})
lcd := pcd8544.New(machine.SPI0, dcPin, rstPin, scePin)
lcd.Configure(pcd8544.Config{})
var x int16
var y int16
deltaX := int16(1)
deltaY := int16(1)
for {
pixel := lcd.GetPixel(x, y)
c := color.RGBA{255, 255, 255, 255}
if pixel {
c = color.RGBA{0, 0, 0, 255}
}
lcd.SetPixel(x, y, c)
lcd.Display()
x += deltaX
y += deltaY
if x == 0 || x == 83 {
deltaX = -deltaX
}
if y == 0 || y == 47 {
deltaY = -deltaY
}
time.Sleep(1 * time.Millisecond)
}
}
+23
View File
@@ -0,0 +1,23 @@
package main
// A small example that demonstrates how SemiHosting can be used.
// You could use it with a board that supports GDB, such as the BBC micro:bit:
// 1. Compile and debug it:
// tinygo gdb -target=microbit -ocd-output tinygo.org/x/drivers/examples/semihosting
// 2. Enable semihosting in the GDB shell:
// monitor arm semihosting enable
// 3. Start the program:
// continue
import (
"time"
"tinygo.org/x/drivers/semihosting"
)
func main() {
for {
semihosting.Stdout.Write([]byte("hello world!\n"))
time.Sleep(time.Second)
}
}
+44
View File
@@ -0,0 +1,44 @@
// This example is designed to implement the button shifter for a PyBadge.
package main
import (
"time"
"tinygo.org/x/drivers/shifter"
)
func main() {
buttons := shifter.NewButtons()
buttons.Configure()
for {
// Update the pins state, to later be returned by .Get()
buttons.ReadInput()
if buttons.Pins[shifter.BUTTON_LEFT].Get() {
println("Button LEFT pressed")
}
if buttons.Pins[shifter.BUTTON_UP].Get() {
println("Button UP pressed")
}
if buttons.Pins[shifter.BUTTON_DOWN].Get() {
println("Button DOWN pressed")
}
if buttons.Pins[shifter.BUTTON_RIGHT].Get() {
println("Button RIGHT pressed")
}
if buttons.Pins[shifter.BUTTON_SELECT].Get() {
println("Button SELECT pressed")
}
if buttons.Pins[shifter.BUTTON_START].Get() {
println("Button START pressed")
}
if buttons.Pins[shifter.BUTTON_A].Get() {
println("Button A pressed")
}
if buttons.Pins[shifter.BUTTON_B].Get() {
println("Button B pressed")
}
time.Sleep(100 * time.Millisecond)
}
}
+124
View File
@@ -0,0 +1,124 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/shiftregister"
)
func main() {
d := shiftregister.New(
shiftregister.EIGHT_BITS,
machine.PA6, // D12 Pin latch connected to ST_CP of 74HC595 (12)
machine.PA7, // D11 Pin clock connected to SH_CP of 74HC595 (11)
machine.PB6, // D10 Pin data connected to DS of 74HC595 (14)
)
d.Configure()
for {
// Examples using masks. This method writes all pins state at once.
// All pins High
d.WriteMask(0xFF)
delay()
// All pins Low
d.WriteMask(0x00)
delay()
// Some fun with masks
for _, pattern := range patterns {
d.WriteMask(pattern)
shortDelay()
}
delay()
d.WriteMask(0x00)
// Examples using individually addressable pin API. This method is slower than using mask
// because all register's pins state are send for is p.Set() call.
// Set register's pin #4
d.GetShiftPin(4).High()
delay()
d.GetShiftPin(4).Low()
delay()
// Get an individual pin and use it
pin := d.GetShiftPin(7)
pin.High()
delay()
pin.Low()
delay()
// Prepare an array of pin attached to the register
pins := [8]*shiftregister.ShiftPin{}
for p := 0; p < 8; p++ {
pins[p] = d.GetShiftPin(p)
}
for p := 7; p >= 0; p-- {
pins[p].Low()
shortDelay()
pins[p].High()
}
for p := 7; p >= 0; p-- {
pins[p].High()
time.Sleep(100 * time.Millisecond)
pins[p].Low()
}
delay()
}
}
func delay() {
time.Sleep(500 * time.Millisecond)
}
func shortDelay() {
time.Sleep(100 * time.Millisecond)
}
var patterns = []uint32{
0b00000001,
0b00000010,
0b00000100,
0b00001000,
0b00010000,
0b00100000,
0b01000000,
0b10000000,
0b10000001,
0b10000010,
0b10000100,
0b10001000,
0b10010000,
0b10100000,
0b11000000,
0b11000001,
0b11000010,
0b11000100,
0b11001000,
0b11010000,
0b11100000,
0b11100001,
0b11100010,
0b11100100,
0b11101000,
0b11110000,
0b11110001,
0b11110010,
0b11110100,
0b11111000,
0b11111001,
0b11111010,
0b11111100,
0b11111101,
0b11111110,
0b11111111,
0b00000000,
0b11111111,
0b00000000,
0b11111111,
}
+23
View File
@@ -0,0 +1,23 @@
package main
import (
"fmt"
"machine"
"time"
"tinygo.org/x/drivers/sht3x"
)
func main() {
machine.I2C0.Configure(machine.I2CConfig{})
sensor := sht3x.New(machine.I2C0)
for {
temp, humidity, _ := sensor.ReadTemperatureHumidity()
t := fmt.Sprintf("%.2f", float32(temp)/1000)
h := fmt.Sprintf("%.2f", float32(humidity)/100)
println("Temperature:", t, "°C")
println("Humidity", h, "%")
time.Sleep(2 * time.Second)
}
}
+51
View File
@@ -0,0 +1,51 @@
package main
import (
"machine"
"image/color"
"time"
"tinygo.org/x/drivers/ssd1306"
)
func main() {
machine.I2C0.Configure(machine.I2CConfig{
Frequency: machine.TWI_FREQ_400KHZ,
})
display := ssd1306.NewI2C(machine.I2C0)
display.Configure(ssd1306.Config{
Address: ssd1306.Address_128_32,
Width: 128,
Height: 32,
})
display.ClearDisplay()
x := int16(0)
y := int16(0)
deltaX := int16(1)
deltaY := int16(1)
for {
pixel := display.GetPixel(x, y)
c := color.RGBA{255, 255, 255, 255}
if pixel {
c = color.RGBA{0, 0, 0, 255}
}
display.SetPixel(x, y, c)
display.Display()
x += deltaX
y += deltaY
if x == 0 || x == 127 {
deltaX = -deltaX
}
if y == 0 || y == 31 {
deltaY = -deltaY
}
time.Sleep(1 * time.Millisecond)
}
}
+48
View File
@@ -0,0 +1,48 @@
package main
import (
"image/color"
"machine"
"time"
"tinygo.org/x/drivers/ssd1306"
)
func main() {
machine.SPI0.Configure(machine.SPIConfig{
Frequency: 8000000,
})
display := ssd1306.NewSPI(machine.SPI0, machine.P8, machine.P7, machine.P9)
display.Configure(ssd1306.Config{
Width: 128,
Height: 64,
})
display.ClearDisplay()
x := int16(64)
y := int16(32)
deltaX := int16(1)
deltaY := int16(1)
for {
pixel := display.GetPixel(x, y)
c := color.RGBA{255, 255, 255, 255}
if pixel {
c = color.RGBA{0, 0, 0, 255}
}
display.SetPixel(x, y, c)
display.Display()
x += deltaX
y += deltaY
if x == 0 || x == 127 {
deltaX = -deltaX
}
if y == 0 || y == 63 {
deltaY = -deltaY
}
time.Sleep(1 * time.Millisecond)
}
}
+33
View File
@@ -0,0 +1,33 @@
package ssd1331
import (
"machine"
"image/color"
"tinygo.org/x/drivers/ssd1331"
)
func main() {
machine.SPI0.Configure(machine.SPIConfig{
Frequency: 8000000,
})
display := ssd1331.New(machine.SPI0, machine.P6, machine.P7, machine.P8)
display.Configure(ssd1331.Config{})
display.SetContrast(0x30, 0x20, 0x30)
width, height := display.Size()
white := color.RGBA{255, 255, 255, 255}
red := color.RGBA{255, 0, 0, 255}
blue := color.RGBA{0, 0, 255, 255}
green := color.RGBA{0, 255, 0, 255}
black := color.RGBA{0, 0, 0, 255}
display.FillScreen(black)
display.FillRectangle(0, 0, width/2, height/2, white)
display.FillRectangle(width/2, 0, width/2, height/2, red)
display.FillRectangle(0, height/2, width/2, height/2, green)
display.FillRectangle(width/2, height/2, width/2, height/2, blue)
display.FillRectangle(width/4, height/4, width/2, height/2, black)
}
+33
View File
@@ -0,0 +1,33 @@
package main
import (
"machine"
"image/color"
"tinygo.org/x/drivers/st7735"
)
func main() {
machine.SPI0.Configure(machine.SPIConfig{
Frequency: 8000000,
})
display := st7735.New(machine.SPI0, machine.P6, machine.P7, machine.P8, machine.P9)
display.Configure(st7735.Config{})
width, height := display.Size()
white := color.RGBA{255, 255, 255, 255}
red := color.RGBA{255, 0, 0, 255}
blue := color.RGBA{0, 0, 255, 255}
green := color.RGBA{0, 255, 0, 255}
black := color.RGBA{0, 0, 0, 255}
display.FillScreen(black)
display.FillRectangle(0, 0, width/2, height/2, white)
display.FillRectangle(width/2, 0, width/2, height/2, red)
display.FillRectangle(0, height/2, width/2, height/2, green)
display.FillRectangle(width/2, height/2, width/2, height/2, blue)
display.FillRectangle(width/4, height/4, width/2, height/2, black)
}
+34
View File
@@ -0,0 +1,34 @@
package main
import (
"machine"
"image/color"
"tinygo.org/x/drivers/st7789"
)
func main() {
machine.SPI0.Configure(machine.SPIConfig{
Frequency: 8000000,
Mode: 3,
})
display := st7789.New(machine.SPI0, machine.P6, machine.P7, machine.P8)
display.Configure(st7789.Config{Rotation: st7789.NO_ROTATION})
width, height := display.Size()
white := color.RGBA{255, 255, 255, 255}
red := color.RGBA{255, 0, 0, 255}
blue := color.RGBA{0, 0, 255, 255}
green := color.RGBA{0, 255, 0, 255}
black := color.RGBA{0, 0, 0, 255}
display.FillScreen(black)
display.FillRectangle(0, 0, width/2, height/2, white)
display.FillRectangle(width/2, 0, width/2, height/2, red)
display.FillRectangle(0, height/2, width/2, height/2, green)
display.FillRectangle(width/2, height/2, width/2, height/2, blue)
display.FillRectangle(width/4, height/4, width/2, height/2, black)
}
+26
View File
@@ -0,0 +1,26 @@
// This example uses the settings for the thermistor that is built in to the
// Adafruit Circuit Playground Express.
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/thermistor"
)
const ADC_PIN = machine.TEMPSENSOR
func main() {
machine.InitADC()
sensor := thermistor.New(ADC_PIN)
sensor.Configure()
for {
temp, _ := sensor.ReadTemperature()
println("Temperature:", temp/1000, "°C")
time.Sleep(2 * time.Second)
}
}
+80
View File
@@ -0,0 +1,80 @@
// demo of 4-wire touchscreen as described in app note:
// http://ww1.microchip.com/downloads/en/Appnotes/doc8091.pdf
package main
import (
"machine"
"math"
"tinygo.org/x/drivers/touch"
"tinygo.org/x/drivers/touch/resistive"
)
var (
resistiveTouch = new(resistive.FourWire)
)
const (
Xmin = 750
Xmax = 325
Ymin = 840
Ymax = 240
)
func main() {
// configure touchscreen
machine.InitADC()
resistiveTouch.Configure(&resistive.FourWireConfig{
YP: machine.TOUCH_YD, // y+
YM: machine.TOUCH_YU, // y-
XP: machine.TOUCH_XR, // x+
XM: machine.TOUCH_XL, // x-
})
last := touch.Point{}
// loop and poll for touches, including performing debouncing
debounce := 0
for {
point := resistiveTouch.ReadTouchPoint()
touch := touch.Point{}
if point.Z>>6 > 100 {
touch.X = mapval(point.X>>6, Xmin, Xmax, 0, 240)
touch.Y = mapval(point.Y>>6, Ymin, Ymax, 0, 320)
touch.Z = point.Z >> 6 / 100
} else {
touch.X = 0
touch.Y = 0
touch.Z = 0
}
if last.Z != touch.Z {
debounce = 0
last = touch
} else if math.Abs(float64(touch.X-last.X)) > 4 ||
math.Abs(float64(touch.Y-last.Y)) > 4 {
debounce = 0
last = touch
} else if debounce > 1 {
debounce = 0
HandleTouch(last)
} else if touch.Z > 0 {
debounce++
} else {
last = touch
debounce = 0
}
}
}
// based on Arduino's "map" function
func mapval(x int, inMin int, inMax int, outMin int, outMax int) int {
return (x-inMin)*(outMax-outMin)/(inMax-inMin) + outMin
}
func HandleTouch(touch touch.Point) {
println("touch point:", touch.X, touch.Y, touch.Z)
}
@@ -0,0 +1,185 @@
package main
import (
"image/color"
"machine"
"math"
"tinygo.org/x/drivers/ili9341"
"tinygo.org/x/drivers/touch"
"tinygo.org/x/drivers/touch/resistive"
)
var (
resistiveTouch = &resistive.FourWire{}
display = ili9341.NewParallel(
machine.LCD_DATA0,
machine.TFT_WR,
machine.TFT_DC,
machine.TFT_CS,
machine.TFT_RESET,
machine.TFT_RD,
)
white = color.RGBA{255, 255, 255, 255}
black = color.RGBA{0, 0, 0, 255}
red = color.RGBA{255, 0, 0, 255}
green = color.RGBA{0, 255, 0, 255}
blue = color.RGBA{0, 0, 255, 255}
magenta = color.RGBA{255, 0, 255, 255}
yellow = color.RGBA{255, 255, 0, 255}
cyan = color.RGBA{0, 255, 255, 255}
oldColor color.RGBA
currentColor color.RGBA
)
const (
penRadius = 3
boxSize = 30
Xmin = 750
Xmax = 325
Ymin = 840
Ymax = 240
)
func main() {
// configure backlight
machine.TFT_BACKLIGHT.Configure(machine.PinConfig{machine.PinOutput})
// configure touchscreen
machine.InitADC()
resistiveTouch.Configure(&resistive.FourWireConfig{
YP: machine.TOUCH_YD,
YM: machine.TOUCH_YU,
XP: machine.TOUCH_XR,
XM: machine.TOUCH_XL,
})
// configure display
display.Configure(ili9341.Config{})
// fill the background and activate the backlight
width, height := display.Size()
display.FillRectangle(0, 0, width, height, black)
machine.TFT_BACKLIGHT.High()
// make color selection boxes
display.FillRectangle(0, 0, boxSize, boxSize, red)
display.FillRectangle(boxSize, 0, boxSize, boxSize, yellow)
display.FillRectangle(boxSize*2, 0, boxSize, boxSize, green)
display.FillRectangle(boxSize*3, 0, boxSize, boxSize, cyan)
display.FillRectangle(boxSize*4, 0, boxSize, boxSize, blue)
display.FillRectangle(boxSize*5, 0, boxSize, boxSize, magenta)
display.FillRectangle(boxSize*6, 0, boxSize, boxSize, black)
display.FillRectangle(boxSize*7, 0, boxSize, boxSize, white)
// set the initial color to red and draw a box to highlight it
oldColor = red
currentColor = red
display.DrawRectangle(0, 0, boxSize, boxSize, white)
last := touch.Point{}
// loop and poll for touches, including performing debouncing
debounce := 0
for {
point := resistiveTouch.ReadTouchPoint()
touch := touch.Point{}
if point.Z>>6 > 100 {
rawX := mapval(point.X>>6, Xmin, Xmax, 0, 240)
rawY := mapval(point.Y>>6, Ymin, Ymax, 0, 320)
touch.X = rawX
touch.Y = rawY
touch.Z = 1
} else {
touch.X = 0
touch.Y = 0
touch.Z = 0
}
if last.Z != touch.Z {
debounce = 0
last = touch
} else if math.Abs(float64(touch.X-last.X)) > 4 ||
math.Abs(float64(touch.Y-last.Y)) > 4 {
debounce = 0
last = touch
} else if debounce > 1 {
debounce = 0
HandleTouch(last)
} else if touch.Z > 0 {
debounce++
} else {
last = touch
debounce = 0
}
}
}
// based on Arduino's "map" function
func mapval(x int, inMin int, inMax int, outMin int, outMax int) int {
return (x-inMin)*(outMax-outMin)/(inMax-inMin) + outMin
}
func HandleTouch(touch touch.Point) {
if int16(touch.Y) < boxSize {
oldColor = currentColor
x := int16(touch.X)
switch {
case x < boxSize:
currentColor = red
case x < boxSize*2:
currentColor = yellow
case x < boxSize*3:
currentColor = green
case x < boxSize*4:
currentColor = cyan
case x < boxSize*5:
currentColor = blue
case x < boxSize*6:
currentColor = magenta
case x < boxSize*7:
currentColor = black
case x < boxSize*8:
currentColor = white
}
if oldColor == currentColor {
return
}
display.DrawRectangle((x/boxSize)*boxSize, 0, boxSize, boxSize, white)
switch oldColor {
case red:
x = 0
case yellow:
x = boxSize
case green:
x = boxSize * 2
case cyan:
x = boxSize * 3
case blue:
x = boxSize * 4
case magenta:
x = boxSize * 5
case black:
x = boxSize * 6
case white:
x = boxSize * 7
}
display.FillRectangle(int16(x), 0, boxSize, boxSize, oldColor)
}
if (int16(touch.Y) - penRadius) > boxSize {
display.FillRectangle(
int16(touch.X), int16(touch.Y), penRadius*2, penRadius*2, currentColor)
}
}
+41
View File
@@ -0,0 +1,41 @@
package main
import (
"time"
"machine"
"tinygo.org/x/drivers/veml6070"
)
func main() {
machine.I2C0.Configure(machine.I2CConfig{})
sensor := veml6070.New(machine.I2C0)
if !sensor.Configure() {
println("VEML6070 could not be configured")
return
}
println("VEML6070 configured")
for {
intensity, _ := sensor.ReadUVALightIntensity()
println("UVA light intensity:", float32(intensity)/1000.0, "W/(m*m)")
switch sensor.GetEstimatedRiskLevel(intensity) {
case veml6070.UVI_RISK_LOW:
println("UV risk level: low")
case veml6070.UVI_RISK_MODERATE:
println("UV risk level: moderate")
case veml6070.UVI_RISK_HIGH:
println("UV risk level: high")
case veml6070.UVI_RISK_VERY_HIGH:
println("UV risk level: very high")
case veml6070.UVI_RISK_EXTREME:
println("UV risk level: extreme")
}
time.Sleep(2 * time.Second)
}
}
+34
View File
@@ -0,0 +1,34 @@
package main
import (
"machine"
"time"
"tinygo.org/x/drivers/vl53l1x"
)
func main() {
machine.I2C0.Configure(machine.I2CConfig{
Frequency: 400000,
})
sensor := vl53l1x.New(machine.I2C0)
connected := sensor.Connected()
if !connected {
println("VL53L1X device not found")
return
}
println("VL53L1X device found")
sensor.Configure(true)
sensor.SetMeasurementTimingBudget(50000)
sensor.StartContinuous(50)
for {
sensor.Read(true)
println("Distance (mm):", sensor.Distance())
println("Status:", sensor.Status())
println("Peak signal rate (cps):", sensor.SignalRate())
println("Ambient rate (cps):", sensor.AmbientRate())
println("---")
time.Sleep(100 * time.Millisecond)
}
}
+77
View File
@@ -0,0 +1,77 @@
package main
import (
"machine"
"image/color"
"time"
"tinygo.org/x/drivers/waveshare-epd/epd2in13"
)
var display epd2in13.Device
func main() {
machine.SPI0.Configure(machine.SPIConfig{
Frequency: 8000000,
Mode: 0,
})
display = epd2in13.New(machine.SPI0, machine.P6, machine.P7, machine.P8, machine.P9)
display.Configure(epd2in13.Config{})
black := color.RGBA{1, 1, 1, 255}
white := color.RGBA{0, 0, 0, 255}
display.ClearBuffer()
println("Clear the display")
display.ClearDisplay()
display.WaitUntilIdle()
println("Waiting for 2 seconds")
time.Sleep(2 * time.Second)
// Show a checkered board
for i := int16(0); i < 16; i++ {
for j := int16(0); j < 25; j++ {
if (i+j)%2 == 0 {
showRect(i*8, j*10, 8, 10, black)
}
}
}
println("Show checkered board")
display.Display()
display.WaitUntilIdle()
println("Waiting for 2 seconds")
time.Sleep(2 * time.Second)
println("Set partial lut")
display.SetLUT(false) // partial updates (faster, but with some ghosting)
println("Show smaller striped area")
for i := int16(40); i < 88; i++ {
for j := int16(83); j < 166; j++ {
if (i+j)%4 == 0 || (i+j)%4 == 1 {
display.SetPixel(i, j, black)
} else {
display.SetPixel(i, j, white)
}
}
}
// There are two memory areas in the display, once the display is refreshed, memory areas are auto-toggled.
// DisplayRect needs to be called twice
display.DisplayRect(40, 83, 48, 83)
display.WaitUntilIdle()
display.DisplayRect(40, 83, 48, 83)
display.WaitUntilIdle()
println("You could remove power now")
}
func showRect(x int16, y int16, w int16, h int16, c color.RGBA) {
for i := x; i < x+w; i++ {
for j := y; j < y+h; j++ {
display.SetPixel(i, j, c)
}
}
}
+46
View File
@@ -0,0 +1,46 @@
package main
import (
"machine"
"image/color"
"tinygo.org/x/drivers/waveshare-epd/epd2in13x"
)
var display epd2in13x.Device
func main() {
machine.SPI0.Configure(machine.SPIConfig{
Frequency: 8000000,
Mode: 0,
})
display = epd2in13x.New(machine.SPI0, machine.P6, machine.P7, machine.P8, machine.P9)
display.Configure(epd2in13x.Config{})
white := color.RGBA{0, 0, 0, 255}
colored := color.RGBA{255, 0, 0, 255}
black := color.RGBA{1, 1, 1, 255}
display.ClearBuffer()
display.ClearDisplay()
// Show a checkered board
for i := int16(0); i < 27; i++ {
showRect((i%3)*35, i*8, 35, 8, colored)
showRect(((i+1)%3)*35, i*8, 35, 8, black)
showRect(((i+2)%3)*35, i*8, 35, 8, white)
}
display.Display()
display.WaitUntilIdle()
println("You could remove power now")
}
func showRect(x int16, y int16, w int16, h int16, c color.RGBA) {
for i := x; i < x+w; i++ {
for j := y; j < y+h; j++ {
display.SetPixel(i, j, c)
}
}
}
+149
View File
@@ -0,0 +1,149 @@
// This is a sensor station that uses a ESP8266 or ESP32 running on the device UART1.
// It creates an MQTT connection that publishes a message every second
// to an MQTT broker.
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266 <--> Internet <--> MQTT broker.
//
// You must install the Paho MQTT package to build this program:
//
// go get -u github.com/eclipse/paho.mqtt.golang
//
package main
import (
"fmt"
"machine"
"math/rand"
"time"
"tinygo.org/x/drivers/net/mqtt"
"tinygo.org/x/drivers/wifinina"
)
// access point info
const ssid = ""
const pass = ""
// IP address of the MQTT broker to use. Replace with your own info.
const server = "tcp://test.mosquitto.org:1883"
//const server = "ssl://test.mosquitto.org:8883"
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
// these are the default pins for the Arduino Nano33 IoT.
uart = machine.UART2
tx = machine.NINA_TX
rx = machine.NINA_RX
spi = machine.NINA_SPI
// this is the ESP chip that has the WIFININA firmware flashed on it
adaptor = &wifinina.Device{
SPI: spi,
CS: machine.NINA_CS,
ACK: machine.NINA_ACK,
GPIO0: machine.NINA_GPIO0,
RESET: machine.NINA_RESETN,
}
console = machine.UART0
topic = "tinygo"
)
func main() {
time.Sleep(3000 * time.Millisecond)
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
rand.Seed(time.Now().UnixNano())
// Configure SPI for 8Mhz, Mode 0, MSB First
spi.Configure(machine.SPIConfig{
Frequency: 8 * 1e6,
MOSI: machine.NINA_MOSI,
MISO: machine.NINA_MISO,
SCK: machine.NINA_SCK,
})
// Init esp8266/esp32
adaptor.Configure()
connectToAP()
opts := mqtt.NewClientOptions()
opts.AddBroker(server).SetClientID("tinygo-client-" + randomString(10))
println("Connectng to MQTT...")
cl := mqtt.NewClient(opts)
if token := cl.Connect(); token.Wait() && token.Error() != nil {
failMessage(token.Error().Error())
}
for i := 0; ; i++ {
println("Publishing MQTT message...")
data := []byte(fmt.Sprintf(`{"e":[{"n":"hello %d","v":101}]}`, i))
token := cl.Publish(topic, 0, false, data)
token.Wait()
if err := token.Error(); err != nil {
switch t := err.(type) {
case wifinina.Error:
println(t.Error(), "attempting to reconnect")
if token := cl.Connect(); token.Wait() && token.Error() != nil {
failMessage(token.Error().Error())
}
default:
println(err.Error())
}
}
time.Sleep(1 * time.Millisecond)
}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting MQTT...")
cl.Disconnect(100)
println("Done.")
}
// connect to access point
func connectToAP() {
time.Sleep(2 * time.Second)
println("Connecting to " + ssid)
adaptor.SetPassphrase(ssid, pass)
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
println("Connection status: " + st.String())
time.Sleep(1 * time.Second)
st, _ = adaptor.GetConnectionStatus()
}
println("Connected.")
time.Sleep(2 * time.Second)
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
println(err.Error())
time.Sleep(1 * time.Second)
}
println(ip.String())
}
// Returns an int >= min, < max
func randomInt(min, max int) int {
return min + rand.Intn(max-min)
}
// Generate a random string of A-Z chars with len = l
func randomString(len int) string {
bytes := make([]byte, len)
for i := 0; i < len; i++ {
bytes[i] = byte(randomInt(65, 90))
}
return string(bytes)
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
+162
View File
@@ -0,0 +1,162 @@
// This is a sensor station that uses a ESP8266 or ESP32 running on the device UART1.
// It creates an MQTT connection that publishes a message every second
// to an MQTT broker.
//
// In other words:
// Your computer <--> UART0 <--> MCU <--> UART1 <--> ESP8266 <--> Internet <--> MQTT broker.
//
// You must also install the Paho MQTT package to build this program:
//
// go get -u github.com/eclipse/paho.mqtt.golang
//
package main
import (
"fmt"
"machine"
"math/rand"
"time"
"tinygo.org/x/drivers/net/mqtt"
"tinygo.org/x/drivers/wifinina"
)
// access point info
const ssid = ""
const pass = ""
// IP address of the MQTT broker to use. Replace with your own info.
const server = "tcp://test.mosquitto.org:1883"
//const server = "ssl://test.mosquitto.org:8883"
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
// these are the default pins for the Arduino Nano33 IoT.
uart = machine.UART2
tx = machine.NINA_TX
rx = machine.NINA_RX
spi = machine.NINA_SPI
// this is the ESP chip that has the WIFININA firmware flashed on it
adaptor = &wifinina.Device{
SPI: spi,
CS: machine.NINA_CS,
ACK: machine.NINA_ACK,
GPIO0: machine.NINA_GPIO0,
RESET: machine.NINA_RESETN,
}
console = machine.UART0
cl mqtt.Client
topicTx = "tinygo/tx"
topicRx = "tinygo/rx"
)
func subHandler(client mqtt.Client, msg mqtt.Message) {
fmt.Printf("[%s] ", msg.Topic())
fmt.Printf("%s\r\n", msg.Payload())
}
func main() {
time.Sleep(3000 * time.Millisecond)
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
rand.Seed(time.Now().UnixNano())
// Configure SPI for 8Mhz, Mode 0, MSB First
spi.Configure(machine.SPIConfig{
Frequency: 8 * 1e6,
MOSI: machine.NINA_MOSI,
MISO: machine.NINA_MISO,
SCK: machine.NINA_SCK,
})
// Init esp8266/esp32
adaptor.Configure()
connectToAP()
opts := mqtt.NewClientOptions()
opts.AddBroker(server).SetClientID("tinygo-client-" + randomString(10))
println("Connecting to MQTT broker at", server)
cl = mqtt.NewClient(opts)
if token := cl.Connect(); token.Wait() && token.Error() != nil {
failMessage(token.Error().Error())
}
// subscribe
token := cl.Subscribe(topicRx, 0, subHandler)
token.Wait()
if token.Error() != nil {
failMessage(token.Error().Error())
}
go publishing()
select {}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting MQTT...")
cl.Disconnect(100)
println("Done.")
}
func publishing() {
for i := 0; ; i++ {
println("Publishing MQTT message...")
data := []byte(fmt.Sprintf(`{"e":[{"n":"hello %d","v":101}]}`, i))
token := cl.Publish(topicRx, 0, false, data)
token.Wait()
if token.Error() != nil {
println(token.Error().Error())
}
time.Sleep(100 * time.Millisecond)
}
}
// connect to access point
func connectToAP() {
time.Sleep(2 * time.Second)
println("Connecting to " + ssid)
adaptor.SetPassphrase(ssid, pass)
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
println("Connection status: " + st.String())
time.Sleep(1 * time.Second)
st, _ = adaptor.GetConnectionStatus()
}
println("Connected.")
time.Sleep(2 * time.Second)
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
println(err.Error())
time.Sleep(1 * time.Second)
}
println(ip.String())
}
// Returns an int >= min, < max
func randomInt(min, max int) int {
return min + rand.Intn(max-min)
}
// Generate a random string of A-Z chars with len = l
func randomString(len int) string {
bytes := make([]byte, len)
for i := 0; i < len; i++ {
bytes[i] = byte(randomInt(65, 90))
}
return string(bytes)
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
+143
View File
@@ -0,0 +1,143 @@
// This example opens a TCP connection using a device with WiFiNINA firmware
// and sends some data, for the purpose of testing speed and connectivity.
//
// You can open a server to accept connections from this program using:
//
// nc -w 5 -lk 8080
//
package main
import (
"bytes"
"fmt"
"machine"
"time"
"tinygo.org/x/drivers/net"
"tinygo.org/x/drivers/wifinina"
)
// access point info
const ssid = ""
const pass = ""
// IP address of the server aka "hub". Replace with your own info.
const serverIP = ""
// these are the default pins for the Arduino Nano33 IoT.
// change these to connect to a different UART or pins for the ESP8266/ESP32
var (
// these are the default pins for the Arduino Nano33 IoT.
uart = machine.UART2
tx = machine.NINA_TX
rx = machine.NINA_RX
spi = machine.NINA_SPI
// this is the ESP chip that has the WIFININA firmware flashed on it
adaptor = &wifinina.Device{
SPI: spi,
CS: machine.NINA_CS,
ACK: machine.NINA_ACK,
GPIO0: machine.NINA_GPIO0,
RESET: machine.NINA_RESETN,
}
console = machine.UART0
)
var buf = &bytes.Buffer{}
func main() {
uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
// Configure SPI for 8Mhz, Mode 0, MSB First
spi.Configure(machine.SPIConfig{
Frequency: 8 * 1e6,
MOSI: machine.NINA_MOSI,
MISO: machine.NINA_MISO,
SCK: machine.NINA_SCK,
})
adaptor.Configure()
connectToAP()
for {
sendBatch()
time.Sleep(500 * time.Millisecond)
}
println("Done.")
}
func sendBatch() {
// make TCP connection
ip := net.ParseIP(serverIP)
raddr := &net.TCPAddr{IP: ip, Port: 8080}
laddr := &net.TCPAddr{Port: 8080}
message("---------------\r\nDialing TCP connection")
conn, err := net.DialTCP("tcp", laddr, raddr)
for ; err != nil; conn, err = net.DialTCP("tcp", laddr, raddr) {
message(err.Error())
time.Sleep(5 * time.Second)
}
n := 0
w := 0
start := time.Now()
// send data
message("Sending data")
for i := 0; i < 1000; i++ {
buf.Reset()
fmt.Fprint(buf,
"\r---------------------------- i == ", i, " ----------------------------"+
"\r---------------------------- i == ", i, " ----------------------------")
if w, err = conn.Write(buf.Bytes()); err != nil {
println("error:", err.Error(), "\r")
continue
}
n += w
}
buf.Reset()
ms := time.Now().Sub(start).Milliseconds()
fmt.Fprint(buf, "\nWrote ", n, " bytes in ", ms, " ms\r\n")
message(buf.String())
if _, err := conn.Write(buf.Bytes()); err != nil {
println("error:", err.Error(), "\r")
}
// Right now this code is never reached. Need a way to trigger it...
println("Disconnecting TCP...")
conn.Close()
}
// connect to access point
func connectToAP() {
time.Sleep(2 * time.Second)
message("Connecting to " + ssid)
adaptor.SetPassphrase(ssid, pass)
for st, _ := adaptor.GetConnectionStatus(); st != wifinina.StatusConnected; {
message("Connection status: " + st.String())
time.Sleep(1 * time.Second)
st, _ = adaptor.GetConnectionStatus()
}
message("Connected.")
time.Sleep(2 * time.Second)
ip, _, _, err := adaptor.GetIP()
for ; err != nil; ip, _, _, err = adaptor.GetIP() {
message(err.Error())
time.Sleep(1 * time.Second)
}
message(ip.String())
}
func message(msg string) {
println(msg, "\r")
}

Some files were not shown because too many files have changed in this diff Show More