Lorawan uplink support and new lorawan 'basic-demo' example

This commit is contained in:
Olivier Fauchon
2023-01-10 23:15:39 +01:00
committed by Ron Evans
parent 301e6bc35b
commit 889536f7f0
15 changed files with 195 additions and 28 deletions
+4 -3
View File
@@ -4,6 +4,7 @@ import (
"encoding/hex" "encoding/hex"
"strings" "strings"
"tinygo.org/x/drivers/examples/lora/lorawan/common"
"tinygo.org/x/drivers/lora/lorawan" "tinygo.org/x/drivers/lora/lorawan"
) )
@@ -14,7 +15,7 @@ func quicktest() {
// Check firmware version. // Check firmware version.
func version() { func version() {
writeCommandOutput("VER", currentVersion()+" ("+firmwareVersion()+")") writeCommandOutput("VER", common.CurrentVersion()+" ("+common.FirmwareVersion()+")")
} }
// Use to check the ID of the LoRaWAN module, or change the ID. // Use to check the ID of the LoRaWAN module, or change the ID.
@@ -443,7 +444,7 @@ func sendhex(data string) error {
func recv(setting string) error { func recv(setting string) error {
cmd := "RECV" cmd := "RECV"
data, err := lorarx() data, err := common.Lorarx()
if err != nil { if err != nil {
writeCommandOutput(cmd, "ERROR "+err.Error()) writeCommandOutput(cmd, "ERROR "+err.Error())
return err return err
@@ -456,7 +457,7 @@ func recv(setting string) error {
func recvhex(setting string) error { func recvhex(setting string) error {
cmd := "RECVHEX" cmd := "RECVHEX"
data, err := lorarx() data, err := common.Lorarx()
if err != nil { if err != nil {
writeCommandOutput(cmd, "ERROR "+err.Error()) writeCommandOutput(cmd, "ERROR "+err.Error())
return err return err
+2 -1
View File
@@ -12,6 +12,7 @@ import (
"machine" "machine"
"time" "time"
"tinygo.org/x/drivers/examples/lora/lorawan/common"
"tinygo.org/x/drivers/lora" "tinygo.org/x/drivers/lora"
"tinygo.org/x/drivers/lora/lorawan" "tinygo.org/x/drivers/lora/lorawan"
) )
@@ -34,7 +35,7 @@ func main() {
uart.Configure(machine.UARTConfig{TX: tx, RX: rx}) uart.Configure(machine.UARTConfig{TX: tx, RX: rx})
var err error var err error
radio, err = setupLora() radio, err = common.SetupLora()
if err != nil { if err != nil {
fail(err.Error()) fail(err.Error())
} }
-7
View File
@@ -1,7 +0,0 @@
package main
const VERSION = "0.0.1"
func currentVersion() string {
return VERSION
}
@@ -0,0 +1,35 @@
# Simple Lorawan example
This demo code will connect Lorawan network and send sample uplink message
You may change your Lorawan keys (AppEUI, DevEUI, AppKEY) in key-default.go
```
$ tinygo monitor
Connected to /dev/ttyACM0. Press Ctrl-C to exit.
Lorawan Simple Demo
Start Lorawan Join sequence
loraConnect: Connected !
```
# Building
## Simulator
```
tinygo flash -target pico ./examples/lora/lorawan/basic-demo
```
## PyBadge with LoRa Featherwing
```
tinygo flash -target pybadge -tags featherwing ./examples/lora/lorawan/basic-demo
```
## LoRa-E5
```
tinygo flash -target lorae5 ./examples/lora/lorawan/basic-demo
```
@@ -0,0 +1,11 @@
//go:build !customkeys
package main
// These are sample keys, so the example builds
// Either change here, or create a new go file and use customkeys build tag
func setLorawanKeys() {
otaa.SetAppEUI([]uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
otaa.SetDevEUI([]uint8{0xB3, 0xD5, 0x41, 0x00, 0x0A, 0xF1, 0xA4, 0x45})
otaa.SetAppKey([]uint8{0x12, 0x22, 0xA3, 0xFF, 0x0C, 0x7B, 0x76, 0x7B, 0x8F, 0xD3, 0x12, 0x4F, 0xCE, 0x7A, 0x32, 0x16})
}
+107
View File
@@ -0,0 +1,107 @@
// Simple code for connecting to Lorawan network and uploading sample payload
package main
import (
"errors"
"strconv"
"time"
"tinygo.org/x/drivers/examples/lora/lorawan/common"
"tinygo.org/x/drivers/lora"
"tinygo.org/x/drivers/lora/lorawan"
)
const (
LORAWAN_JOIN_TIMEOUT_SEC = 180
LORAWAN_RECONNECT_DELAY_SEC = 15
LORAWAN_UPLINK_DELAY_SEC = 60
)
var (
radio lora.Radio
session *lorawan.Session
otaa *lorawan.Otaa
)
func loraConnect() error {
start := time.Now()
var err error
for time.Since(start) < LORAWAN_JOIN_TIMEOUT_SEC*time.Second {
println("Trying to join network")
err = lorawan.Join(otaa, session)
if err == nil {
println("Connected to network !")
return nil
}
println("Join error:", err, "retrying in", LORAWAN_RECONNECT_DELAY_SEC, "sec")
time.Sleep(time.Second * LORAWAN_RECONNECT_DELAY_SEC)
}
err = errors.New("Unable to join Lorawan network")
println(err.Error())
return err
}
func failMessage(err error) {
println("FATAL:", err)
for {
}
}
func main() {
println("*** Lorawan basic join and uplink demo ***")
// Board specific Lorawan initialization
var err error
radio, err = common.SetupLora()
if err != nil {
failMessage(err)
}
// Required for LoraWan operations
session = &lorawan.Session{}
otaa = &lorawan.Otaa{}
// Initial Lora modulation configuration
loraConf := lora.Config{
Freq: 868100000,
Bw: lora.Bandwidth_125_0,
Sf: lora.SpreadingFactor9,
Cr: lora.CodingRate4_7,
HeaderType: lora.HeaderExplicit,
Preamble: 12,
Ldr: lora.LowDataRateOptimizeOff,
Iq: lora.IQStandard,
Crc: lora.CRCOn,
SyncWord: lora.SyncPublic,
LoraTxPowerDBm: 20,
}
radio.LoraConfig(loraConf)
// Connect the lorawan with the Lora Radio device.
lorawan.UseRadio(radio)
// Configure AppEUI, DevEUI, APPKey
setLorawanKeys()
// Try to connect Lorawan network
if err := loraConnect(); err != nil {
failMessage(err)
}
// Try to periodicaly send an uplink sample message
upCount := 1
for {
payload := "Hello TinyGo #" + strconv.Itoa(upCount)
if err := lorawan.SendUplink([]byte(payload), session); err != nil {
println("Uplink error:", err)
} else {
println("Uplink success, msg=", payload)
}
println("Sleeping for", LORAWAN_UPLINK_DELAY_SEC, "sec")
time.Sleep(time.Second * LORAWAN_UPLINK_DELAY_SEC)
upCount++
}
}
@@ -1,4 +1,4 @@
package main package common
import ( import (
"errors" "errors"
@@ -1,11 +1,11 @@
//go:build !featherwing && !gnse && !lorae5 && !nucleowl55jc //go:build !featherwing && !gnse && !lorae5 && !nucleowl55jc
package main package common
import "tinygo.org/x/drivers/lora" import "tinygo.org/x/drivers/lora"
// do simulator setup here // do simulator setup here
func setupLora() (lora.Radio, error) { func SetupLora() (lora.Radio, error) {
return &SimLoraRadio{}, nil return &SimLoraRadio{}, nil
} }
@@ -29,11 +29,12 @@ func (sr *SimLoraRadio) SetCodingRate(cr uint8) {}
func (sr *SimLoraRadio) SetBandwidth(bw uint8) {} func (sr *SimLoraRadio) SetBandwidth(bw uint8) {}
func (sr *SimLoraRadio) SetCrc(enable bool) {} func (sr *SimLoraRadio) SetCrc(enable bool) {}
func (sr *SimLoraRadio) SetSpreadingFactor(sf uint8) {} func (sr *SimLoraRadio) SetSpreadingFactor(sf uint8) {}
func (sr *SimLoraRadio) LoraConfig(cnf lora.Config) {}
func firmwareVersion() string { func FirmwareVersion() string {
return "simulator " + currentVersion() return "simulator " + CurrentVersion()
} }
func lorarx() ([]byte, error) { func Lorarx() ([]byte, error) {
return nil, nil return nil, nil
} }
@@ -1,6 +1,6 @@
//go:build gnse || lorae5 || nucleowl55jc //go:build gnse || lorae5 || nucleowl55jc
package main package common
import ( import (
"device/stm32" "device/stm32"
@@ -24,7 +24,7 @@ var (
) )
// do sx126x setup here // do sx126x setup here
func setupLora() (lora.Radio, error) { func SetupLora() (lora.Radio, error) {
loraRadio = sx126x.New(machine.SPI3) loraRadio = sx126x.New(machine.SPI3)
loraRadio.SetDeviceType(sx126x.DEVICE_TYPE_SX1262) loraRadio.SetDeviceType(sx126x.DEVICE_TYPE_SX1262)
@@ -64,10 +64,10 @@ func radioIntHandler(intr interrupt.Interrupt) {
loraRadio.HandleInterrupt() loraRadio.HandleInterrupt()
} }
func firmwareVersion() string { func FirmwareVersion() string {
return "sx126x" return "sx126x"
} }
func lorarx() ([]byte, error) { func Lorarx() ([]byte, error) {
return loraRadio.Rx(LORA_DEFAULT_RXTIMEOUT_MS) return loraRadio.Rx(LORA_DEFAULT_RXTIMEOUT_MS)
} }
@@ -1,6 +1,6 @@
//go:build featherwing //go:build featherwing
package main package common
import ( import (
"strconv" "strconv"
@@ -28,7 +28,7 @@ var (
) )
// do sx127x setup here // do sx127x setup here
func setupLora() (lora.Radio, error) { func SetupLora() (lora.Radio, error) {
rstPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) rstPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
csPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) csPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
dio0Pin.Configure(machine.PinConfig{Mode: machine.PinInputPullup}) dio0Pin.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
@@ -75,11 +75,11 @@ func dioIrqHandler(machine.Pin) {
loraRadio.HandleInterrupt() loraRadio.HandleInterrupt()
} }
func firmwareVersion() string { func FirmwareVersion() string {
v := loraRadio.GetVersion() v := loraRadio.GetVersion()
return "sx127x v" + strconv.Itoa(int(v)) return "sx127x v" + strconv.Itoa(int(v))
} }
func lorarx() ([]byte, error) { func Lorarx() ([]byte, error) {
return loraRadio.Rx(LORA_DEFAULT_RXTIMEOUT_MS) return loraRadio.Rx(LORA_DEFAULT_RXTIMEOUT_MS)
} }
+7
View File
@@ -0,0 +1,7 @@
package common
const VERSION = "0.0.1"
func CurrentVersion() string {
return VERSION
}
@@ -13,7 +13,7 @@
| RX | HIGH | LOW | HIGH | | RX | HIGH | LOW | HIGH |
+-----------+----------+-----------+------------+ +-----------+----------+-----------+------------+
*/ */
package main package common
import ( import (
"machine" "machine"
+11 -1
View File
@@ -71,7 +71,17 @@ func Join(otaa *Otaa, session *Session) error {
return nil return nil
} }
func SendUplink() error { func SendUplink(data []uint8, session *Session) error {
payload, err := session.GenMessage(0, []byte(data))
if err != nil {
return err
}
ActiveRadio.SetCrc(true)
ActiveRadio.SetIqMode(0) // IQ Standard
ActiveRadio.Tx(payload, LORA_RXTX_TIMEOUT)
if err != nil {
return err
}
return nil return nil
} }
+1 -1
View File
@@ -87,7 +87,7 @@ func (o *Otaa) GenerateJoinRequest() ([]uint8, error) {
o.buf = append(o.buf, 0x00) o.buf = append(o.buf, 0x00)
o.buf = append(o.buf, reverseBytes(o.AppEUI[:])...) o.buf = append(o.buf, reverseBytes(o.AppEUI[:])...)
o.buf = append(o.buf, reverseBytes(o.DevEUI[:])...) o.buf = append(o.buf, reverseBytes(o.DevEUI[:])...)
o.buf = append(o.buf, reverseBytes(o.DevNonce[:])...) o.buf = append(o.buf, o.DevNonce[:]...)
mic := genPayloadMIC(o.buf, o.AppKey) mic := genPayloadMIC(o.buf, o.AppKey)
o.buf = append(o.buf, mic[:]...) o.buf = append(o.buf, mic[:]...)
+1
View File
@@ -10,4 +10,5 @@ type Radio interface {
SetBandwidth(bw uint8) SetBandwidth(bw uint8)
SetCrc(enable bool) SetCrc(enable bool)
SetSpreadingFactor(sf uint8) SetSpreadingFactor(sf uint8)
LoraConfig(cnf Config)
} }