Compare commits

...

11 Commits

Author SHA1 Message Date
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
21 changed files with 474 additions and 54 deletions
+20
View File
@@ -1,3 +1,23 @@
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**
+5 -3
View File
@@ -11,6 +11,7 @@ smoke-test:
@mkdir -p build
tinygo build -size short -o ./build/test.elf -target=itsybitsy-m0 ./examples/adxl345/main.go
tinygo build -size short -o ./build/test.elf -target=itsybitsy-m0 ./examples/apa102/main.go
tinygo build -size short -o ./build/test.elf -target=itsybitsy-m0 ./examples/apa102/itsybitsy-m0/main.go
tinygo build -size short -o ./build/test.elf -target=microbit ./examples/at24cx/main.go
tinygo build -size short -o ./build/test.elf -target=itsybitsy-m0 ./examples/bh1750/main.go
tinygo build -size short -o ./build/test.elf -target=itsybitsy-m0 ./examples/blinkm/main.go
@@ -19,9 +20,9 @@ smoke-test:
tinygo build -size short -o ./build/test.elf -target=bluepill ./examples/ds1307/time/main.go
tinygo build -size short -o ./build/test.elf -target=itsybitsy-m0 ./examples/ds3231/main.go
tinygo build -size short -o ./build/test.elf -target=microbit ./examples/easystepper/main.go
tinygo build -size short -o ./build/test.elf -target=itsybitsy-m0 ./examples/espat/espconsole/main.go
tinygo build -size short -o ./build/test.elf -target=itsybitsy-m0 ./examples/espat/esphub/main.go
tinygo build -size short -o ./build/test.elf -target=itsybitsy-m0 ./examples/espat/espstation/main.go
tinygo build -size short -o ./build/test.elf -target=arduino-nano33 ./examples/espat/espconsole/main.go
tinygo build -size short -o ./build/test.elf -target=arduino-nano33 ./examples/espat/esphub/main.go
tinygo build -size short -o ./build/test.elf -target=arduino-nano33 ./examples/espat/espstation/main.go
tinygo build -size short -o ./build/test.elf -target=feather-m0 ./examples/gps/i2c/main.go
tinygo build -size short -o ./build/test.elf -target=feather-m0 ./examples/gps/uart/main.go
tinygo build -size short -o ./build/test.elf -target=microbit ./examples/hd44780/customchar/main.go
@@ -49,5 +50,6 @@ smoke-test:
tinygo build -size short -o ./build/test.elf -target=trinket-m0 ./examples/bme280/main.go
tinygo build -size short -o ./build/test.elf -target=circuitplay-express ./examples/microphone/main.go
tinygo build -size short -o ./build/test.elf -target=circuitplay-express ./examples/buzzer/main.go
tinygo build -size short -o ./build/test.elf -target=trinket-m0 ./examples/veml6070/main.go
test: clean fmt-check smoke-test
+1
View File
@@ -82,6 +82,7 @@ func main() {
| [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 |
+15 -2
View File
@@ -21,15 +21,28 @@ const (
// Device wraps APA102 SPI LEDs.
type Device struct {
bus machine.SPI
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 machine.SPI) Device {
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) {
+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()
}
}
+3 -3
View File
@@ -1,5 +1,5 @@
// Package drivers provides a collection of hardware drivers for devices that
// can be used together with TinyGo (https://tinygo.org).
// 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:
//
@@ -9,7 +9,7 @@
// "time"
// "machine"
//
// "github.com/tinygo-org/drivers/bmp180"
// "tinygo.org/x/drivers/bmp180"
// )
//
// func main() {
+1 -1
View File
@@ -1,4 +1,4 @@
// Simple driver to rotate a 4-wire stepper motor
// Package easystepper provides a simple driver to rotate a 4-wire stepper motor.
package easystepper // import "tinygo.org/x/drivers/easystepper"
import (
+2
View File
@@ -1,3 +1,5 @@
// Package mqtt is intended to provide compatible interfaces with the
// Paho mqtt library.
package mqtt
import (
+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
}
+4 -3
View File
@@ -23,11 +23,12 @@ const actAsAP = false
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.D10
rx = machine.D11
uart = machine.UART2
tx = machine.PA22
rx = machine.PA23
console = machine.UART0
+4 -3
View File
@@ -21,11 +21,12 @@ const actAsAP = false
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.D10
rx = machine.D11
uart = machine.UART2
tx = machine.PA22
rx = machine.PA23
adaptor *espat.Device
)
+4 -3
View File
@@ -21,11 +21,12 @@ 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.D10
rx = machine.D11
uart = machine.UART2
tx = machine.PA22
rx = machine.PA23
adaptor *espat.Device
)
+4 -3
View File
@@ -28,11 +28,12 @@ const pass = "YOURPASS"
//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.UART1
tx = machine.D10
rx = machine.D11
uart = machine.UART2
tx = machine.PA22
rx = machine.PA23
console = machine.UART0
+2 -1
View File
@@ -21,9 +21,10 @@ 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
uart = machine.UART2
tx = machine.PA22
rx = machine.PA23
+1 -1
View File
@@ -11,7 +11,7 @@ import (
var i2c = machine.I2C1
func main() {
i2c.Configure(machine.I2CConfig{})
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
+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)
}
}
+3 -16
View File
@@ -34,7 +34,7 @@ type Config struct {
Height int16
}
// New creates a new ST7735 connection. The SPI wire must already be configured.
// New creates a new SSD1331 connection. The SPI wire must already be configured.
func New(bus machine.SPI, resetPin, dcPin, csPin machine.Pin) Device {
dcPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
resetPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
@@ -250,21 +250,8 @@ func (d *Device) Data(data uint8) {
// Tx sends data to the display
func (d *Device) Tx(data []byte, isCommand bool) {
if isCommand {
d.csPin.High()
d.dcPin.Low()
d.csPin.Low()
d.bus.Tx(data, nil)
d.csPin.High()
} else {
d.csPin.High()
d.dcPin.High()
d.csPin.Low()
d.bus.Tx(data, nil)
d.csPin.High()
}
d.dcPin.Set(!isCommand)
d.bus.Tx(data, nil)
}
// Size returns the current size of the display.
+2 -15
View File
@@ -383,21 +383,8 @@ func (d *Device) Data(data uint8) {
// Tx sends data to the display
func (d *Device) Tx(data []byte, isCommand bool) {
if isCommand {
d.csPin.High()
d.dcPin.Low()
d.csPin.Low()
d.bus.Tx(data, nil)
d.csPin.High()
} else {
d.csPin.High()
d.dcPin.High()
d.csPin.Low()
d.bus.Tx(data, nil)
d.csPin.High()
}
d.dcPin.Set(!isCommand)
d.bus.Tx(data, nil)
}
// Size returns the current size of the display.
+65
View File
@@ -0,0 +1,65 @@
package veml6070
// I2C addresses and other constants
const (
ADDR_L = 0x38 // 7bit address of the VEML6070 (write, read)
ADDR_H = 0x39 // 7bit address of the VEML6070 (read)
)
// Some possible values for resistance value (in ohm) of VEML6070 calibration resistor
const (
RSET_240K = 240000
RSET_270K = 270000
RSET_300K = 300000
RSET_600K = 600000
)
// Possible values for integration time of VEML6070
// (internally represents the config register bit mask)
const (
IT_HALF = 0x00
IT_1 = 0x04
IT_2 = 0x08
IT_4 = 0x0C
)
// Possible values for UVI (UV index) risk level estimations - the VEML6070 can
// only estimate UVI risk levels since it can only sense UVA rays but the vendor
// tried to come up with some coarse thresholds, from application notes
const (
UVI_RISK_LOW = iota
UVI_RISK_MODERATE
UVI_RISK_HIGH
UVI_RISK_VERY_HIGH
UVI_RISK_EXTREME
)
// Scale factor in milliseconds / ohm to determine refresh time
// (aka sampling time) without IT_FACTOR for any given RSET, from datasheet.
// Note: 100.0 milliseconds are applicable for RSET=240 kOhm and IT_FACTOR=1
const RSET_TO_REFRESHTIME_SCALE = 100.0 / RSET_240K
// The refresh time in milliseconds for which NORMALIZED_UVA_SENSITIVITY
// is applicable to a step count
const NORMALIZED_REFRESHTIME = 100.0
// The UVA sensitivity in mW/(m*m)/step which is applicable to a step count
// normalized to the NORMALIZED_REFRESHTIME, from datasheet for RSET=240 kOhm
// and IT_FACTOR=1
const NORMALIZED_UVA_SENSITIVITY = 50.0
// Config register
// Possible values for shutdown
const (
CONFIG_SD_DISABLE = 0x00
CONFIG_SD_ENABLE = 0x01
)
// Enable / disable
const (
CONFIG_DEFAULTS = 0x02
CONFIG_ENABLE = CONFIG_SD_DISABLE | CONFIG_DEFAULTS
CONFIG_DISABLE = CONFIG_SD_ENABLE | CONFIG_DEFAULTS
)
+140
View File
@@ -0,0 +1,140 @@
// Package veml6070 provides a driver for the VEML6070 digital UV light sensor
// by Vishay.
//
// Datasheet:
// https://www.vishay.com/docs/84277/veml6070.pdf
// Application Notes:
// https://www.vishay.com/docs/84310/designingveml6070.pdf
//
package veml6070 // import "tinygo.org/x/drivers/veml6070"
import (
"time"
"machine"
)
// Device wraps an I2C connection to a VEML6070 device.
type Device struct {
bus machine.I2C
AddressLow uint16
AddressHigh uint16
RSET uint32
IT uint8
}
// New creates a new VEML6070 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,
AddressLow: ADDR_L,
AddressHigh: ADDR_H,
RSET: RSET_240K,
// Note: default to maximum to get as much precision as possible since
// raw data values larger than 16 bit can hardly occur with RSET below
// 300 kOhm in real world applications. Power saving due to shorter
// sampling time might be a reason to reduce this.
IT: IT_4,
}
}
// Configure sets up the device for communication
func (d *Device) Configure() bool {
// save power by shutdown as early as possible, also serves as presence test
if err := d.disable(); err != nil {
return false
}
return true
}
// ReadUVALightIntensity returns the UVA light intensity (irradiance)
// in milli Watt per square meter (mW/(m*m))
func (d *Device) ReadUVALightIntensity() (uint32, error) {
var err2 error
if err := d.enable(); err != nil {
return 0, err
}
// wait two times the refresh time to allow completion of a previous cycle
// with old settings (worst case)
time.Sleep(time.Duration(d.getRefreshTime()) * 2 * time.Millisecond)
msb, err2 := d.readData(d.AddressHigh)
if err2 != nil {
return 0, err2
}
lsb, err2 := d.readData(d.AddressLow)
if err2 != nil {
return 0, err2
}
if err := d.disable(); err != nil {
return 0, err
}
rawData := (uint32(msb) << 8) | uint32(lsb)
// normalize raw data (step count sampled in d.getRefreshTime()) into the
// linearly scaled normalized data (step count sampled in 100ms) for which
// we know the UVA sensitivity
normalizedData := float32(rawData) * NORMALIZED_REFRESHTIME / d.getRefreshTime()
// now we can calculate the absolute UVA power detected combining normalized
// data with known UVA sensitivity for this data, from datasheet
intensity := normalizedData * NORMALIZED_UVA_SENSITIVITY // mW/(m*m)
return uint32(intensity + 0.5), nil
}
// GetEstimatedRiskLevel returns estimated risk level from comparing UVA light
// intensity values in mW/(m*m) with thresholds calculated from application notes
func (d *Device) GetEstimatedRiskLevel(intensity uint32) uint8 {
if intensity <= 24888 {
return UVI_RISK_LOW
} else if intensity <= 49800 {
return UVI_RISK_MODERATE
} else if intensity <= 66400 {
return UVI_RISK_HIGH
} else if intensity <= 91288 {
return UVI_RISK_VERY_HIGH
} else {
return UVI_RISK_EXTREME
}
}
func (d *Device) disable() error {
return d.bus.Tx(uint16(d.AddressLow), []byte{CONFIG_DISABLE}, nil)
}
func (d *Device) enable() error {
return d.bus.Tx(uint16(d.AddressLow), []byte{CONFIG_ENABLE | d.IT}, nil)
}
func (d *Device) readData(address uint16) (byte, error) {
data := []byte{0}
err := machine.I2C0.Tx(address, []byte{}, data)
return data[0], err
}
// getRefreshTime returns the refresh time (aka sample time) in milliseconds
func (d *Device) getRefreshTime() float32 {
var it float32
switch d.IT {
case IT_HALF:
it = 0.5
case IT_1:
it = 1
case IT_2:
it = 2
case IT_4:
it = 4
}
return float32(d.RSET) * RSET_TO_REFRESHTIME_SCALE * it
}
+5
View File
@@ -0,0 +1,5 @@
package drivers
// Version returns a user-readable string showing the version of the drivers package for support purposes.
// Update this value before release of new version of software.
const Version = "0.7.0"