Pycom Ation Wi Py 3.0 User Guide
User Manual:
Open the PDF directly: View PDF .
Page Count: 496 [warning: Documents this large are best viewed by clicking the View PDF Link!]
- Preface
- Pycom Products
- 1.0 Introduction
- 1.1 Hardware Setup
- 1.2 Software
- 1.3 Programming the modules
- 1.4 Device Registration
- 2.1 Installation
- 2.2 Tools/Features
- 2.3 Settings
- 3.1 Introduction
- 3.2 Installing Software
- 3.3 API Reference
- 4.1 Introduction
- 4.2 All Pycom Device Examples
- 4.3 LoRa Examples
- 4.4 Sigfox Examples
- 4.5 LTE Examples
- 4.6 Pytrack Examples
- 4.7 Pysense Examples
- 5.1 Introduction
- 5.2 Pycom Modules
- 5.3 MicroPython Modules
- 6.0 Introduction
- 6.1 Development Modules
- 6.2 OEM Modules
- 6.3 Expansion Boards and Shields
- 6.4 Notes
- 7.1 Development Modules
- 7.2 OEM Modules
- 7.3 Expansion Boards and Shields
- 8.1 Introduction
- 8.2 Getting Started
- 8.3 Add a device to Pybytes
- 8.4 Visualise data from your device
- 9.1 Introduction
- 9.2 Syntax
- 9.3 REPL vs Scripts
- 10.1 Firmware Downgrade
- 10.2 CLI Updater
- 10.3 SecureBoot and Encryption
- 11.1 License
1.1
1.2
2.1
2.2
2.2.1
2.2.2
2.2.3
2.2.4
2.2.5
2.2.6
2.3
2.3.1
2.3.2
2.3.3
2.4
2.4.1
2.4.2
2.4.3
2.4.4
2.4.4.1
2.4.4.2
2.4.5
2.4.6
2.5
2.5.1
TableofContents
About
Preface
PycomProducts
1.GettingStarted
1.0Introduction
1.1HardwareSetup
1.1.1LoPy
1.1.2LoPy4
1.1.1SiPy
1.1.1GPy
1.1.1FiPy
1.1.1WiPy
1.2Software
1.2.1Drivers
1.2.2UpdatingFirmware
1.2.3Pymakr
1.3Programmingthemodules
1.3.1IntroductiontoMicroPython
1.3.2MicroPythonExamples
1.3.3YourfirstPymakrproject
1.3.4REPL
1.3.4.1SerialUSB
1.3.4.2Telnet
1.3.5FTP
1.3.6Safeboot
1.4DeviceRegistration
1.4.1Sigfox
1
2.5.2
2.5.3
2.5.3.1
2.5.3.2
3.1
3.1.1
3.1.2
3.2
3.3
4.1
4.2
4.2.1
4.2.2
4.2.3
4.3
4.3.1
4.3.2
4.3.3
5.1
5.2
5.2.1
5.2.2
5.2.3
5.2.4
5.2.5
1.4.2Cellular
1.4.3LoRaWAN
1.4.3.2TheThingsNetwork
1.4.3.2Objenious
2.PymakrPlugin
2.1Installation
2.1.1Atom
2.1.2VisualStudioCode
2.2Tools/Features
2.3Settings
3.Pysense&Pytrack
3.1Introduction
3.2InstallingSoftware
3.2.1UpdatingFirmware
3.2.2InstallingDrivers-Windows7
3.2.3InstallingLibraries
3.3APIReference
3.3.1Pytrack
3.3.2Pysense
3.3.3Sleep
4.Tutorials&Examples
4.1Introduction
4.2AllPycomDeviceExamples
4.2.1REPL
4.2.2WLAN
4.2.3Bluetooth
4.2.4HTTPS
4.2.5MQTT
2
5.2.6
5.2.7
5.2.8
5.2.9
5.2.10
5.2.11
5.2.12
5.2.13
5.2.14
5.2.15
5.2.16
5.3
5.3.1
5.3.2
5.3.3
5.3.4
5.3.5
5.3.6
5.3.7
5.4
5.4.1
5.4.2
5.5
5.5.1
5.5.2
5.5.3
5.5.4
5.6
5.7
6.1
6.2
4.2.6AWS
4.2.7ADC
4.2.8I2C
4.2.9OnewireDriver
4.2.10Threading
4.2.11RGBLED
4.2.12Timers
4.2.13PIRSensor
4.2.14Modbus
4.2.15OTAupdate
4.2.16RMT
4.3LoRaExamples
4.3.1LoRa-MAC(RawLoRa)
4.3.2LoRaWANwithOTAA
4.3.3LoRaWANwithABP
4.3.4LoRa-MACNano-Gateway
4.3.5LoPytoLoPy
4.3.6LoRaWANNano-Gateway
4.3.7RN2483toLoPy
4.4SigfoxExamples
4.4.1RegisterDevice
4.4.2DisengageSequenceNumber
4.5LTEExamples
4.5.1CAT-M1
4.5.2NB-IoT
4.5.3ModuleIMEI
4.5.3ModemFirmwareUpdate
4.6PytrackExamples
4.7PysenseExamples
5.Firmware&APIReference
5.1Introduction
5.2PycomModules
3
6.2.1
6.2.1.1
6.2.1.2
6.2.1.3
6.2.1.4
6.2.1.5
6.2.1.6
6.2.1.7
6.2.1.8
6.2.1.9
6.2.1.10
6.2.1.11
6.2.1.12
6.2.1.13
6.2.2
6.2.2.1
6.2.2.2
6.2.2.3
6.2.2.3.1
6.2.2.3.2
6.2.2.3.3
6.2.2.3.4
6.2.2.3.5
6.2.2.3.6
6.2.2.4
6.2.2.5
6.2.2.6
6.2.3
6.2.4
6.3
6.3.1
6.3.2
6.3.3
6.3.4
5.2.1machine
5.2.1.1ADC
5.2.1.2DAC
5.2.1.3I2C
5.2.1.4Pin
5.2.1.5PWM
5.2.1.6RTC
5.2.1.7SPI
5.2.1.8UART
5.2.1.9WDT
5.2.1.10Timer
5.2.1.11SD
5.2.1.12CAN
5.2.1.13RMT
5.2.2network
5.2.2.1WLAN
5.2.2.2Server
5.2.2.3Bluetooth
5.2.2.3.1GATT
5.2.2.3.2GATTCConnection
5.2.2.3.3GATTCService
5.2.2.3.4GATTCCharacteristic
5.2.2.3.5GATTSService
5.2.2.3.6GATTSCharacteristic
5.2.2.4LoRa
5.2.2.5Sigfox
5.2.2.6LTE
5.2.3AES
5.2.4pycom
5.3MicroPythonModules
5.3.1micropython
5.3.2uctypes
5.3.3sys
5.3.4uos
4
6.3.5
6.3.6
6.3.7
6.3.8
6.3.9
6.3.10
6.3.11
6.3.12
6.3.13
6.3.14
6.3.15
6.3.16
6.3.17
6.3.18
6.3.19
6.3.20
7.1
7.2
7.2.1
7.2.2
7.2.3
7.2.4
7.2.5
7.2.6
7.2.7
7.3
7.3.1
7.3.2
7.3.3
7.3.4
5.3.5array
5.3.6cmath
5.3.7math
5.3.8gc
5.3.9ubinascii
5.3.10ujson
5.3.11ure
5.3.12usocket
5.3.13select
5.3.14utime
5.3.15uhashlib
5.3.16ussl
5.3.17ucrypto
5.3.18ustruct
5.3.19_thread
5.3.20Builtin
6.ProductInfo
6.0Introduction
6.1DevelopmentModules
6.1.1WiPy2.0
6.1.2WiPy3.0
6.1.3LoPy
6.1.4LoPy4
6.1.5SiPy
6.1.6GPy
6.1.7FiPy
6.2OEMModules
6.2.1W01
6.2.2L01
6.2.3L04
6.2.4G01
5
7.3.5
7.3.6
7.4
7.4.1
7.4.2
7.4.3
7.4.4
7.4.5
7.4.6
7.4.6.1
7.5
8.1
8.1.1
8.1.2
8.1.3
8.1.4
8.1.5
8.1.6
8.1.7
8.2
8.2.1
8.2.2
8.2.3
8.2.4
8.3
8.3.1
8.3.2
8.3.3
8.3.4
6.2.5L01OEMBaseboardReference
6.2.6UniversalOEMBaseboardReference
6.3ExpansionBoardsandShields
6.3.1ExpansionBoard3.0
6.3.2Pytrack
6.3.3Pysense
6.3.4Pyscan
6.3.5ExpansionBoard2.0
6.3.6DeepSleepShield
6.3.6.1DeepSleepAPI
6.4Notes
7.Datasheets
7.1DevelopmentModules
7.1.1WiPy2.0
7.1.2WiPy3.0
7.1.3LoPy
7.1.4LoPy4
7.1.5SiPy
7.1.6GPy
7.1.7FiPy
7.2OEMModules
7.2.1W01
7.2.2L01
7.2.3L04
7.2.4G01
7.3ExpansionBoardsandShields
7.3.1ExpansionBoard3.0
7.3.2Pytrack
7.3.3Pysense
7.3.4ExpansionBoard2.0
6
9.1
9.2
9.3
9.3.1
9.3.2
9.4
10.1
10.2
10.3
11.1
11.2
11.3
12.1
8.Pybytes
8.1Introduction
8.2GettingStarted
8.3AddadevicetoPybytes
8.3.1ConnecttoPybytes:QuickAdd
8.3.2ConnecttoPybytes:FlashPybyteslibrarymanually
8.4Visualisedatafromyourdevice
9.DocumentationNotes
9.1Introduction
9.2Syntax
9.3REPLvsScripts
10.AdvancedTopics
10.1FirmwareDowngrade
10.2CLIUpdater
10.3SecureBootandEncryption
11.License
11.1License
7
PycomDocumentation
WelcometothePycomdocumentationsite.Thedocumentationissplitinto5sections;we
recommendreadingthroughallthesectionstofamiliariseyourselfwiththevarioustoolsand
featuresavailabletoyoutohelpyoudeveloponyourPycommodule.
Togetstarted,readthroughtheGettingStartedGuidethenfeelfreetojumpstraightintothe
tutorialsandexamplesinTutorials&Examplestobeginbuildingyourprojects.
Products
GettingStarted
Tutorials
Preface
8
GettingStarted
So,you'vedecidedtoorderaPycomdevelopmentmodule.Firstlywewouldliketo
congratulateyouinmakinganexcellentdecision.Ifyouhaven'tyetplacedyourorderwe
highlyrecommendyoucheckouttheproductspagebeforeyouplaceyourordertoensure
youknowwhichaccessoriesyoumightrequire.
Step1:Settingupthehardware
Inthefirstpartofthisgettingstartedguide,wewilltakeyouthroughsettingupyourdevice.
FirstlywewillcoverhowtoconnectthemoduletoyourcomputereitherviaUSBorWiFi.
SecondlywewillexplainhowtoconnectvariousaccessoriessuchasantennasorSIMcards
toyourmodule.
Step2:Settingupyourcomputer
Nowthatyourmoduleissuccessfullyconnected,youwillneedtoinstallsomesoftwareon
yourcomputertointerfacewithit.Thesecondpartofthisguidewillguideyouthrough
installingdrivers;performingfirmwareupdatesforyourmodule/accessoriestoensureyou
havethemoststableandfeaturepackedversion;andhowtosetupthesoftwareuseto
programthedevice.
1.0Introduction
15
Step3:Usingyourmodule
Nowthatyouhaveaconnectedmoduleandalltherequiredsoftwareinstalleditistimeto
beginprogrammingyourdevice.Thispartoftheguidewillgetyoustartedwithabasic
exampleandpointyouintherightdirectionforgettingyourdeviceconnectedtoyourchosen
network.
Step4:Connectingtoanetwork
Nowthatyoufamiliarwithprogrammingyourdeviceyouwillnodoubtbekeentogetit
connectedtooneoftheadvertisedwirelessnetworks.Thisusuallyrequiressome
registration.Thisstepwilldetailhowtogetregisteredandconnectedtovariouswireless
networks.
Youcannavigatethroughthisguideusingthearrowbuttonsontheleftandrightofthe
screen(oratthebottomifyouareusingmobile).
1.0Introduction
16
Settingupthehardware
ThischapterofthedocumentationwillshowyouhowtoconnectyouPycommodule.For
eachdevicetherearedetailedinstructionsonhowtoconnectyourmoduletooneofour
baseboards,aUSBUARTadapterorWiFiaswellaswhatantennasyoumightneedto
connect.Pleaseselectyourmodulebelowtobetakentotheappropriateguide.
1.1HardwareSetup
17
LoPy
Basicconnection
ExpBoard2.0
ExpBoard3.0
Pysense/Pytrack/Pyscan
USBUARTAdapter
WiFi
Lookfortheresetbuttononthemodule(locatedatacorneroftheboard,nexttothe
LED).
LocatetheUSBconnectorontheexpansionboard.
InserttheLoPymoduleonthetheexpansionboardwiththeresetbuttonpointing
towardstheUSBconnector.Itshouldfirmlyclickintoplaceandthepinsshouldnowno
longerbevisible.
BeforeconnectingyourmoduletoanExpansionBoard3.0,youshouldupdatethe
firmwareontheExpansionBoard3.0.Instructionsonhowtodothiscanbefoundhere.
Lookfortheresetbuttononthemodule(locatedatacorneroftheboard,nexttothe
LED).
1.1.1LoPy
20
LocatetheUSBconnectorontheexpansionboard.
InserttheLoPymoduleontheExpansionBoardwiththeresetbuttonpointingtowards
theUSBconnector.Itshouldfirmlyclickintoplaceandthepinsshouldnownolonger
bevisible.
BeforeconnectingyourmoduletoaPysense/Pytrack/Pyscanboard,youshouldupdate
thefirmwareonthePysense/Pytrack/Pyscan.Instructionsonhowtodothiscanbe
foundhere.
LookfortheresetbuttonontheLoPymodule(locatedatacorneroftheboard,nextto
theLED).
LocatetheUSBconnectoronthePysense/Pytrack/Pyscan.
InsertthemoduleonthePysense/Pytrack/Pyscanwiththeresetbuttonpointingtowards
theUSBconnector.Itshouldfirmlyclickintoplaceandthepinsshouldnownolonger
bevisible.
1.1.1LoPy
21
Onceyouhavecompletedtheabovestepssuccessfullyyoushouldseetheon-boardLED
blinkingblue.Thisindicatesthedeviceispoweredupandrunning.
FirstlyyouwillneedtoconnectpowertoyourLoPy.Youwillneedtosupply
3.5v-5.5vtothe Vinpin.Note:Donotfeed 3.3vdirectlytothe 3.3vsupplypin,
thiswilldamagetheregulator.
Theconnectthe RXand TXofyourUSBUARTtothe TXand RXoftheLoPy
respectively.Note:PleaseensureyouhavethesignalleveloftheUARTadaptersetto
3.3vbeforeconnectingit.
InordertoputtheLoPyintobootloadermodetoupdatethedevicefirmwareyouwill
needtoconnect P2to GND.Werecommendyouconnectabuttonbetweenthetwoto
makethissimpler.
Note:Thismethodofconnectionisnotrecommendedforfirsttimeusers.Itispossibleto
lockyourselfoutofthedevice,requiringaUSBconnection.
1.1.1LoPy
22
InordertoaccesstheLoPyviaWiFiyouonlyneedtoprovide 3.5v- 5.5vonthe
VinpinoftheLoPy:
Bydefault,whentheLoPyboots,itwillcreateaWiFiaccesspointwiththefollowing
credentials:
SSID: lopy-wlan
password: www.pycom.io
OnceconnectedtothisnetworkyouwillbeabletoaccessthetelnetandFTP
serversrunningontheLoPy.Forbothofthesethelogindetailsare:
username: micro
password: python
Antennas
LoRa
IfyouintendonusingtheLoRaconnectivityoftheLoPyyoumustconnectaLoRa
antennatoyourLoPybeforetryingtouseLoRaotherwiseyouriskdamagingthedevice.
1.1.1LoPy
23
TheLoPyonlysupportsLoRaonthe868MHzor915MHzbands.Itdoesnotsupport
433MHz.ForthisyouwillrequireaLoPy4.
FirstlyyouwillneedtoconnecttheU.FLtoSMApigtailtotheLoPyusingtheU.FL
connectoronthesamesideoftheLoPyastheLED.
Ifyouareusingapycase,youwillnextneedtoputtheSMAconnectorthroughthe
antennahole,ensuringyoualigntheflatedgecorrectly,andscrewdowntheconnector
usingtheprovidednut.
FinallyyouwillneedtoscrewontheantennatotheSMAconnector.
WiFi/Bluetooth(optional)
AllPycommodules,includingtheLoPy,comewithaon-boardWiFiantennaaswellasa
U.FLconnectorforanexternalantenna.Theexternalantennaisoptionalandonlyrequiredif
youneedbetterperformanceoraremountingtheLoPyinsuchawaythattheWiFisignalis
1.1.1LoPy
24
blocked.Switchingbetweentheantennasisdoneviasoftware,instructionsforthiscanbe
foundhere.
DeepSleepcurrentissue
TheLoPy,SiPy,andWiPy2.0experienceanissuewherethemodulesmaintainahigh
currentconsumptionindeepsleepmode.Thisissuehasbeenresolvedinallnewer
products.ThecauseforthisissueistheDCtoDCswitchmodeconverterremainsinahigh
performancemodeevenwhenthedeviceisindeepsleep.Theflashmemorychipalsodoes
notpowerdown.Amoredetailedexplanationcanbefoundhere.
1.1.1LoPy
25
LoPy4
Basicconnection
ExpBoard2.0
ExpBoard3.0
Pysense/Pytrack/Pyscan
USBUARTAdapter
WiFi
Lookfortheresetbuttononthemodule(locatedatacorneroftheboard,nexttothe
LED).
LocatetheUSBconnectorontheexpansionboard.
InserttheLoPy4moduleonthetheexpansionboardwiththeresetbuttonpointing
towardstheUSBconnector.Itshouldfirmlyclickintoplaceandthepinsshouldnowno
longerbevisible.
BeforeconnectingyourmoduletoanExpansionBoard3.0,youshouldupdatethe
firmwareontheExpansionBoard3.0.Instructionsonhowtodothiscanbefoundhere.
Lookfortheresetbuttononthemodule(locatedatacorneroftheboard,nexttothe
LED).
1.1.2LoPy4
26
LocatetheUSBconnectorontheexpansionboard.
InserttheLoPy4moduleontheExpansionBoardwiththeresetbuttonpointingtowards
theUSBconnector.Itshouldfirmlyclickintoplaceandthepinsshouldnownolonger
bevisible.
BeforeconnectingyourmoduletoaPysense/Pytrack/Pyscanboard,youshouldupdate
thefirmwareonthePysense/Pytrack/Pyscan.Instructionsonhowtodothiscanbe
foundhere.
LookfortheresetbuttonontheLoPy4module(locatedatacorneroftheboard,nextto
theLED).
LocatetheUSBconnectoronthePysense/Pytrack/Pyscan.
InsertthemoduleonthePysense/Pytrack/Pyscanwiththeresetbuttonpointingtowards
theUSBconnector.Itshouldfirmlyclickintoplaceandthepinsshouldnownolonger
bevisible.
1.1.2LoPy4
27
Onceyouhavecompletedtheabovestepssuccessfullyyoushouldseetheon-boardLED
blinkingblue.Thisindicatesthedeviceispoweredupandrunning.
FirstlyyouwillneedtoconnectpowertoyourLoPy4.Youwillneedtosupply
3.5v-5.5vtothe Vinpin.Note:Donotfeed 3.3vdirectlytothe 3.3vsupplypin,
thiswilldamagetheregulator.
Theconnectthe RXand TXofyourUSBUARTtothe TXand RXoftheLoPy4
respectively.Note:PleaseensureyouhavethesignalleveloftheUARTadaptersetto
3.3vbeforeconnectingit.
InordertoputtheLoPy4intobootloadermodetoupdatethedevicefirmwareyouwill
needtoconnect P2to GND.Werecommendyouconnectabuttonbetweenthetwoto
makethissimpler.
1.1.2LoPy4
28
Note:Thismethodofconnectionisnotrecommendedforfirsttimeusers.Itispossibleto
lockyourselfoutofthedevice,requiringaUSBconnection.
InordertoaccesstheLoPy4viaWiFiyouonlyneedtoprovide 3.5v- 5.5vonthe
VinpinoftheLoPy4:
Bydefault,whentheLoPy4boots,itwillcreateaWiFiaccesspointwiththefollowing
credentials:
SSID: lopy4-wlan
password: www.pycom.io
OnceconnectedtothisnetworkyouwillbeabletoaccessthetelnetandFTP
serversrunningontheLoPy4.Forbothofthesethelogindetailsare:
username: micro
password: python
Antennas
LoRa/Sigfox
IfyouintendonusingtheLoRa/SigfoxconnectivityoftheLoPy4youmustconnecta
LoRa/SigfoxantennatoyourLoPy4beforetryingtouseLoRa/Sigfoxotherwiseyourisk
damagingthedevice.
1.1.2LoPy4
29
FirstlyyouwillneedtoconnecttheU.FLtoSMApigtailtotheLoPy4usingoneofthe
twotheU.FLconnectorsonthesamesideoftheLoPy4astheLED.Theoneontheleft
handsideisfor433MHz(LoRaonly),theoneoftherighthandsideisfor
868MHz/915MHz(LoRa&Sigfox).Note:ThisisdifferentfromtheLoPy.
Ifyouareusingapycase,youwillnextneedtoputtheSMAconnectorthroughthe
antennahole,ensuringyoualigntheflatedgecorrectly,andscrewdowntheconnector
usingtheprovidednut.
FinallyyouwillneedtoscrewontheantennatotheSMAconnector.
WiFi/Bluetooth(optional)
1.1.2LoPy4
30
AllPycommodules,includingtheLoPy4,comewithaon-boardWiFiantennaaswellasa
U.FLconnectorforanexternalantenna.Theexternalantennaisoptionalandonlyrequiredif
youneedbetterperformanceoraremountingtheLoPy4insuchawaythattheWiFisignal
isblocked.Switchingbetweentheantennasisdoneviasoftware,instructionsforthiscanbe
foundhere.
1.1.2LoPy4
31
SiPy
Basicconnection
ExpBoard2.0
ExpBoard3.0
Pysense/Pytrack/Pyscan
USBUARTAdapter
WiFi
Lookfortheresetbuttononthemodule(locatedatacorneroftheboard,nexttothe
LED).
LocatetheUSBconnectorontheexpansionboard.
InserttheSiPymoduleonthetheexpansionboardwiththeresetbuttonpointing
towardstheUSBconnector.Itshouldfirmlyclickintoplaceandthepinsshouldnowno
longerbevisible.
BeforeconnectingyourmoduletoanExpansionBoard3.0,youshouldupdatethe
firmwareontheExpansionBoard3.0.Instructionsonhowtodothiscanbefoundhere.
Lookfortheresetbuttononthemodule(locatedatacorneroftheboard,nexttothe
LED).
1.1.1SiPy
32
LocatetheUSBconnectorontheexpansionboard.
InserttheSiPymoduleontheExpansionBoardwiththeresetbuttonpointingtowards
theUSBconnector.Itshouldfirmlyclickintoplaceandthepinsshouldnownolonger
bevisible.
BeforeconnectingyourmoduletoaPysense/Pytrack/Pyscanboard,youshouldupdate
thefirmwareonthePysense/Pytrack/Pyscan.Instructionsonhowtodothiscanbe
foundhere.
LookfortheresetbuttonontheSiPymodule(locatedatacorneroftheboard,nextto
theLED).
LocatetheUSBconnectoronthePysense/Pytrack/Pyscan.
InsertthemoduleonthePysense/Pytrack/Pyscanwiththeresetbuttonpointingtowards
theUSBconnector.Itshouldfirmlyclickintoplaceandthepinsshouldnownolonger
bevisible.
1.1.1SiPy
33
Onceyouhavecompletedtheabovestepssuccessfullyyoushouldseetheon-boardLED
blinkingblue.Thisindicatesthedeviceispoweredupandrunning.
FirstlyyouwillneedtoconnectpowertoyourSiPy.Youwillneedtosupply 3.5v-5.5v
tothe Vinpin.Note:Donotfeed 3.3vdirectlytothe 3.3vsupplypin,thiswill
damagetheregulator.
Theconnectthe RXand TXofyourUSBUARTtothe TXand RXoftheSiPy
respectively.Note:PleaseensureyouhavethesignalleveloftheUARTadaptersetto
3.3vbeforeconnectingit.
InordertoputtheSiPyintobootloadermodetoupdatethedevicefirmwareyouwill
needtoconnect P2to GND.Werecommendyouconnectabuttonbetweenthetwoto
makethissimpler.
Note:Thismethodofconnectionisnotrecommendedforfirsttimeusers.Itispossibleto
lockyourselfoutofthedevice,requiringaUSBconnection.
1.1.1SiPy
34
InordertoaccesstheSiPyviaWiFiyouonlyneedtoprovide 3.5v- 5.5vonthe
VinpinoftheSiPy:
Bydefault,whentheSiPyboots,itwillcreateaWiFiaccesspointwiththefollowing
credentials:
SSID: sipy-wlan
password: www.pycom.io
OnceconnectedtothisnetworkyouwillbeabletoaccessthetelnetandFTP
serversrunningontheSiPy.Forbothofthesethelogindetailsare:
username: micro
password: python
Antennas
Sigfox
IfyouintendonusingtheSigfoxconnectivityoftheSiPyyoumustconnectaSigfox
antennatoyourSiPybeforetryingtouseSigfoxotherwiseyouriskdamagingthe
device.
FirstlyyouwillneedtoconnecttheU.FLtoSMApigtailtotheSiPyusingtheU.FL
1.1.1SiPy
35
connectoronthesamesideoftheSiPyastheLED.
Ifyouareusingapycase,youwillnextneedtoputtheSMAconnectorthroughthe
antennahole,ensuringyoualigntheflatedgecorrectly,andscrewdowntheconnector
usingtheprovidednut.
FinallyyouwillneedtoscrewontheantennatotheSMAconnector.
WiFi/Bluetooth(optional)
AllPycommodules,includingtheSiPy,comewithaon-boardWiFiantennaaswellasa
U.FLconnectorforanexternalantenna.Theexternalantennaisoptionalandonlyrequiredif
youneedbetterperformanceoraremountingtheSiPyinsuchawaythattheWiFisignalis
blocked.Switchingbetweentheantennasisdoneviasoftware,instructionsforthiscanbe
foundhere.
1.1.1SiPy
36
DeepSleepcurrentissue
TheLoPy,SiPy,andWiPy2.0experienceanissuewherethemodulesmaintainahigh
currentconsumptionindeepsleepmode.Thisissuehasbeenresolvedinallnewer
products.ThecauseforthisissueistheDCtoDCswitchmodeconverterremainsinahigh
performancemodeevenwhenthedeviceisindeepsleep.Theflashmemorychipalsodoes
notpowerdown.Amoredetailedexplanationcanbefoundhere.
1.1.1SiPy
37
GPy
Basicconnection
ExpBoard2.0
ExpBoard3.0
Pysense/Pytrack/Pyscan
USBUARTAdapter
WiFi
Lookfortheresetbuttononthemodule(locatedatacorneroftheboard,nexttothe
LED).
LocatetheUSBconnectorontheexpansionboard.
InserttheGPymoduleonthetheexpansionboardwiththeresetbuttonpointing
towardstheUSBconnector.Itshouldfirmlyclickintoplaceandthepinsshouldnowno
longerbevisible.
BeforeconnectingyourmoduletoanExpansionBoard3.0,youshouldupdatethe
firmwareontheExpansionBoard3.0.Instructionsonhowtodothiscanbefoundhere.
Lookfortheresetbuttononthemodule(locatedatacorneroftheboard,nexttothe
LED).
1.1.1GPy
38
LocatetheUSBconnectorontheexpansionboard.
InserttheGPymoduleontheExpansionBoardwiththeresetbuttonpointingtowards
theUSBconnector.Itshouldfirmlyclickintoplaceandthepinsshouldnownolonger
bevisible.
BeforeconnectingyourmoduletoaPysense/Pytrack/Pyscanboard,youshouldupdate
thefirmwareonthePysense/Pytrack/Pyscan.Instructionsonhowtodothiscanbe
foundhere.
LookfortheresetbuttonontheGPymodule(locatedatacorneroftheboard,nextto
theLED).
LocatetheUSBconnectoronthePysense/Pytrack/Pyscan.
InsertthemoduleonthePysense/Pytrack/Pyscanwiththeresetbuttonpointingtowards
theUSBconnector.Itshouldfirmlyclickintoplaceandthepinsshouldnownolonger
bevisible.
1.1.1GPy
39
Onceyouhavecompletedtheabovestepssuccessfullyyoushouldseetheon-boardLED
blinkingblue.Thisindicatesthedeviceispoweredupandrunning.
FirstlyyouwillneedtoconnectpowertoyourGPy.Youwillneedtosupply 3.5v-5.5v
tothe Vinpin.Note:Donotfeed 3.3vdirectlytothe 3.3vsupplypin,thiswill
damagetheregulator.
Theconnectthe RXand TXofyourUSBUARTtothe TXand RXoftheGPy
respectively.Note:PleaseensureyouhavethesignalleveloftheUARTadaptersetto
3.3vbeforeconnectingit.
InordertoputtheGPyintobootloadermodetoupdatethedevicefirmwareyouwill
needtoconnect P2to GND.Werecommendyouconnectabuttonbetweenthetwoto
makethissimpler.
1.1.1GPy
40
Note:Thismethodofconnectionisnotrecommendedforfirsttimeusers.Itispossibleto
lockyourselfoutofthedevice,requiringaUSBconnection.
InordertoaccesstheGPyviaWiFiyouonlyneedtoprovide 3.5v- 5.5vonthe
VinpinoftheGPy:
Bydefault,whentheGPyboots,itwillcreateaWiFiaccesspointwiththefollowing
credentials:
SSID: gpy-wlan
password: www.pycom.io
OnceconnectedtothisnetworkyouwillbeabletoaccessthetelnetandFTP
serversrunningontheGPy.Forbothofthesethelogindetailsare:
username: micro
password: python
Antennas
LTECat-M1/NB-IoT
IfyouintendonusingtheLTECAT-M1orNB-IoTconnectivityoftheGPyyoumustconnect
aLTECAT-M1/NB-IoTantennatoyourGPybeforetryingtouseLTECat-M1orNB-IoT
otherwiseyouriskdamagingthedevice.
1.1.1GPy
41
YouwillneedtoconnecttheantennatotheGPyusingtheU.FLconnectoronthesame
sideoftheGPyastheLED.
WiFi/Bluetooth(optional)
AllPycommodules,includingtheGPy,comewithaon-boardWiFiantennaaswellasa
U.FLconnectorforanexternalantenna.Theexternalantennaisoptionalandonlyrequiredif
youneedbetterperformanceoraremountingtheGPyinsuchawaythattheWiFisignalis
blocked.Switchingbetweentheantennasisdoneviasoftware,instructionsforthiscanbe
foundhere.
1.1.1GPy
42
SIMcard
IfyouintendonusingtheLTECAT-M1orNB-IoTconnectivityoftheGPyyouwillneedto
insertaSIMcardintoyourGPy.ItshouldbenotedthattheGPydoesnotsupportregular
LTEconnectivityandyoumayrequireaspecialSIM.Itisbesttocontactyourlocalcellular
providersformoreinformationonacquiringaLTECAT-M1/NB-IoTenablednanoSIM.
1.1.1GPy
43
FiPy
Basicconnection
ExpBoard2.0
ExpBoard3.0
Pysense/Pytrack/Pyscan
USBUARTAdapter
WiFi
WhenusingtheexpansionboardwithaFiPy,youwillneedtoremovetheCTSandRTS
jumpersastheseinterferewithcommunicationwiththecellularmodem.
Lookfortheresetbuttononthemodule(locatedatacorneroftheboard,nexttothe
LED).
LocatetheUSBconnectorontheexpansionboard.
InserttheFiPymoduleonthetheexpansionboardwiththeresetbuttonpointing
towardstheUSBconnector.Itshouldfirmlyclickintoplaceandthepinsshouldnowno
longerbevisible.
BeforeconnectingyourmoduletoanExpansionBoard3.0,youshouldupdatethe
firmwareontheExpansionBoard3.0.Instructionsonhowtodothiscanbefoundhere.
1.1.1FiPy
44
WhenusingtheexpansionboardwithaFiPy,youwillneedtoremovetheCTSandRTS
jumpersastheseinterferewithcommunicationwiththecellularmodem.
Lookfortheresetbuttononthemodule(locatedatacorneroftheboard,nexttothe
LED).
LocatetheUSBconnectorontheexpansionboard.
InserttheFiPymoduleontheExpansionBoardwiththeresetbuttonpointingtowards
theUSBconnector.Itshouldfirmlyclickintoplaceandthepinsshouldnownolonger
bevisible.
BeforeconnectingyourmoduletoaPysense/Pytrack/Pyscanboard,youshouldupdate
thefirmwareonthePysense/Pytrack/Pyscan.Instructionsonhowtodothiscanbe
foundhere.
LookfortheresetbuttonontheFiPymodule(locatedatacorneroftheboard,nextto
theLED).
LocatetheUSBconnectoronthePysense/Pytrack/Pyscan.
InsertthemoduleonthePysense/Pytrack/Pyscanwiththeresetbuttonpointingtowards
theUSBconnector.Itshouldfirmlyclickintoplaceandthepinsshouldnownolonger
bevisible.
1.1.1FiPy
45
Onceyouhavecompletedtheabovestepssuccessfullyyoushouldseetheon-boardLED
blinkingblue.Thisindicatesthedeviceispoweredupandrunning.
FirstlyyouwillneedtoconnectpowertoyourFiPy.Youwillneedtosupply 3.5v-5.5v
tothe Vinpin.Note:Donotfeed 3.3vdirectlytothe 3.3vsupplypin,thiswill
damagetheregulator.
Theconnectthe RXand TXofyourUSBUARTtothe TXand RXoftheFiPy
respectively.Note:PleaseensureyouhavethesignalleveloftheUARTadaptersetto
3.3vbeforeconnectingit.
InordertoputtheFiPyintobootloadermodetoupdatethedevicefirmwareyouwill
needtoconnect P2to GND.Werecommendyouconnectabuttonbetweenthetwoto
makethissimpler.
Note:Thismethodofconnectionisnotrecommendedforfirsttimeusers.Itispossibleto
lockyourselfoutofthedevice,requiringaUSBconnection.
InordertoaccesstheFiPyviaWiFiyouonlyneedtoprovide 3.5v- 5.5vonthe
1.1.1FiPy
46
VinpinoftheFiPy:
Bydefault,whentheFiPyboots,itwillcreateaWiFiaccesspointwiththefollowing
credentials:
SSID: fipy-wlan
password: www.pycom.io
OnceconnectedtothisnetworkyouwillbeabletoaccessthetelnetandFTP
serversrunningontheFiPy.Forbothofthesethelogindetailsare:
username: micro
password: python
Antennas
LoRa/Sigfox
IfyouintendonusingtheLoRa/SigfoxconnectivityoftheFiPyyoumustconnecta
LoRa/SigfoxantennatoyourFiPybeforetryingtouseLoRa/Sigfoxotherwiseyourisk
damagingthedevice.
1.1.1FiPy
47
TheFiPyonlysupportsLoRaonthe868MHzor915MHzbands.Itdoesnotsupport
433MHz.ForthisyouwillrequireaLoPy4.
FirstlyyouwillneedtoconnecttheU.FLtoSMApigtailtotheFiPyusingtheU.FL
connectoronthesamesideoftheFiPyastheLED.
Ifyouareusingapycase,youwillnextneedtoputtheSMAconnectorthroughthe
antennahole,ensuringyoualigntheflatedgecorrectly,andscrewdowntheconnector
usingtheprovidednut.
FinallyyouwillneedtoscrewontheantennatotheSMAconnector.
LTECat-M1/NB-IoT
IfyouintendonusingtheLTECAT-M1orNB-IoTconnectivityoftheFiPyyoumustconnect
aLTECAT-M1/NB-IoTantennatoyourFiPybeforetryingtouseLTECat-M1orNB-IoT
otherwiseyouriskdamagingthedevice.
1.1.1FiPy
48
YouwillneedtoconnecttheantennatotheFiPyusingtheU.FLconnectorontheunder
sideoftheFiPy.
WiFi/Bluetooth(optional)
AllPycommodules,includingtheFiPy,comewithaon-boardWiFiantennaaswellasa
U.FLconnectorforanexternalantenna.Theexternalantennaisoptionalandonlyrequiredif
youneedbetterperformanceoraremountingtheFiPyinsuchawaythattheWiFisignalis
blocked.Switchingbetweentheantennasisdoneviasoftware,instructionsforthiscanbe
foundhere.
1.1.1FiPy
49
SIMcard
IfyouintendonusingtheLTECAT-M1orNB-IoTconnectivityoftheFiPyyouwillneedto
insertaSIMcardintoyourFiPy.ItshouldbenotedthattheFiPydoesnotsupportregular
LTEconnectivityandyoumayrequireaspecialSIM.Itisbesttocontactyourlocalcellular
providersformoreinformationonacquiringaLTECAT-M1/NB-IoTenablednanoSIM.
1.1.1FiPy
50
WiPy
Basicconnection
ExpBoard2.0
ExpBoard3.0
Pysense/Pytrack/Pyscan
USBUARTAdapter
WiFi
Lookfortheresetbuttononthemodule(locatedatacorneroftheboard,nexttothe
LED).
LocatetheUSBconnectorontheexpansionboard.
InserttheWiPymoduleonthetheexpansionboardwiththeresetbuttonpointing
towardstheUSBconnector.Itshouldfirmlyclickintoplaceandthepinsshouldnowno
longerbevisible.
BeforeconnectingyourmoduletoanExpansionBoard3.0,youshouldupdatethe
firmwareontheExpansionBoard3.0.Instructionsonhowtodothiscanbefoundhere.
Lookfortheresetbuttononthemodule(locatedatacorneroftheboard,nexttothe
LED).
1.1.1WiPy
51
LocatetheUSBconnectorontheexpansionboard.
InserttheWiPymoduleontheExpansionBoardwiththeresetbuttonpointingtowards
theUSBconnector.Itshouldfirmlyclickintoplaceandthepinsshouldnownolonger
bevisible.
BeforeconnectingyourmoduletoaPysense/Pytrack/Pyscanboard,youshouldupdate
thefirmwareonthePysense/Pytrack/Pyscan.Instructionsonhowtodothiscanbe
foundhere.
LookfortheresetbuttonontheWiPymodule(locatedatacorneroftheboard,nextto
theLED).
LocatetheUSBconnectoronthePysense/Pytrack/Pyscan.
InsertthemoduleonthePysense/Pytrack/Pyscanwiththeresetbuttonpointingtowards
theUSBconnector.Itshouldfirmlyclickintoplaceandthepinsshouldnownolonger
bevisible.
1.1.1WiPy
52
Onceyouhavecompletedtheabovestepssuccessfullyyoushouldseetheon-boardLED
blinkingblue.Thisindicatesthedeviceispoweredupandrunning.
FirstlyyouwillneedtoconnectpowertoyourWiPy.Youwillneedtosupply
3.5v-5.5vtothe Vinpin.Note:Donotfeed 3.3vdirectlytothe 3.3vsupplypin,
thiswilldamagetheregulator.
Theconnectthe RXand TXofyourUSBUARTtothe TXand RXoftheWiPy
respectively.Note:PleaseensureyouhavethesignalleveloftheUARTadaptersetto
3.3vbeforeconnectingit.
InordertoputtheWiPyintobootloadermodetoupdatethedevicefirmwareyouwill
needtoconnect P2to GND.Werecommendyouconnectabuttonbetweenthetwoto
makethissimpler.
Note:Thismethodofconnectionisnotrecommendedforfirsttimeusers.Itispossibleto
lockyourselfoutofthedevice,requiringaUSBconnection.
1.1.1WiPy
53
InordertoaccesstheWiPyviaWiFiyouonlyneedtoprovide 3.5v- 5.5vonthe
VinpinoftheWiPy:
Bydefault,whentheWiPyboots,itwillcreateaWiFiaccesspointwiththefollowing
credentials:
SSID: wipy-wlan
password: www.pycom.io
OnceconnectedtothisnetworkyouwillbeabletoaccessthetelnetandFTP
serversrunningontheWiPy.Forbothofthesethelogindetailsare:
username: micro
password: python
Antennas
WiFi/Bluetooth(optional)
AllPycommodules,includingtheWiPy,comewithaon-boardWiFiantennaaswellasa
U.FLconnectorforanexternalantenna.Theexternalantennaisoptionalandonlyrequiredif
youneedbetterperformanceoraremountingtheWiPyinsuchawaythattheWiFisignalis
blocked.Switchingbetweentheantennasisdoneviasoftware,instructionsforthiscanbe
foundhere.
1.1.1WiPy
54
DeepSleepcurrentissue
TheLoPy,SiPy,andWiPy2.0experienceanissuewherethemodulesmaintainahigh
currentconsumptionindeepsleepmode.Thisissuehasbeenresolvedinallnewer
products.ThecauseforthisissueistheDCtoDCswitchmodeconverterremainsinahigh
performancemodeevenwhenthedeviceisindeepsleep.Theflashmemorychipalsodoes
notpowerdown.Amoredetailedexplanationcanbefoundhere.
WiPy2.0vsWiPy3.0
TheWiPy3.0isanupgradedversionoftheWiPy2.0withthefollowingchanges:
TheFLASHhasbeenupgradedfrom4MBto8MB.
TheRAMhasbeenupgradedfrom512KBto4MB.
Thedeepsleepcurrentconsumptionissuehasbeenfixed
TheantennaselectpinhasmovedtoGPIO21(P12)
1.1.1WiPy
55
Settingupyourcomputer
Togetyouupandrunning,Pycomprovidesasuiteoftoolstoassistwithdevelopingand
programmingyourPycomDevices:
1. Drivers:IfyouareusingMicrosoftWindows,youmightberequiredtoinstalldriversfor
ourproductstofunctioncorrectly.
2. Pycomfirmwareupdateutility:Thistoolautomatestheprocessofupgradingthe
firmwareofyourPycomdevice.Itisimportantthatyouusethistoolbeforeyouattempt
touseyourdevice.Notonlytoensureyouhavethemoststableandfeaturepacked
firmware,butalsotoensureallthefunctionalityofyourdeviceisenable.E.g.thistool
alsoactivatesyourtwoyearfreesigfoxconnectivity.
3. DevelopmentEnvironment:Pymakrisaplug-inforAtomandVisualStudioCode
developedbyPycomtomakedevelopmentforPycommodulessupereasy.Itallows
youtouseyourfavouritetexteditorwhilesimplifyingtheprocessofuploadingcodeto
thedevice.
1.2Software
56
Drivers
Linux
YoushouldnotneedtoinstallanydriversforourdevicestoberecognisedbyLinux.You
mayhoweverneedtoadjustpermissionstomakesureyouhaveaccesstotheserialport.
Onmostdistributionsthiscanbedonebyaddingyourusertothe dialoutusergroup.
Pleasecheckthespecificinstructionsforyourlinuxdistributionforhowtodothis.
macOS
OnmacOSyoushouldn'tneedtodoanythingspecialtogetourdevicetowork.
Windows
AllourproductswillworkoutoftheboxforWindows8/10/+.IfusingWindows7,driversto
supportthePysense/Pytrack/Pyscan/ExpansionBoard3.0boardswillneedtobeinstalled.
Download
Pleasedownloadthedriversoftwarefromthelinkbelow.
Pysense/Pytrack/Pyscan/ExpansionBoard3.0SerialDriver
Installation
FirstnavigateopentheWindowsstartmenuandsearch/navigateto`DeviceManager.You
shouldseeyourPytrack/Pysenseinthedropdownunderotherdevices.
1.2.1Drivers
57
Rightclickthedeviceandselect UpdateDriverSoftware.
SelecttheoptiontoBrowsemycomputerfordriversoftware.
1.2.1Drivers
58
Nextyouwillneedtonavigatetowhereyoudownloadedthedriverto(e.g.Downloads
Folder).
Specifythefolderinwhichthedriversarecontained.Ifyouhaven'textractedthe .zipfile,
pleasedothisbeforeselectingthefolder.
1.2.1Drivers
59
Youmayreceiveawarning,suggestingthatWindowscan'tverifythepublisherofthisdriver.
Click Installthisdriversoftwareanywayasthislinkpointstoourofficialdriver.
Iftheinstallationwassuccessful,youshouldnowseeawindowspecifyingthatthedriver
wascorrectlyinstalled.
1.2.1Drivers
60
Toconfirmthattheinstallationwascorrect,navigatebacktothe DeviceManagerandclick
thedropdownforotherdevices.Thewarninglabelshouldnowbegoneand
Pytrack/Pysenseshouldbeinstalled.
1.2.1Drivers
61
FirmwareUpdateTools
Westronglyrecommendyoutoupgradeyourfirmwaretothelatestversionasweare
constantlymakingimprovementsandaddingnewfeaturestothedevices.
Herearethedownloadlinkstotheupdatetool.Pleasedownloadtheappropriateonefor
yourOSandfollowtheinstructionsonthescreen.
Windows
macOS(10.11orHigher)
Linux(requires dialogand python-serialpackage)
Previousversionsoffirmwareareavailablefordownloadhere.
UpdatingDeviceFirmware
Thebasicfirmwareupgradeprocedurecanbefoundbelow,pleasefollowthesesteps
carefully:
ExpansionBoard2.0
Pysense/Pytrack/Pyscan/ExpansionBoard3.0
1. Disconnectyourdevicefromyourcomputer
2. InsertmoduleintotheExpansionBoard
3. Connectajumpercableorwirebetween G23and GND
4. ReconnecttheboardviaUSBtoyourcomputer,thisputsthedevicein‘firmwareupdate
mode’.
5. RuntheFirmwareUpgradetool
1.2.2UpdatingFirmware
62
6. Removethe G23to GNDjumpercable/wire
7. Rebootthedevice(buttonorpoweroffthenon),yourdeviceisnowreadytouse
Ifyouarehavinganyissues,makesuretheTXandRXjumpersarepresentonyour
ExpansionBoard,asthejumperssometimescomelooseintheboxduringtransport.
Withoutthesejumpers,theupdaterwillfail.
WhenusingaPysense/Pytrack/Pyscan/ExpansionBoard3.0toupdateyourmoduleyouare
notrequiredtomakeaconnectionbetween G23and GND,the
Pysense/Pytrack/Pyscan/ExpansionBoard3.0willdothisautomatically.
1. BeforeconnectingyourmoduletoaPysense/Pytrackboard,youshouldupdatethe
firmwareonthePysense/Pytrack.Instructionsonhowtodothiscanbefoundhere.
2. Disconnectyourdevicefromyourcomputer
3. InsertmoduleintoExpansionBoard
4. ReconnecttheboardviaUSBtoyourcomputer
5. RuntheFirmwareUpgradetool
1.2.2UpdatingFirmware
63
6. DisconnecttheUSBcablefromtheboardandreconnectit,yourdeviceisnowreadyto
use
Afteryou’redonewithupgrading,youcanusethePymakrPluginstouploadandrun
programsinyourdevice.
1.2.2UpdatingFirmware
64
1.2.3Pymakr
66
Usingyourmodule
Nowthatyouhaveconnectedandupdatedyourpycommoduleandinstalledalltherequired
softwareonyourcomputer,wecanbeginprogrammingyourPycommodule.
IfthisisyourfirsttimeusingaPycommodulewehighlyrecommendyoureadthroughthe
followingpages:
IntroductiontoMicroPython:ThispagewillexplainwhatMicropythonisandits
relationtoPython.
MicroPythonExamples:WealsorecommendyoubrowsetheseshortMicroPython
examplestofamiliariseyourselfwithitssyntax.Thisisnotmeantasacomprehensive
guidetoMicroPythonprogrammingbutratherareferencetothosewhoalreadyknow
programming.Ifyouarenewtopython,orprogrammingalltogether,wehighly
recommendsearchingtheinternetforPythontutorials.Therearemanyverygood
tutorialsavailableforfreeandtheskillsyoulearnwillbeeasilytransferabletoour
platform.
YourfirstPymakrproject:OnceyouunderstandwhatMicroPythonis,thisguidewill
takeyouthroughsettingupyourfirstPymakrprojecttoblinktheon-boardRGBLED.
ThisguidewillexplainthestructureofaMicroPythonprojectaswellashowtouploadit
toyourmodule.
OnceyouarefamiliarwithMicroPythonandPymakr,therecommendedwayofuploading
codetoyourmodule,youcanexplorethepagesbelow.Thesewilldiscussingreaterdetail
thevariousmechanismsforrunningcodeonyourdeviceaswellashowtorecoveritif
somethinggoeswrong.
REPL:TheREPL(ReadEvaluatePrintLoop)isaninteractiveterminalthatallowsyou
totypeinandtestyourcodedirectlyonthedevice,justlikeinteractivepython
interpreter.ItcanbeaccessedviaUARTorTelnet.Thisisaccessedeasiestbyusing
Pymakrbutifyouwishtouseothertools,thispagewillexplainhow.
FTP:AllPycommodulesstartupwithaWiFiaccesspointenabled,andasimpleFTP
serverrunningonit.OnceconnectedtotheWiFinetwork,youcanuseFTPtotransfer
filesovertoyourdevicewirelessly.Thiscanbeveryusefulifyoudonothavephysical
accesstoyourdevice.
SafeBoot:Itispossiblethatsomecodeyouuploadtoyourmodulewillpreventyou
accessingtheREPLorFTPserver,preventingyoufromupdatingyourscripts.This
guidewilldetailhowtosafebootyourmoduleandhowtoremovetheoffendingscripts
1.3Programmingthemodules
67
fromit.
1.3Programmingthemodules
68
IntroductiontoMicroPython
OurboardsworkwithMicroPython;aPython3.5implementationthatisoptimisedtorunon
microcontrollers.Thisallowsformuchfasterandmoresimpledevelopmentprocessthan
usingC.
BootingintoMicroPython
Whenbooting,twofilesareexecutedautomatically:first boot.pyandthen main.py.These
areplacedinthe /flashfolderontheboard.Anyotherfilesorlibrariescanbeplacedhere
aswell,andcanbeincludedorusedfrom boot.pyor main.py.
Thefolderstructurein /flashlookslikethepicturebelow.Thefilescanbemanagedeither
usingFTPorusingthePymakrPlugin.
Tips&Tricks
MicropythonsharesmajorityofthesamesyntaxasPython3.5.Theintentionofthisdesign
istoprovidecompatibilityupwardsfromMicropythontoPython3.5,meaningthatcode
writtenforMicropythonshouldworkinasimilarmannerinPython3.5.Therearesomeminor
variationsandtheseshouldtakenviewedasimplementationdifferences.
1.3.1IntroductiontoMicroPython
69
MicropythonalsohasanumberofMicropythonspecificlibrariesforaccessinghardware
levelfeatures.SpecificsrelatingtothoselibrariescanbefoundintheFirmwareAPI
Referencesectionofthisdocumentation.
Micropython,unlikeC/C++orArduino,doesnotusebraces{}toindicateblocksof
codespecifiedforclassandfunctiondefinitionsorflowcontrol.Blocksofcodeare
denotedbylineindentation,whichisstrictlyenforced.
Thenumberofspacesintheindentationisvariablebutallstatementswithinablock
mustbeindentedthesameamount.
1.3.1IntroductiontoMicroPython
70
MicroPythonExamples
TogetyoustartedwithPython(MicroPython)syntax,we'veprovidedyouwithanumberof
codeexamples.
VariableAssignment
AswithPython3.5,variablescanbeassignedtoandreferenced.Belowisanexampleof
settingavariableequaltoastringandthenprintingittotheconsole.
variable="HelloWorld"
print(variable)
ConditionalStatements
Conditionalstatementsallowcontroloverwhichelementsofcoderundependingonspecific
cases.Theexamplebelowshowshowatemperaturesensormightbeimplementedincode.
temperature=15
target=10
iftemperature>target:
print("TooHigh!")
eliftemperature<target:
print("TooLow!")
else:
print("Justright!")
Loops(For&Whileloop)
Loopsareanotherimportantfeatureofanyprogramminglanguage.Thisallowsyoutocycle
yourcodeandrepeatfunctions/assignments/etc.
forloopsallowyoutocontrolhowmanytimesablockofcoderunsforwithinarange.
x=0
foryinrange(0,9):
x+=1
print(x)
1.3.2MicroPythonExamples
71
whileloopsaresimilarto forloops,howevertheyallowyoutorunaloopuntilaspecific
conditionalis true/false.Inthiscase,theloopchecksif xislessthan 9eachtimethe
looppasses.
x=0
whilex<9:
x+=1
print(x)
Functions
Functionsareblocksofcodethatarereferredtobyname.Datacanbepassedintoittobe
operatedon(i.e.theparameters)andcanoptionallyreturndata(thereturnvalue).Alldata
thatispassedtoafunctionisexplicitlypassed.
Thefunctionbelowtakestwonumbersandaddsthemtogether,outputtingtheresult.
defadd(number1,number2):
returnnumber1+number2
add(1,2)#expectaresultof3
Thenextfunctiontakesaninputnameandreturnsastringcontainingawelcomephrase.
defwelcome(name):
welcome_phrase="Hello,"+name+"!"
print(welcome_phrase)
welcome("Alex")#expect"Hello,Alex!"
DataStructures
Pythonhasanumberofdifferentdatastructuresforstoringandmanipulatingvariables.The
maindifference(regardingdatastructures)betweenCandPythonisthatPythonmanages
memoryforyou.Thismeansthere’snoneedtodeclarethesizesoflists,dictionaries,
strings,etc.
Lists
Adatastructurethatholdsanorderedcollection(sequence)ofitems.
1.3.2MicroPythonExamples
72
networks=['lora','sigfox','wifi','bluetooth','lte-m']
print(networks[2])#expect'wifi'
Dictionaries
Adictionaryislikeanaddress-bookwhereyoucanfindtheaddressorcontactdetailsofa
personbyknowingonlyhis/hername,i.e.keys(names)areassociatewithvalues(details).
address_book={'Alex':'2604CrosswindDrive','Joe':'1301HillviewDrive','Chris':'323
6GoldleafLane'}
print(address_book['Alex'])#expect'2604CrosswindDrive'
Tuple
Similartolistsbutareimmutable,i.e.youcannotmodifytuplesafterinstantiation.
pycom_devices=('wipy','lopy','sipy','gpy','fipy')
print(pycom_devices[0])#expect'wipy'
FormorePythonexamples,checkoutthesetutorials.Beawareoftheimplementation
differencesbetweenMicroPythonandPython3.5.
1.3.2MicroPythonExamples
73
YourFirstPymakrProject
ThisguidewilltakeyouthroughhowtosetupyourfirstprojectwithPymakrandmakethe
on-boardRGBLEDflashvariouscolours.
CreatingaprojectinPymakr
1. Firstlyyouwillneedtocreateanew,empty,directoryonyourcomputer.Forthis
examplewewillcreateonecalled RGB-Blink.
2. NextyouwillneedtoopeneitherAtomorVisualStudioCodedependingonwhichyou
setuppreviously.
3. Oncethetexteditorhasloadedyouwillneedtoclick File> Open,andopenthe
directoryyoucreatedinstep1
IfyouareusingAtom,itisimportanttocheckatthispointthatAtomhas
successfullyidentifiedtheproject.Thenameofthedirectoryyoucreatedinstep1
(RGB-Blinkinthiscase)shouldbeshowninthePymakrpanelikeso:
Ifthisisnotthecaseyoucanpress alt-ctrl-ronWindows/Linuxor ctrl-alt-
cmd-lonmacOS,inordertoreloadAtomandfixtheissue.
4. Nowthatyouhaveaprojectcreated,weneedtoaddsomefilestoit.Astandard
MicroPythonprojecthasthefollowingstructure:
RGB-Blink
|-lib
||-some_library.py
|-boot.py
|-main.py
boot.pyThisisthefirstscriptthatrunsonyourmodulewhenitturnson.Thisis
oftenusedtoconnectamoduleaaWiFinetworksothatTelnetandFTPcanbe
usedwithoutconnectingtotheWiFiAPcreatedbythemoduleandnotclutteringup
the main.pyfile.Asabeginneryoudonotneedtousea boot.py.
1.3.3YourfirstPymakrproject
74
main.pyThisscriptrunsdirectlyafter boot.pyandshouldcontainthemaincode
youwishtorunonyourdevice.
libItisoftenagoodideatosplitoutre-usablecodeintolibraries.Ifyouwantto
createoruselibrariescreatedbyothers,youwillneedtocreatea libdirectory
andputthelibraryfilesinthis.Itisimportantthatyouput .pyfilesdirectlyinto
libratherthancreatingadirectorytree.BydefaultMicroPythonwillnotdetect
anylibrarieswithinsub-directories.
Forthisexample,youwilljustneedtocreatea main.pyfile.
Nowthattheprojectstructureissetup,youmaywishtoconfigureprojectspecificsettingsfor
Pymakre.g.Whichserialporttouse.OnAtomyouneedtoclickthe ^buttononthe
Pymakrpane,thenclick ProjectSettings.OnVisualStudioCodeyouneedtoclickthe
Allcommandsbuttononthebottomofthewindows,thenclick Pymakr>ProjectSettings.
Thiscreatesafilecalled pymakr.confinsideyourprojectandpopulatesitwithdefault
settingscopiedoverfromyourglobalsettings.Adetailedexplanationofthesesettingscan
befoundhere.
Controllingtheon-boardLED
Nowthatyouhavesetupandconfiguredyourproject,wecanmoveontoprogrammingyour
module.Thefirstthingwewillneedtodoisimportsomelibrariesinordertointeractwiththe
on-boardLED.ThePycomfirmwarecomeswithalargeamountoflibrariesforstandard
functionalitybuilt-in.YoucanfindoutmoreabouttheseintheAPIdocumentation.Forthis
exampleyouwillneedtoopenthe main.pyfileandaddthefollowingcode:
importpycom
importtime
Thiswillimporttwolibraries, PycomwhichisresponsibleforPycomspecificfeatures,such
astheon-boardLEDand timewhichisastandardlibraryusedtiminganddelays.
YoumayhavenoticedthatwhenyoupowerupyourPycommodule,theon-boardLED
blinksblueonaregularbasis.This"heartbeat"isusedasawayofknowthatyourmodule
haspoweredupandstartedcorrectly.BeforewecanchangethecolourofthisLEDweneed
todisablethisheartbeat.Belowyourimportsyouwillneedtoaddthefollowing:
pycom.heartbeat(False)
1.3.3YourfirstPymakrproject
75
Nowit'stimetotestyourcode.OnthePymakrpane/bottomofthewindowyouwillseea
runbutton.(Ifyouhaven'tconnectedtoyourdeviceyet,youwillneedtodothatfirst).
Whenyouclicktherunbutton,thecodeinthecurrentlyopenfilewillbeexecutedonthe
device,butitwon'tcopyittothedevice.Afterrunningthiscode,youshouldseethatthaton-
boardLEDstopsblinkingblue.
NowthatwecanconfirmthedeviceisconnectedandPymakrisabletoruncodeonit,we
cancompleteourscripttoblinktheLEDlikeso:
importpycom
importtime
pycom.heartbeat(False)
whileTrue:
pycom.rgbled(0xFF0000)#Red
time.sleep(1)
pycom.rgbled(0x00FF00)#Green
time.sleep(1)
pycom.rgbled(0x0000FF)#Blue
time.sleep(1)
Onceyouruntheabovescript,itwillrunforever.Youwillnoticethispreventsyoufrom
accessingtheinteractiveREPLonthedevice(Youcannotseethe >>>prompt).Inorderto
stopthescript,clickontothePymakrterminal,andpress ctrl-conyourkeyboard.This
shouldstopthescriptrunningandreturnyoutotheinteractiveREPL.
Uploadingtoyourmodule
IntheprevioussectionwegotcoderunningononyourPycommoduleusingthe run
featureofPymakr.Thisisusefulforquicktestingbuthasacoupleofdrawbacks.Firstlythe
codedoesnotremainonthedevicepermanently.Ifyourebootthedevice,itwillnolonger
berunningyourcode.Secondly,itwillonlyworkifyouareusinglibrariesbuiltintothe
firmware.Ifyouneedanyextralibraries,theseneedtobecopiedtothedevicefirst.Thisis
wherethe uploadfeaturecomesin.Ifinsteadof runyouclick upload,Pymakrwill
uploadallthefilesintheproject(solongastheirtypeisinthe sync_file_typessettingfor
yourproject).Thesethenpersistonyourdeviceevenbetweenreboots,andallowsyouto
uselibrariesfromthe libfolderinyourproject.
Ifyouneedtoremovefilesfromyourdeviceyouhavetwooptions,eitherconnectviaFTP
andmanageyourfilesthatwayorformatthedevice'sinternalflashlikeso:
1.3.3YourfirstPymakrproject
76
importos
os.mkfs('/flash')
1.3.3YourfirstPymakrproject
77
REPL(ReadEvaluatePrintLoop)
REPLstandsforReadEvaluatePrintLoop,andisthenamegiventotheinteractive
MicroPythonpromptthatisaccessibleonthePycomdevices.UsingtheREPLisbyfarthe
easiestwaytotestoutPythoncodeandruncommands.YoucanusetheREPLinaddition
towritingscriptsin main.py.
ThefollowingpageswillexplainhowtousetheREPLwithbothSerialUSBandTelnet
connections.
TheREPLincludesthefollowingfeatures:
Inputhistory:usearrowupandarrowdowntoscrollthroughthehistory
Tabcompletion:presstabtoauto-completevariablesormodulenames
Haltanyexecutingcode:with Ctrl-C
Copy/pastecodeoroutput: Ctrl-Cand Ctrl-V
ThereareanumberofusefulshortcutsforinteractingwiththeMicroPythonREPL.See
belowforthekeycombinations;
Ctrl-AonablanklinewillenterrawREPLmode.Thisissimilartopermanent
pastemode,exceptthatcharactersarenotechoedback.
Ctrl-BonablanklikegoestonormalREPLmode.
Ctrl-Ccancelsanyinput,orinterruptsthecurrentlyrunningcode.
Ctrl-Donablanklinewilldoasoftreset.
Ctrl-Eenters‘pastemode’thatallowsyoutocopyandpastechunksoftext.Exit
thismodeusing Ctrl-D.
Ctrl-Fperformsa"safe-boot"ofthedevicethatprevents boot.pyand main.py
fromexecuting
1.3.4REPL
78
SerialUSBREPL(UART)
TousetheREPL,aPycomdevicemustbeconnectedtothehostcomputerwithaUSB
connectioneithertoanExpansionBoardortoserialconverter(adiagramofhowtodothis
canbefoundthethegettingstartedpageforyourmodule).
InordertoconnecttotheREPLoverUSBserial,therearemultiplemethods.Detailedbelow
aretheexplanationsofhowtodoitinMacOS,LinuxandWindows.
Allplatforms
ByfartheeasiestwaytoaccesstheUSBUARTREPLisviatheourPymakrplug-infor
AtomandVisualStudioCode.Thisaddsapanetothebottomoftheeditorsthatallowsyou
todirectlyaccesstheREPLandanyoutputfromthedevice.Detailedinstructionsonhowto
setupPymakrcanbefoundhere.
macOSandLinux
ToopenaserialUSBconnectionfrommacOS,anyserialtoolmaybeused;inthisexample,
theterminaltool screenwillbeused.
Openaterminalinstanceandrunthefollowingcommands:
$screen/dev/tty.usbmodem*115200
Uponexiting screen,press CTRL-ACTRL-\.Ifthekeyboarddoesnotsupportthe \-key
(i.e.anobscurecombinationfor \like ALT-SHIFT-7isrequired),thekeycombinationcan
beremappedforthe quitcommand:
create ~/.screenrc
addbind qtothe exitcommand
Thiswillallowscreentoexitedbypressing CTRL-AQ.
OnLinux, picocomor minicommaybeusedinsteadof screen.Theusbserial
addressmightalsobelistedas /dev/ttyUSB01orahigherincrementfor ttyUSB.
Additionally,theelevatedpermissionstoaccessthedevice(e.g.groupuucp/dialoutor
use sudo)mayberequired.
1.3.4.1SerialUSB
79
Windows
AterminalemulatorisneededtoopentheconnectionfromWindows;theeasiestoptionisto
downloadthefreeprogram,PuTTY.
COMPort
TousePuTTYtheserialport(COMport)inwhichthePycomdeviceisconnected,mustbe
located.InWindows,thisinformationcanbefoundfromthe'DeviceManager'program.
1. OpentheWindowsstartmenuandsearchfor'DeviceManager'
2. TheCOMportforthePycomdevicewillbelistedas'USBSerialDevice'orasimilar
name
3. Copy/WritedowntheassociatedCOMport(e.g. COM4)
UsingPutty
1. WithPuTTYopen,clickon Sessionintheleft-handpanel
2. Nextclickthe SerialradiobuttonontherightandentertheassociatedCOMport(e.g.
COM4)inthe SerialLinebox
3. Finally,clickthe Openbutton
1.3.4.1SerialUSB
80
TelnetREPL
Pycomdevicesalsosupportaconnectionvia telnet,usingthedevice'sonboard
WiFi/WLAN.Connecttothedevice'sWiFiAccessPoint(AP)andusingthefollowing
credentialstoconnecttotheAP.TheWiFi SSIDwillappearuponpoweringonaPycom
Deviceforthefirsttime(e.g. lopy-).Tore-enablethisfeatureatalaterdate,pleasesee
network.WLAN.
password: www.pycom.io
TelnetServer
Additionally,tousetheMircoPythonREPLovertelnet,furtherauthenticationisrequired.The
defaultcredentialsforthetelnetserverare:
username: micro
password: python
Seenetwork.serverforinfoonhowtochangethedefaultauthentication.
Allplatforms
ByfartheeasiestwaytoaccesstheTelnetREPLisviatheourPymakrplug-inforAtomand
VisualStudioCode.Thisaddsapanetothebottomoftheeditorsthatallowsyoutodirectly
accesstheREPLandanyoutputfromthedevice.Detailedinstructionsonhowtosetup
Pymakrcanbefoundhere.
macOSandLinux
OncethehostmachineisconnectedtothePycomdevice'sAccessPoint,atelnet
connectionmaybeopenedfromaterminalinstance.
$telnet192.168.4.1
Uponconnection,thetelnetprogramwillpromptforthe usernameand passwordinthe
sectionabove.
Windows
1.3.4.2Telnet
81
AterminalemulatorisneededtoopenatelnetconnectionfromWindows;theeasiestoption
istodownloadthefreeprogram,PuTTY.
1. WithPuTTYopen,selecttelnetasconnectiontypeandleavethedefaultport( 23)
2. NextentertheIPaddressofthePycomdevice(e.g. 192.168.4.1)
3. Finallyclick Open
WhenusingaPycomdevicewithapersonal,homeorofficeWiFiaccesspoint,the
telnetconnectionmaystillbeused.Inthisinstance,theuserwillneedtodeterminethe
Pycomdevice'slocalIPaddressandsubstitutethisfor 192.168.4.1,referredtointhe
earliersections.
1.3.4.2Telnet
82
FTP(LocalFileSystem)
ThereisasmallinternalfilesystemaccessiblewitheachPycomdevice,called /flash.
Thisisstoredwithintheexternalserialflashmemory.IfamicroSDcardisalsoconnected
andmounted,itwillbeavailableaswell.Whenthedevicestartsup,itwillalwaysbootfrom
the boot.pylocatedinthe /flashfilesystem.
ThefilesystemisaccessibleviathenativeFTPserverrunningoneachPycomdevice.
OpenanFTPclientandconnectto:
url: ftp://192.168.4.1
username: micro
password: python
Seenetwork.serverforinformationonhowtochangethedefaults.Therecommendedclients
are:
macOS/Linux:defaultFTPclient
Windows:FilezillaandFireFTP
Forexample,fromamacOS/Linuxterminal:
$ftp192.168.4.1
TheFTPserverdoesn’tsupportactivemode,onlypassivemode.Therefore,ifusingthe
nativeunixFTPclient,immediatelyafterloggingin,runthefollowingcommand:
ftp>passive
TheFTPserveronlysupportsoneconnectionatatime.IfusingotherFTPclients,please
checktheirdocumentationforhowtolimitthemaximumallowedconnectionstooneata
time.
FileZilla
IfusingFileZilla,it'simportanttoconfigurethesettingscorrectly.
Donotusethequickconnectbutton.Instead,openthesitemanagerandcreateanew
configuration.Withinthe Generaltab,ensurethatencryptionissetto: OnlyuseplainFTP
(insecure).
1.3.5FTP
83
Inthe TransferSettingstab,limitthemaxnumberofconnectionstoone.OtherFTPclients
maybehaveinasimilarways;visittheirdocumentationformorespecificinformation.
1.3.5FTP
84
BootModes
Ifpoweringupnormallyoruponpressingtheresetbutton,aPycommodulewillbootinto
standardmode;the boot.pyfilewillbeexecutedfirst,followedby main.py.Itispossibleto
alterthebootprocedureofthemodulebytyingcertainpins highor lowwhenthemodule
boots.
Bootloader
Ifyouupdatedyourdevicebeforeusingit,youhavealreadyputthedeviceintobootloader
mode.Thisisachievedbyconnecting G23to GNDwhilethedeviceboots.Ifyouuseda
Pysense/Pytracktoupdate,itdidthisautomaticallyforyou.Youonlyneedtoputyour
Pycommoduleintobootloadermodeifyouareupdatingitsfirmware,orareprogramming
yourownlowlevelcode.ThisisnotrequiredifyouareupdatingyourMicroPythoncode.
SafeBoot
SometimesthecodeyouhavewrittenwillpreventyougainingaccesstotheREPLor
preventyouupdatingyourcode.Someexamplemaybe:
YoudisabledtheWiFi/UART
YourcodegetsstuckbeforereachingtheREPL
Yousetasocketasblockingbutneverreceiveanydata
Inordertofixthisyoucansafebootyourmodule.Thiswillprevent boot.pyand main.py
frombeingexecutedandwilldropyoustraightintotheinteractiveREPL.Afterreset,if P12
pinisheld high(i.e.connectittothe 3V3outputpin),theheartbeatLEDwillbegin
flashingorangeslowly.Ifafter3secondsthepinisstillheldhigh,theLEDwillstartblinking
faster.Inthismodethemodulewilldothesameaspreviouslyexplainedbutitwillalsoselect
thepreviousOTAimagetobootifyouhaveupdatedthemoduleviatheOTAupdate
procedure(updatesperformedviathefirmwareupdatetooldonotcount).Thisisusefulif
youflashedaOTAupdatethatbreaksthedevice.
Pin P12releasedduring:
1st3secswindow 2nd3secswindow
Disable boot.pyand main.py sameaspreviousbutusingpreviousOTAfirmware
Theselectionmadeduringsafebootisnotpersistent,thereforeafterthenextnormalreset,
thelatestfirmwarewillproceedtorunagain.
1.3.6Safeboot
85
Ifproblemsoccurwithinthefilesystemoryouwishtofactoryresetyourmoduletoremove
yourcode,runfollowingcodeintheREPL:
>>>importos
>>>os.mkfs('/flash')
Beaware,resettingtheflashfilesystemwilldeleteallfilesinsidetheinternaldevice
storage(nottheSDcard)andtheycannotberecovered.
Reset
Pycomdevicessupportbothsoftandhardresets.Asoftresetclearsthestateofthe
MicroPythonvirtualmachinebutleaveshardwareperipheralsunaffected.Todoasoftreset,
press Ctrl+DontheREPLorfromwithinascript,run:
>>>importsys
>>>sys.exit()
Ahardresetisthesameasperformingapowercycletothedevice.Inordertohardreset
thedevice,pressthe resetswitchorrun:
>>>importmachine
>>>machine.reset()
1.3.6Safeboot
86
RegisteringaPycomDevice
Someofourdevicesrequireregistrationbeforeyoucanutilisespecificfeaturessuchas
certaintypesofnetworking.Pleaseseethelistbelowforsetupguidestoensurethatyour
deviceisregisteredandactivatedonthevariousplatformsrequiredtoaccessallofthe
availablefeatures.
NotallPycomdevicesrequireactivation;mostfeaturesworkimmediatelyoutofthe
box!
1.4DeviceRegistration
87
RegisteringwithSigfox
ToensurethedevicehasbeenprovisionedwithDeviceIDandPACnumber,pleaseupdate
tothelatestfirmware.
InordertosendaSigfoxmessage,thedeviceneedtoregisterwiththeSigfoxBackend.
Navigatetohttps://backend.sigfox.com/activatetofindthelistofSigfoxenabled
developmentkits.
Select Pycomtoproceed.
NextchooseaSigfoxOperatorforthecountrywherethedevicewillbeactivated.Findthe
specificcountryandselecttheoperatortocontinue.
1.4.1Sigfox
88
Nowneedtoenterthedevice'sDeviceIDandPACnumber.
TheDeviceIDandPACnumberareretrievablethroughacoupleofcommandsviathe
REPL.
fromnetworkimportSigfox
importbinascii
#initaliseSigfoxforRCZ1(YoumayneedadifferentRCZRegion)
sigfox=Sigfox(mode=Sigfox.SIGFOX,rcz=Sigfox.RCZ1)
#printSigfoxDeviceID
print(binascii.hexlify(sigfox.id()))
#printSigfoxPACnumber
print(binascii.hexlify(sigfox.pac()))
See SigfoxformoreinfoabouttheSigfoxClassandwhichRCZregiontouse.
1.4.1Sigfox
89
Oncethedevice'sDeviceIDandPACnumberhavebeenentered,createanaccount.
Providetherequiredinformationincludingemailaddressandclicktocontinue.
AnemailconfirmingthecreationofaSigfoxBackendaccountandthesuccessful
registrationofthedeviceshouldarriveattheusersinbox.
1.4.1Sigfox
90
Cellularregistration
InordertouseyourGPy/FiPyonacellularnetworkyouarerequiredtogetaSIMcardfrom
alocalprovider.Note:ThismightdifferfromastandardSIMyoucanbuyinastore,our
devicesdonotsupportstandardLTE.
CurrentlywearenotabletoprovideanyspecificdetailsabouthowtogetsuchaSIMcard
andhowtoregisteritasmostdeploymentsareclosedtrials,eachcarrierhasit’sownrules
(forexample,whethertheyrequirespecialSIMsornot).
WerecommendcontactingyourlocalcellularproviderstochecktheirplanssurroundingLTE
CAT-M1andNB-IoT.Bycontactingthem,youwillshowthecarriersthatthereislocal
interestindeployingsuchnetworks.
Youcanfindamapofdeployednetworksandopenlabshere.
1.4.2Cellular
91
LoRaWANRegistration
RawLoRa
WhenusingrawLoRa,youdonothavetoregisteryourmoduleinanyway.Themodules
cantalktoeachotherdirectly.
LoRaWAN
InordertoconnectyourLoRacapablePycommoduletoaLoRaWANnetworkyouwillhave
toregisteryourdevicewiththedesirednetwork.Weareunabletoprovideinstructionsforall
LoRaWANnetworksbutbelowyouwillfindsomegenericinstructions,alongwithlinkstoany
specificguidesweareawareof.
Genericinstructions
Firstlyyouwillneedtogetyourmodules DeviceEUI,thiscanbeachievedusingthe
followingcode:
fromnetworkimportLoRa
importubinascii
lora=LoRa(mode=LoRa.LORAWAN)
print(ubinascii.hexlify(lora.mac()).upper().decode('utf-8'))
Theoutputwillbeahexstringlike: 70B3D5499585FCA1.Onceyouhavethisyouwillneedto
provideittoyourLoRaWANnetworkwhichwillthenprovideyouwiththedetailsneedto
connectviaOver-the-AirActivation(OTAA)orActivationbyPersonalisation(ABP)
OTAA
IfyouwishtoconnectviaOTAA(whichistherecommendedmethod)thenetworkwill
provideyouwithan ApplicationEUIand ApplicationKey.Theformeridentifieswhat
applicationyourdeviceisconnectingto,thelatterisasharedsecretkeyuniquetoyour
devicetogeneratethesessionkeysthatproveitsidentitytothenetwork.Onceyouhave
theseyoucanusetheLoRaWANOTAAexamplecodetoconnecttothenetwork.
ABP
1.4.3LoRaWAN
92
WithABPtheencryptionkeysenablingcommunicationwiththenetworkarepreconfiguredin
thedevice.Thenetworkwillneedtoprovideyouwitha DeviceAddress, NetworkSession
Keyand ApplicationSessionKey.OnceyouhavetheseyoucanusetheLoRaWANABP
examplecodetoconnecttothenetwork.
Networks
1.4.3LoRaWAN
93
TheThingsNetwork
InordertouseTheThingsNetwork(TTN)youshouldnavigatetotheirwebsiteand
create/registeranaccount.Enterausernameandanemailaddresstoverifywiththeir
platform.
Onceanaccounthasbeenregistered,youcanregisteryourPycommoduleaseitheranode
oranano-gateway.Thestepsbelowwilldetailhowtodothis.
Createanapplication
Inordertoregisteryourdevicetoconnecttothethingsnetwork,youmustfirstcreatean
applicationforthesedevicestobelongto.ThiswaytheNetworkwillknowwheretosendthe
devicesdatato.
1.4.3.2TheThingsNetwork
95
Selectingthe ApplicationstabatthetopoftheTTNconsole,willbringupascreenfor
registeringapplications.Clickregisterandanewpage,similartotheonebelow,willopen.
Enteraunique ApplicationIDaswellasaDescription&HandlerRegistration.
NowthePycommodulenodescanberegisteredtosenddatauptothenewApplication.
RegisteraDevice
Toconnectnodestoathingsnetworkgateway,devicesneedtobeaddedtotheapplication.
Todothis,navigatetothe Devicestabonthe Applicationhomepageandclickthe
RegisterDevicebutton.
Inthe RegisterDevicepanel,completetheformsforthe DeviceIDandthe DeviceEUI.
The DeviceIDisuserspecifiedandisuniquetothedeviceinthisapplication.The Device
EUIshouldbeagloballyuniqueidentifierforthedevice.Youcanrunthefollowingonyou
PycommoduletoretrieveitsEUI.
1.4.3.2TheThingsNetwork
96
fromnetworkimportLoRa
importubinascii
lora=LoRa()
print("DevEUI:%s"%(ubinascii.hexlify(lora.mac()).decode('ascii')))
Oncethedevicehasbeenadded,changethe ActivationMethodbetween OTAAand ABP
dependingonuserpreference.Thisoptioncanbefoundunderthe Settingstab.
RegisteraNano-Gateway
YoucanalsosetupyourPycommoduletoactasagatewaywithTheThingsNetwork.The
coderequiredtodothiscanbefoundhere.
InsidetheTTNConsole,therearetwooptions, Applicationsand Gateways.Select
Gatewaysandthenclickon registerGateway.Thiswillallowforthesetupandregistration
ofanewnano-gateway.
OntheRegisterGatewaypage,youwillneedtosetthefollowingsettings:
1.4.3.2TheThingsNetwork
97
Theseareuniquetoeachgateway,locationandcountryspecificfrequency.Pleaseverify
thatcorrectsettingsareselectedotherwisethegatewaywillnotconnecttoTTN.
Youneedtotickthe"I'musingthelegacypacketforwarder"toenabletheright
settings.ThisisbecausetheNano-Gatewayusesthe'defacto'standardSemtechUDP
protocol.
Option Value
Protocol PacketForwarder
GatewayEUI UserDefined(mustmatch config.py)
Description UserDefined
FrequencyPlan SelectCountry(e.g.EU-868MHz)
Location UserDefined
AntennaPlacement IndoororOutdoor
MostLoRaWANnetworkserversexpectaGatewayIDintheformofaunique64-bit
hexadecimalnumber(calledaEUI-64).TherecommendedpracticeistoproducethisID
fromyourboardbyexpandingtheWiFiMACaddress(a48-bitnumber,calledMAC-48).You
canobtainthatbyrunningthiscodepriortoconfiguration:
1.4.3.2TheThingsNetwork
98
fromnetworkimportWLAN
importbinascii
wl=WLAN()
binascii.hexlify(wl.mac())[:6]+'FFFE'+binascii.hexlify(wl.mac())[6:]
Oncethesesettingshavebeenapplied,click RegisterGateway.AGatewayOverviewpage
willappear,withtheconfigurationsettingsshowing.Nextclickonthe GatewaySettingsand
configuretheRouteraddresstomatchthatofthegateway(default:
router.eu.thethings.network).
The Gatewayshouldnowbeconfigured.
1.4.3.2TheThingsNetwork
99
ConnectingtoObjeniousLoRaWAN'Spot'
network
Identifiers
ToconnectaPycomLoRadevice(LoPy,LoPy4,FiPy)toObjeniousyou'llneedtoprovision
it.Thisrequiresthreepiecesofinformation
DeviceEUI(DevEUI)
ApplicationEUI(AppEUI)
ApplicationKey(AppKey)
DeviceEUI
Thiscomesfromthedeviceitselfandcanbeobtainedfrom lora.mac().
Toobtaintherequiredhexadecimalrepresentationyoucanrunthefollowingcodeonyour
LoPy:
fromnetworkimportLoRa
importubinascii
lora=LoRa()
print("DevEUI:%s"%(ubinascii.hexlify(lora.mac()).decode('ascii')))
ApplicationEUIandApplicationKey
ApplicationEUIandKeyaretwoLoRaWANparametersthatshouldideallybygeneratedby
you,ifsupplyingdevicestoendcustomers.
TheApplicationEUIisaEUI-64(8bytes)identifierwhichshouldbeuniversallyunique-it's
usuallyallocatedfromaMA-SblockpurchasedfromtheIEEERegistrationAuthority.
TheApplicationKeyshouldbearandomlygenerated,secure,128bit(16byte)token.
FortestingpurposesweprovideascriptwhichgeneratesarandomApplicationEUIfromour
assignmentandaseriesofApplicationKeys:
EUI/Keygeneratorfortesting
(note:theApplicationEUIproducedbythisscriptisnotguaranteedtobeunique)
1.4.3.2Objenious
100
TousethescriptmakesureyouareusingPython3.6onyourcomputerandrunit(onyour
computer,notonthePycomboard)as:
pythongenerate_keys.py1
Theoutputwillbesimilarto:
AppEUI:70b3d54923e36a89
AppKeys:
78fe712d96f46784a98b574a8cd616fe
IfyouareregisteringmultipledevicesyoucangeneratemoreApplicationsKeysbychanging
1toyourdesirednumberofdevices.
Provisioning
Onceyouhavethethreeidentifiersforyourdeviceyouneedtoregisterthemonthe
Objeniusportal.
Follow"Importerdescapteurs"under"StatucdoParc"andselect"ProvisioningUnitaire":
OncetheregiveyourdeviceanameandentertheDevEUI,AppEUIandAppKeyobtained
fromthestepsabove:
1.4.3.2Objenious
101
1.4.3.2Objenious
102
2.1Installation
104
PymakrPluginInstallationforAtom
Forbeginners,usersgettingstartedwithMicroPython&PycomaswellasAtomtexteditor
users,werecommendthePymakrPluginforAtom.Thissectionwillhelpyougetstarted
usingtheAtomTextEditor&PymakrPlugin.
PleasefollowthesestepstoinstallthePymakrPlugin:
1. EnsurethatyouhaveAtominstalledandopen.
2. NavigatetotheInstallpage,via Atom>Preferences>Install
2.1.1Atom
105
3. Searchfor PymakrandselecttheofficialPycomPymakrPlugin.
4. YoushouldnowseeandclicktheInstallbutton.Thiswilldownloadandinstallthe
PymakrPlugin.
5. That’sit!You’veinstalledthePymakrPluginforAtom.
2.1.1Atom
106
ConnectingviaSerialUSB
AfterinstallingthePymakrPlugin,youneedtotakeafewsecondstoconfigureitforfirst
timeuse.Pleasefollowthesesteps:
1. ConnectyourPycomdevicetoyourcomputerviaUSB.IfyouareusinganExpansion
Board2.0,andhavejustfinishedafirmwareupgrade,besuretoremovethewire
betweenGNDandG23andresetyourdevicebypressingthebutton.Note:youdon't
needthewireforExpansionBoard3.0
2. OpenAtomandensurethatthePymakrPluginhascorrectlyinstalled.
3. OpenthePymakrconsolebyclickingthe ^button,locatedinthelowerrightsideof
theAtomwindow.
4. Click, Morefollowedby GetSerialPorts.Thiswillcopytheserialaddressofyour
expansionboardtoyourclipboard.
2.1.1Atom
107
5. Navigateto Settings>GlobalSettings
6. Pastetheserialaddressyoucopiedearlierintothetextfield DeviceAddress
7. PressconnectandthePymakrconsoleshouldshowthreearrows >>>,indicatingthat
youareconnected
2.1.1Atom
108
Thesesettingscanalsobeappliedonaperprojectbasisbyclicking Settingsthen
ProjectSettings.ThiswillopenaJSONfilewhichyoucanedittoenteryourdesired
settings.
ThisprocessiseasiestwitheitheraPycomExpansionBoardoraPytrack/Pysenseas
theaddressesareautomaticallyselected.ForexternalproductssuchasFTDIUSB
SerialCables,theserialaddressmayneedtobecopiedmanually.Additionally,thereset
buttononthedevicemayalsoneedtobepressedbeforeaconnectionmessage
appears.
ConnectingviaTelnet
AfterinstallingthePymakrPlugin,adevicemaybeconnectedviathetelnetinterface.
Pleaseseethefollowingsteps:
1. EnsurethatPycomdeviceisturnedon
2. ConnectthehostcomputertotheWiFiAccessPointnamedafteryourboard(theSSID
willbeasfollowse.g. lopy-wlan-xxxx, wipy-wlan-xxxx,etc.).Thepasswordis
www.pycom.io.
3. Followthestepsasaboveinthe"ConnectingviaSerialUSB"sectionbutenter
192.168.4.1astheaddress.
4. Thedefaultusernameandpasswordare microand python,respectively.
5. Click ConnectinthePymakrpane,Pymakrwillnowconnectviatelnet.
2.1.1Atom
109
2.1.1Atom
110
PymakrPluginInstallationforVisual
StudioCode
PycomalsosupportsMicrosoft'sVisualStudioCodeIDEplatformwiththePymakrPlugin.To
downloadVisualStudioCode,navigatetoVSCode.
YouwillalsoneedNodeJSinstalledonyourPC.PleasedownloadthelatestLTSversion
availablefromtheNodeJSwebsite.
PleasefollowthesestepstoinstallthePymakrVSCodeExtension:
1. EnsurethatyouhaveVSCodeinstalledandopen.
2. NavigatetotheExtensionspage,usingthe5thbuttonintheleftnavigation
3. Searchfor Pymakrandclicktheinstallbuttonnexttoit.
2.1.2VisualStudioCode
111
4. Withinafewminutes,areloadbuttonshouldappear.PressittoreloadVSCode.
2.1.2VisualStudioCode
112
5. That’sit!You’veinstalledthePymakrExtensionforVSCode
2.1.2VisualStudioCode
113
ConnectingviaSerialUSB
AfterinstallingthePymakrPlugin,youneedtotakeafewsecondstoconfigureitforfirst
timeuse.Pleasefollowthesesteps:
1. ConnectyourPycomdevicetoyourcomputerviaUSB.Ifyouareusinganexpansion
board,andhavejustfinishedafirmwareupgrade,besuretoRemovethewire
betweenGNDandG23andresetyourdevicebypressingthebutton.
2. OpenVisualStudioCodeandensurethatthePymakrPluginhascorrectlyinstalled.
3. Click AllcommandsonthebottomoftheVisualStudioCodewindow
4. Inthelistthatappears,click Pymakr>Extra>ListSerialPorts
5. Thiswilllisttheavailableserialports.IfPymakrisabletoauto-detectwhichtouse,this
willbecopiedtoyourclipboard.Ifnotpleasemanuallycopythecorrectserialport.
6. Onceagainclick Allcommands,thenclick Pymakr>GlobalSettings.Thiswillopena
JSONfile.Pastetheserialaddressyoucopiedearlierintothefield addressandsave
thefile.
2.1.2VisualStudioCode
114
7. FinallyclosetheJSONfile,click Allcommands,then Pymakr>Connecttoconnectyour
device.ThePymakrconsoleshouldshowthreearrows >>>,indicatingthatyouare
connected
Thesesettingscanalsobeappliedonaperprojectbasisbyclicking Allcommandsthen
Pymakr>ProjectSettings.ThiswillopenaJSONfilewhichyoucanedittoenteryour
desiredsettingsforthecurrentlyopenproject.
ThisprocessiseasiestwitheitheraPycomExpansionBoardoraPytrack/Pysenseas
theaddressesareautomaticallyselected.ForexternalproductssuchasFTDIUSB
SerialCables,theserialaddressmayneedtobecopiedmanually.Additionally,thereset
buttononthedevicemayalsoneedtobepressedbeforeaconnectionmessage
appears.
ConnectingviaTelnet
AfterinstallingthePymakrPlugin,adevicemaybeconnectedviathetelnetinterface.
Pleaseseethefollowingsteps:
1. EnsurethatPycomdeviceisturnedon
2. ConnectthehostcomputertotheWiFiAccessPointnamedafteryourboard(theSSID
willbeasfollowse.g. lopy-wlan-xxxx, wipy-wlan-xxxx,etc.).Thepasswordis
www.pycom.io.
3. Followthestepsasaboveinthe"ConnectingviaSerialUSB"sectionbutenter
192.168.4.1astheaddress.
2.1.2VisualStudioCode
115
4. Thedefaultusernameandpasswordare microand python,respectively.
5. FinallyclosetheJSONfile,click Allcommands,then Pymakr>Connect,Pymakrwill
nowconnectviatelnet.
2.1.2VisualStudioCode
116
ToolsandFeatures
Console(REPL)
MicroPythonhasaninteractivecodetoolknownastheREPL(ReadEvaluatePrintLine).
TheREPLallowsyoutoruncodeonyourdevice,linebyline.Tobegincoding,gotothe
PymakrPluginConsoleandstarttypingyourcode.StartbymakingtheLEDchangecolour.
importpycom#weneedthismoduletocontroltheLED
pycom.heartbeat(False)#disabletheblueblinking
pycom.rgbled(0x00ff00)#maketheLEDlightupgreenincolour
YoucanchangethecolourbyadjustingthehexRGBvalue.
pycom.rgbled(0xff0000)#nowmaketheLEDlightupredincolour
Theconsolecanbeusedtorunanypythoncode,alsofunctionsorloops.
Use print()tooutputcontentsofvariablestotheconsoleforyoutoread.Returnedvalues
fromfunctionswillalsobedisplayediftheyarenotcaughtinavariable.Thiswillnothappen
forcoderunningfromthemainorbootfiles.Hereyouneedtouse print()tooutputtothe
console.
Notethatafterwritingorpastinganyindentedcodelikeafunctionorawhileloop,the
userwillhavetopressenteruptothreetimestotellMicroPythonthecodeistobe
closed(thisisstandardMicroPython&Pythonbehaviour).
AlsobeawarethatcodewrittenintotheREPLisnotsavedafterthedeviceispowered
off/onagain.
Run
Totestcodeonadevice,createanew .pyfileoropenanexistingone,typethedesired
code,savethefileandthenpressthe Runbutton.Thiswillrunthecodedirectlyontothe
PycomboardandoutputtheresultsofthescripttotheREPL.
2.2Tools/Features
117
Changesmadetofileswon’tbeautomaticallyuploadedtotheboarduponrestartingor
exitingthe Runfeature,asthePycomboardwillnotstorethiscode.Inordertopush
thecodepermanentlytoadevice,usethe Uploadfeature.
Projects
PymakrPluginsupportsuserprojects,allowingforpre-configuredsettingssuchasdefault
serialaddress/credentials,filestobeignoredandfolderstosync.
pymakr.conf
PymakrPluginsupportslocalprojectsettingsusingafilecalled pymakr.conf.Thiscanbe
usedtostorethedefaultserialaddressofadevice,whichfilestoignoreandothersettings.
Anexample pymakr.confisshownbelow:
{
"address":"/dev/cu.usbserial-AB001234",
"username":"micro",
"password":"python",
"sync_folder":"scripts"
}
Upload
ThePymakrPluginshaveafeaturetosyncanduploadcodetoadevice.Thiscanbeused
forbothuploadingcodetoadeviceaswellastestingoutscriptsbyrunningthemliveonthe
device.Thefollowingstepsdemonstratehowtousethisfeature.
Tostartusingthe Uploadfeature,ensurethataprojectfolderhasbeencreatedforthe
device.Forexample,ifusingthe pymakr.conffromabove,thisprojectfoldershouldbe
named scripts.Thisfoldershouldhavethefollowingstructure:
Libraryfilesshouldbeplacedintothe libfolder,certificatesintothe certfolderandso
on.The Uploadbuttonwilltakethehighestlevelfolder(currentlyopen)anduploadthisto
theconnectedPycomdevice.Thefileswillbepushedtothedeviceinexactlythesame
2.2Tools/Features
118
structureaswithinthecodeeditor'sfiledirectory.
More
Clickingthe MorebuttonwithinthePymakrPluginallowsforsomeadditionalfeatures.See
theoptionsbelowforspecificfunctionality.
GetFirmwareVersion
RetrievesthefirmwareversionofthePycomdeviceconnectedtothePymakrPlugin
instance.
GetWiFiAPSSID
RetrievesthedefaultWiFiAccessPointSSIDofthePycomdeviceconnectedtothePymakr
Plugininstance.
GetSerialPorts
RetrievesthevariousserialportsthatareavailabletothePymakrPlugininstance.
2.2Tools/Features
119
Pymakrsettings
BelowyouwillfindadescriptionofthevarioussettingsavailableforPymakr.
address
ThisistheaddressofthePycommoduleyouwantPymakrcanconnectto.Thiscanbe
eitheraserialport(e.g COM1onwindowsor /dev/cu.usbserial-DQ0054ESonLinux/macOS)
oranIPaddress(Telnet)(e.g. 192.168.4.1ifconnectedtotheAPcreatedbythePycom
module).
username
IfaIPaddresswasprovidedforthe addressthereforePymakrisconnectingviaTelnet,you
willalsoneedtoprovideausername,thedefaultis micro.
password
IfanIPaddresswasprovidedfortheaddress,PymakrisconnectingviaTelnet.Youwillalso
needtoprovideapassword,thedefaultis python.
sync_folder
Ifleftblank,alldirectoriesinsidetheprojectwillbesyncedtothedevicewhentheuserclicks
upload.Ifdirectoriesarespecified,onlythesedirectorieswillbesynced,allotherswillbe
ignored
open_on_start
Ifsetto true,thePymakrconsolewillopenandtrytoconnectwhentheeditorisstarted,or
aprojectisopened.
safe_boot_on_upload
2.3Settings
120
Ifsetto true,Pymakrwillreboottheconnecteddeviceintosafe-modebeforeuploading.
ThisisusefulifyourcodeusesalotofRAMcausingissueswiththeuploadprocedure.
Thisfeatureisonlyavailableonmodulesrunningfirmwareversion 1.17.0.b1orhigher.
sync_file_types
Onlyfilesendingwiththeextensionslistedinthissettingwillbesyncedtothedevicewhen
performinganupload.Allotherfilesareignored.Bydefaultthisissettoinclude: py,txt,
log,json,xml
ctrl_c_on_connect
Ifsetto true,Pymakrwillsentthe ctrl-csignaltotheconnectedmodulebefore
uploading.Thisshouldstopthescriptcurrentlyrunningonthedeviceandimprovethe
reliabilityoftheuploadprocess.
2.3Settings
121
Pytrack&Pysense
InadditiontotheExpansionBoard,Pycomalsoofferstwoadditionalsensorboards,which
areidealforquicklybuildingafullyfunctioningIoTsolution!Whethertheapplicationis
environmentsensingorassettracking,theseadditionalboardssupportavarietyofsensors.
Pytrack
PytrackisalocationenabledversionoftheExpansionBoard,intendedforuseinGPS
applicationssuchasassettrackingormonitoring.
Features&Hardware
ThePytrackishasanumberoffeaturesincludingGPS,3-AxisAccelerometerandBattery
Charger.Seethelistbelowfordetailedspecificsabouteachsensor,includingdatasheets.
SerialUSB
3-AxisAccelerometer(LIS2HH12)
BatteryCharger(BQ24040withJSTconnector)
GPSandGLONASS(L76-L)
MicroSDCardReader
AlloftheincludedsensorsareconnectedtothePycomdeviceviatheI2Cinterface.These
pinsarelocatedatP22(SDA)andP21(SCL).
Pysense
3.1Introduction
122
PysenseisasensorpackedversionoftheExpansionBoard,intendedforusein
environmentsensingapplicationssuchastemperature,humiditymonitoring,andlight
sensing.
Features&Hardware
ThePysenseispackedwithanumberofsensorsandhardware,seethelistbelowfor
detailedspecificsabouteachsensor,includingdatasheets.
SerialUSB
3-AxisAccelerometer(LIS2HH12)
BatteryCharger(BQ24040withJSTconnector)
DigitalAmbientLightSensor(LTR-329ALS-01)
HumidityandTemperatureSensor(SI7006-A20)
BarometricPressureSensorwithAltimeter(MPL3115A2)
MicroSDCardReader
AlloftheincludedsensorsareconnectedtothePycomdeviceviatheI2Cinterface.These
pinsarelocatedat GPI09(SDA)and GPI08(SCL).
3.1Introduction
123
InstallingSoftware
Asthedevelopmentforthesedevicesareongoingwithadditionalfeaturesbeingadded,
everyweek,itisessentialtoensureyoufrequentlycheckforupdatesonthe
Pytrack/Pysense.Aswellasupdatingthedevicefirmware,itisimportanttocheckthe
GitHubrepositoryfortherespectivelibraryfilesastheyasalsobeingupdated,toinclude
additionalfeatures/functionality.
3.2InstallingSoftware
124
UpdatingFirmware
ToupdatethefirmwareonthePysense/Pytrack/Pyscan/ExpansionBoardv3,pleaseseethe
followinginstructions.ThefirmwareofPysense/Pytrack/Pyscan/ExpansionBoardv3canbe
updatedviatheUSBportusingtheterminaltool, DFU-util.
ThelatestfirmwareDFUfilecanbedownloadedfromthelinksbelow:
PytrackDFU
PysenseDFU
ExpansionBoardDFU
Whileinthenormal,applicationmode,thePysense/Pytrack/Pyscan/ExpansionBoardv3
requireaSerialUSBCDCdriver,inDFU,bootloadermode,theDFUdriverisrequired.
Below,theUSBProductIDisdepictedforeachcase.
Board DFUbootloader(update
mode)
Applicationfirmware(normal
mode)
Pytrack 0xF014 0xF013
Pysense 0xF011 0xF012
Pyscan 0xEF37 0xEF38
ExpansionBoard
v3 0xEF99 0xEF98
Note:USBVendorIDisalways 0x04D8.
InstallingtheDFU-utilTools
macOS
Ifusing homebrew:
$brewinstalldfu-util
Ifusing MacPorts:
portinstalllibusbdfu-util
Linux
3.2.1UpdatingFirmware
125
UbuntuorDebian:
$sudoapt-getinstalldfu-util
Fedora:
$sudoyuminstalldfu-util
Arch:
$sudopacman-Sydfu-util
Windows
DFU-utilv0.9–TooltouploadthefirmwaretothePytrack/Pysense
Zadig–InstallertoolforthePytrack/PysenseboardDFUFirmware
TouploadedthelatestDFUfirmwaretothePytrack/Pysense,firstinstalltheDFUdrivers
tothehostcomputer.OpenZadigandselect libusbKasthedriver.
Toinstallthedrivers,thePytrack/PysenseboardmustbeinDFU-mode:
1. DisconnecttheUSBcable
2. Holddownthebuttonontheshield
3. ConnecttheUSBcable
4. Keepthebuttonpressedforatleastonesecond
5. Releasethebutton.WhentheboardisconnectedinDFU-mode,itwillbeinthisstate
for7seconds.
6. Clickthe “InstallDriverbuttonimmediately.Ifthedriverwasunsuccessful,repeat
fromstep1.
HeretheUSBIDhastobetheDFU-bootloaderone( 0xF014forPytrackor 0xF011
forPysense).
ThisisasuccessfulDFUdriverinstallationforPytrack:
3.2.1UpdatingFirmware
126
OpenthecommandpromptandnavigatetothedirectorywheretheDFU-utilandthe
firmwarewasdownloaded(mustbeinsamedirectory).Repeattheproceduretogetthe
boardinDFU-modeandrunthecommandbelowbutreplace X.X.Xwiththefirmware
versionandreplacePysensewithPytrackifitisthePytrackthatistobeupdated(e.g:
pytrack_0.0.8.dfu):
dfu-util-static.exe-Dpysense_X.X.X.dfu
Iftheupdatewassuccessful,amessage,"Done!"shouldappearinthebottomofthe
commandprompt.
Double-checkSerialUSB(CDC)driverisinstalledinApplicationmode:if,bymistake,
the libusbkdriverwasinstalledwhiletheUSBIDistheApplicationmode( 0xF013for
Pytrackor 0xF012forPysense),thenthe SerialUSB(CDC)driverhastobeinstalledfor
applicationmode.ThiswillallowWindowstoallocateaCOMport,whichisrequiredfor
REPLconsole.
3.2.1UpdatingFirmware
127
UsingDFU-utilwithPytrack,PysenseandExpansionBoard
v3
Toenterupdatemodefollowthesesteps:
1. Unplugthedevice
2. Pressthebuttonandkeepitheld(ontheExpansionBoardthe S1button)
3. PlugintheUSBcabletothehostcomputerandwait1secondbeforereleasingthe
button
4. Afterthisyouwillhaveapproximately7secondstoruntheDFU-utiltool
MacOSandLinux:
$dfu-util-Dpytrack_0.0.8.dfu
Anoutput,similartotheonebelow,willappearuponsuccessfulinstallation:
3.2.1UpdatingFirmware
128
dfu-util0.9
Copyright2005-2009WestonSchmidt,HaraldWelteandOpenMokoInc.
Copyright2010-2016TormodVoldenandStefanSchmidt
ThisprogramisFreeSoftwareandhasABSOLUTELYNOWARRANTY
Pleasereportbugstohttp://sourceforge.net/p/dfu-util/tickets/
MatchvendorIDfromfile:04d8
MatchproductIDfromfile:f014
OpeningDFUcapableUSBdevice...
ID04d8:f014
Run-timedeviceDFUversion0100
ClaimingUSBDFURuntimeInterface...
Determiningdevicestatus:state=dfuIDLE,status=0
dfu-util:WARNING:RuntimedevicealreadyinDFUstate?!?
ClaimingUSBDFUInterface...
SettingAlternateSetting#0...
Determiningdevicestatus:state=dfuIDLE,status=0
dfuIDLE,continuing
DFUmodedeviceDFUversion0100
Devicereturnedtransfersize64
CopyingdatafromPCtoDFUdevice
Download[=========================]100%16384bytes
Downloaddone.
state(2)=dfuIDLE,status(0)=Noerrorconditionispresent
Done!
Debugging
Using lsusbcommand,thePytrack/Pysensedeviceshouldbevisibleinbothnormaland
bootloadermodes.
Forexemple,aPytrackboardisvisibleaseither:
Bus020Device004:ID04d8:f014MicrochipTechnologyInc.ApplicationSpecific
Device
thisisbootloadermode( f014isUSBPID),activejustfor7-8seconds,ifthereset
buttonwasjustpressedbeforepluggingUSBconnector.
Bus020Device005:ID04d8:f013MicrochipTechnologyInc.PytrackSerial:Pyabcde0
thisisnormal,applicationmode( f013isUSBPID),thismeansthebootloader
verifiedapplicationpartitionanditboot-upcorrectly.
3.2.1UpdatingFirmware
129
Windows7Drivers
PytrackandPysensewillworkoutoftheboxforWindows8/10/+,macOSaswellasLinux.
IfusingWindows7,driverstosupporttheboardswillneedtobeinstalled.
Pleasefollowtheinstructionsbelowtoinstalltherequireddrivers.
Download
Pleasedownloadthedriversoftwarefromthelinkbelow.
Pytrack/Pysense/Pyscan/Expansionboard3Driver
Installation
FirstnavigateopentheWindowsstartmenuandsearch/navigateto DeviceManager.You
shouldseeyourPytrack/Pysenseinthedropdownunderotherdevices.
Rightclickthedeviceandselect UpdateDriverSoftware.
3.2.2InstallingDrivers-Windows7
130
SelecttheoptiontoBrowsemycomputerfordriversoftware.
Nextyouwillneedtonavigatetowhereyoudownloadedthedriverto(e.g.Downloads
Folder).
3.2.2InstallingDrivers-Windows7
131
Specifythefolderinwhichthedriversarecontained.Ifyouhaven'textractedthe .zipfile,
pleasedothisbeforeselectingthefolder.
Youmayreceiveawarning,suggestingthatwindowscan'tverifythepublisherofthisdriver.
Click Installthisdriversoftwareanywayasthislinkpointstoourofficialdriver.
3.2.2InstallingDrivers-Windows7
132
Iftheinstallationwassuccessful,youshouldnowseeawindowspecifyingthatthedriver
wascorrectlyinstalled.
Toconfirmthattheinstallationwascorrect,navigatebacktothe DeviceManagerandclick
thedropdownforotherdevices.Thewarninglabelshouldnowbegoneand
Pytrack/Pysenseshouldbeinstalled.
3.2.2InstallingDrivers-Windows7
133
3.2.2InstallingDrivers-Windows7
134
InstallingLibraries
ToutilisethesensorsonthePytrackandPysense,Pycomhaswrittenlibrariestomake
readingto/fromthevarioussensorsaccessibleviaanAPI.Theselibrariesresideatthe
PycomGitHubrepositoryandthelatestversionscanbefoundunderthereleasespage.
GitHubRepository
Downloadtherepositoryasa .zipfile,navigatetothecorrectdevice(Pysense/Pytrack),
extractthefilesandthenuploadthedesiredfilestothedeviceintheinstructionsbelow.
UploadingtheLibrariestoaDevice
Theselibrariesshouldbeuploadedtoadevice(LoPy,SiPy,WiPy2.0,etc.)inthesame
processasastandardMicroPythonlibrary.Thevarious .pyfilesshouldbeplacedintothe
/libfolderonthedevice.Forexample,ifusingthePysenseandtheuserwishestoenable
theonlyAccelerometerandtheLightSensor,theyshouldplacethefollowing .pyfilesinto
thedevice's /libfolder:
-pysense.py
-LIS2HH12.py
-LTR329ALS01.py
Addasmanyorasfewofthelibrariesthatarerequired.
InadditiontothePysenseorPytrackspecificlibraries,youalsoneedtouploadthe
pycoproc.pyfilefromthe _lib/pycoproc_folderinsidethelibrariesarchive.
ThePytrackandPysenseboardsbehavethesameastheExpansionBoard. Upload,
RunanduploadcodetoPycommodulesviathePymakrPlugin,inexactlythesame
process.
Importing/UsingtheLibraries
Oncethelibrariesareuploadedtothedevice,theycanbeused/importedasatypical
MicroPythonlibrarywouldbe.Forexample,importingandusingthelightsensoronthe
Pysense:
3.2.3InstallingLibraries
135
frompysenseimportPysense
fromLTR329ALS01importLTR329ALS01
py=Pysense()
lt=LTR329ALS01(py)
print(lt.light())
3.2.3InstallingLibraries
136
PytrackAPI
ThischapterdescribesthevariouslibrarieswhicharedesignedforthePytrackboard.This
includesdetailsaboutthevariousmethodsandclassesavailableforeachofthePytrack’s
sensors.
3-AxisAccelerometer(LIS2HH12)
Pytrackhasa3-AxisAccelerometerthatprovidesoutputsforaccelerationaswellasroll,
pitchandyaw.
Constructors
classLIS2HH12(pytrack=None,sda='P22',scl='P21')
Createsa LIS2HH12object,thatwillreturnvaluesforacceleration,roll,pitchandyaw.
ConstructormustbepassedaPytrackorI2Cobjecttosuccessfullyconstruct.
Methods
LIS2HH12.acceleration()
Readtheaccelerationfromthe LIS2HH12.Returnsatuplewiththe3valuesofacceleration
(G).
LIS2HH12.roll()
Readthecurrentrollfromthe LIS2HH12.Returnsafloatindegreesintherange-180to
180.
LIS2HH12.pitch()
Readthecurrentpitchfromthe LIS2HH12.Returnsafloatindegreesintherange-90to90.
Oncetheboardtiltsbeyondthisrangethevalueswillrepeat.Thisisduetoalackofyaw
measurement,makingitnotpossibletoknowtheexactorientationoftheboard.
GPSwithGLONASS(QuectelL76-LGNSS)
PytrackhasaGPS(withGLONASS)thatprovidesoutputslongitude/latitude,speedand
otherinformationaboutthePytrack'slocation.
3.3.1Pytrack
138
Constructors
classL76GNSS(pytrack=None,sda='P22',scl='P21',timeout=None)
Createsa L76GNSSobject,thatwillreturnvaluesforlongitudeandlatitude.Constructormust
bepassedaPytrackorI2Cobjecttosuccessfullyconstruct.Setthe timeouttoatime
period(inseconds)fortheGPStosearchforalock.Ifalockisnotfoundbythetimethe
timeouthasexpired,the coordinatesmethodwillreturn (None,None).
Methods
L76GNSS.coordinates(debug=False)
Readthelongitudeandlatitudefromthe L76GNSS.Returnsatuplewiththelongitudeand
latitude.With debugsetto TruetheoutputfromtheGPSisverbose.
Pleasenotethatmorefunctionalityisbeingaddedweeklytotheselibraries.Ifarequired
featureisnotavailable,feelfreetocontributewithapullrequestattheLibrariesGitHub
repository
3.3.1Pytrack
139
PysenseAPI
ThischapterdescribesthevariouslibrarieswhicharedesignedforthePysenseBoard.This
includesdetailsaboutthevariousmethodsandclassesavailableforeachofthePysense’s
sensors.
3-AxisAccelerometer(LIS2HH12)
Pysensehasa3-AxisAccelerometerthatprovidesoutputsforaccelerationaswellasroll,
pitchandyaw.
Constructors
classLIS2HH12(pysense=None,sda='P22',scl='P21')
Createsa LIS2HH12object,thatwillreturnvaluesforacceleration,roll,pitchandyaw.
ConstructormustbepassedaPysenseorI2Cobjecttosuccessfullyconstruct.
Methods
LIS2HH12.acceleration()
Readtheaccelerationfromthe LIS2HH12.Returnsatuplewiththe3valuesofacceleration
(G).
LIS2HH12.roll()
Readthecurrentrollfromthe LIS2HH12.Returnsafloatindegreesintherange-180to
180.
LIS2HH12.pitch()
Readthecurrentpitchfromthe LIS2HH12.Returnsafloatindegreesintherange-90to90.
Oncetheboardtiltsbeyondthisrangethevalueswillrepeat.Thisisduetoalackofyaw
measurement,makingitnotpossibletoknowtheexactorientationoftheboard.
DigitalAmbientLightSensor(LTR-329ALS-01)
Pysensehasaduallightsensorthatprovidesoutputsforexternallightlevelsinlux.Seethe
datasheetformoreinformationaboutthewavelengthsofthetwosensors.
3.3.2Pysense
140
Constructors
classLTR329ALS01(pysense=None,sda='P22',scl='P21',gain=ALS_GAIN_1X,
integration=ALS_INT_100,rate=ALS_RATE_500)
Createsa LTR329ALS01object,thatwillreturnvaluesforlightinlux.Constructormustbe
passedaPysenseorI2Cobjecttosuccessfullyconstruct.
Methods
LTR329ALS01.light()
Readthelightlevelsofboth LTR329ALS01sensors.Returnsatuplewithtwovaluesforlight
levelsinlux.
Arguments
Thefollowingargumentsmaybepassedintotheconstructor.
gain
ALS_GAIN_1X,ALS_GAIN_2X,ALS_GAIN_4X,ALS_GAIN_8X,ALS_GAIN_48X,
ALS_GAIN_96X
integration
ALS_INT_50,ALS_INT_100,ALS_INT_150,ALS_INT_200,ALS_INT_250,ALS_INT_300,
ALS_INT_350,ALS_INT_400
rate
ALS_RATE_50,ALS_RATE_100,ALS_RATE_200,ALS_RATE_500,ALS_RATE_1000,
ALS_RATE_2000
HumidityandTemperatureSensor(SI7006A20)
PysensehasaHumidityandTemperaturesensorthatprovidesvaluesofrelativehumidity
andexternaltemperature.
Constructors
classSI7006A20(pysense=None,sda='P22',scl='P21')
Createsa SI7006A20object,thatwillreturnvaluesforhumidity(%)andtemperature('C).
ConstructormustbepassedaPysenseorI2Cobjecttosuccessfullyconstruct.
3.3.2Pysense
141
Methods
SI7006A20.humidity()
Readtherelativehumidityofthe SI7006A20.Returnsafloatwiththepercentagerelative
humidity.
SI7006A20.temperature()
Readtheexternaltemperatureofthe SI7006A20.Returnsafloatwiththetemperature.
BarometricPressureSensorwithAltimeter(MPL3115A2)
PysensehasaBarometricPressuresensorthatprovidesreadingsforpressure,altitudeas
wellasanadditionaltemperaturesensor.
Constructors
classMPL3115A2(pysense=None,sda='P22',scl='P21',mode=PRESSURE)
Createsa MPL3115A2object,thatwillreturnvaluesforpressure(Pa),altitude(m)and
temperature('C).ConstructormustbepassedaPysenseorI2Cobjecttosuccessfully
construct.
Methods
MPL3115A2.pressure()
Readtheatmosphericpressureofthe MPL3115A2.Returnsafloatwiththepressurein(Pa).
MPL3115A2.altitude()
Readthealtitudeofthe MPL3115A2.Returnsafloatwiththealtitudein(m).
MPL3115A2.temperature()
Readthetemperatureofthe MPL3115A2.Returnsafloatwiththetemperaturein('C).
Arguments
Thefollowingargumentsmaybepassedintotheconstructor.
mode
3.3.2Pysense
142
SleepandWakeupforPytrack/Pysense
API
Thischapterdescribesthevariousmethodsforsleepandwakeupwhichareembeddedin
PytrackandPysenselibraries.BothPytrackandPysensehavethesamemethods,although
theappropriateclass,either pytrackor pysense,hastobeinstantiated.
QuickUsageExample
ThefollowingexampleisalsoavailableatSleepWakeupExampleLibrariesGitHub
repository
3.3.3Sleep
144
#frompytrackimportPytrack
frompysenseimportPysense
fromLIS2HH12importLIS2HH12
importtime
#py=Pytrack()
py=Pysense()
#displaytheresetreasoncodeandthesleepremaininginseconds
#possiblevaluesofwakeupreasonare:
#WAKE_REASON_ACCELEROMETER=1
#WAKE_REASON_PUSH_BUTTON=2
#WAKE_REASON_TIMER=4
#WAKE_REASON_INT_PIN=8
print("Wakeupreason:"+str(py.get_wake_reason()))
print("Approximatesleepremaining:"+str(py.get_sleep_remaining())+"sec")
time.sleep(0.5)
#enablewakeupsourcefromINTpin
py.setup_int_pin_wake_up(False)
acc=LIS2HH12()
#enableactivityandalsoinactivityinterrupts,usingthedefaultcallbackhandler
py.setup_int_wake_up(True,True)
#settheaccelerationthresholdto2000mG(2G)andthemindurationto200ms
acc.enable_activity_interrupt(2000,200)
#gotosleepfor5minutesmaximumifnoaccelerometerinterrupthappens
py.setup_sleep(300)
py.go_to_sleep()
Methods
pytrack.get_sleep_remaining()
Intheeventofasleepsessionthatwasawokenbyanasynchronousevent(Accelerometer,
INTpinorResetbutton)theapproximatesleepremaininginterval(expressedinseconds)
canbefoundout.Theuserhastomanuallyuse setup_sleep()toconfigurethenextsleep
interval.
pytrack.get_wake_reason()
Returnsthelastwakeupreason.Possiblevaluesare:
3.3.3Sleep
145
#WAKE_REASON_ACCELEROMETER=1#Accelerometeractivity/inactivitydetection
#WAKE_REASON_PUSH_BUTTON=2#Pytrack/Pysenseresetbuttom
#WAKE_REASON_TIMER=4#Normaltimeoutofthesleepinterval
#WAKE_REASON_INT_PIN=8#INTpin
Note:the WAKE_REASON_INT_PINcanbeusedifthePIC_RC1pin(pin#6onExternalIO
Header)istoggled.
Asintheaboveexample,thismethodshouldbecalledatthebeginningofthescript,tofind
outthereset(wakeup)reason.
pytrack.go_to_sleep([gps=True])
Putstheboardinsleepmode,fortheduration,whichhastobesetpreviouslywith
pytrack.setup_sleep(timout_sec).TheoptionalbooleanparametersetstheGPSstate
duringsleep.
MicroPythoncode,whichisafterthisfunction,isnotexecuted,aswakeupwillrestart
MicroPython.
pytrack.setup_int_wake_up(rising,falling])
Enablesaswakeupsource,theaccelerometerINTpin(PIC-RA5).Thebooleanparameters
willindicaterisingedge(activitydetection)and/orfallingedge(inactivitydetection)is
configured.
Theaccelerometer(class LIS2HH12)hastobealsoconfiguredforacertainacceleration
thresholdandduration.Codesnippet:
frompytrackimportPytrack
fromLIS2HH12importLIS2HH12
py=Pytrack()
acc=LIS2HH12()
#enableactivityandalsoinactivityinterrupts,usingthedefaultcallbackhandler
py.setup_int_wake_up(True,True)
#settheaccelerationthresholdto2000mG(2G)andthemindurationto200ms
acc.enable_activity_interrupt(2000,200)
pytrack.setup_int_pin_wake_up([rising_edge=True])
Enablesaswakeupsource,theINTpic(PIC-RC1,pin#6onExternalIOHeader).Either
risingorfallingedgehastobeset,bydefaultit'srisingedge.
3.3.3Sleep
146
pytrack.setup_sleep(time_seconds)
Setsthesleepinterval,specifiedinseconds.Theactualsleepwillbestartedbycalling
go_to_sleep()method.
Pleasenotethatmorefunctionalityisbeingaddedweeklytotheselibraries.Ifarequired
featureisnotavailable,feelfreetocontributewithapullrequestattheLibrariesGitHub
repository
3.3.3Sleep
147
TutorialsandExamples
ThissectioncontainstutorialsandexamplesforusewithPycommodulesandExpansion
boards.
GeneralPycomtutorialscontainstutorialsthatmayberunonanyPycomdevice,suchas
connectingtoaWiFinetwork,Bluetooth,controllingI/Opinsetc.Latersectionsarespecific
totheLoPyandSiPydevicessuchassettingupaLoRanodeorconnectingtotheSigfox
network.ThefinalsectionsarerelatedtoexamplesusingthePytrackandPysense.
Beforestarting,ensurethatanyPycomdevicesarerunningthelatestfirmware;for
instructionsseeFirmwareUpdates.
Thesourcecodeforthesetutorials,alongwiththerequiredlibrariescanbefoundininthe
pycom-librariesrepository.
4.1Introduction
148
UsingtheREPLPrompt
UsingthePymakrPlugin,openandconnectadeviceoruseserialterminal(PuTTY,screen,
picocom,etc).Uponconnecting,thereshouldbeablankscreenwithaflashingcursor.Press
EnterandaMicroPythonpromptshouldappear,i.e. >>>.Let’smakesureitisworkingwith
theobligatorytest:
>>>print("HelloLoPy!")
HelloLoPy!
Intheexampleabove,the >>>charactersshouldnotbetyped.Theyaretheretoindicate
thatthetextshouldbeplacedaftertheprompt.Oncethetexthasbeenentered
print("HelloLoPy!")andpressed Enter,theoutputshouldappearonscreen,identicalto
theexampleabove.
BasicPythoncommandscanbetestedoutinasimilarfashion.
Ifthisisnotworking,tryeitherahardresetorasoftreset;seebelow.
Herearesomeotherexample,utilisingthedevice'shardwarefeatures:
>>>frommachineimportPin
>>>led=Pin('G16',mode=Pin.OUT,value=1)
>>>led(0)
>>>led(1)
>>>led.toggle()
>>>1+2
3
>>>5/2
2.5
>>>20*'py'
'pypypypypypypypypypypypypypypypypypypypy'
ResettingtheDevice
Ifsomethinggoeswrong,thedevicecanberesetwithtwomethods.Thefirstistopress
CTRL-DattheMicroPythonprompt,whichwillperformasoftreset.Amessage,asfollowing,
willappear:
4.2.1REPL
150
>>>
PYB:softreboot
MicroPythonv1.4.6-146-g1d8b5e5on2016-10-21;LoPywithESP32
Type"help()"formoreinformation.
>>>
Ifthatstillisn’tworkingahardresetcanbeperformed(power-off/on)bypressingthe RST
switch(thesmallblackbuttonnexttotheRGBLED).Usingtelnet,thiswillendthesession,
disconnectingtheprogramthatwasusedtoconnecttothePycomDevice.
4.2.1REPL
151
WLAN
TheWLANisasystemfeatureofallPycomdevices,thereforeitisenabledbydefault.
InordertoretrievethecurrentWLANinstance,run:
>>>fromnetworkimportWLAN
>>>wlan=WLAN()#wecalltheconstructorwithoutparams
Thecurrentmode( WLAN.APafterpowerup)maybecheckedbyrunning:
>>>wlan.mode()
WhenchangingtheWLANmode,iffollowingtheinstructionsbelow,theWLAN
connectiontothePycomdevicewillbebroken.Thismeanscommandswillnotrun
interactivelyoverWiFi.
Therearetwowaysaroundthis:
1. Putthissetupcodeintothe boot.pyfileofthePycomdevicesothatitgets
executedautomaticallyafterreset.
2. DuplicatetheREPLonUART.ThiswaycommandscanberunviaSerialUSB.
ConnectingtoaRouter
TheWLANnetworkclassalwaysbootsin WLAN.APmode;toconnectittoanexisting
network,theWiFiclassmustbeconfiguredasastation:
fromnetworkimportWLAN
wlan=WLAN(mode=WLAN.STA)
Nowthedevicemayproceedtoscanfornetworks:
4.2.2WLAN
152
nets=wlan.scan()
fornetinnets:
ifnet.ssid=='mywifi':
print('Networkfound!')
wlan.connect(net.ssid,auth=(net.sec,'mywifikey'),timeout=5000)
whilenotwlan.isconnected():
machine.idle()#savepowerwhilewaiting
print('WLANconnectionsucceeded!')
break
AssigningaStaticIPAddressatBootUp
Iftheuserswantstheirdevicetoconnecttoahomerouteruponbootup,usingwithafixed
IPaddress,usethefollowingscriptas /flash/boot.py:
importmachine
fromnetworkimportWLAN
wlan=WLAN()#getcurrentobject,withoutchangingthemode
ifmachine.reset_cause()!=machine.SOFT_RESET:
wlan.init(mode=WLAN.STA)
#configurationbelowMUSTmatchyourhomeroutersettings!!
wlan.ifconfig(config=('192.168.178.107','255.255.255.0','192.168.178.1','8.8.8.
8'))
ifnotwlan.isconnected():
#changethelinebelowtomatchyournetworkssid,securityandpassword
wlan.connect('mywifi',auth=(WLAN.WPA2,'mywifikey'),timeout=5000)
whilenotwlan.isconnected():
machine.idle()#savepowerwhilewaiting
Noticehowwecheckfortheresetcauseandtheconnectionstatus,thisiscrucialin
ordertobeabletosoftresettheLoPyduringatelnetsessionwithoutbreakingthe
connection.
MultipleNetworksusingaStaticIPAddress
Thefollowingscriptholdsalistwithnetsandanoptionallistof wlan_configtosetafixedIP
4.2.2WLAN
153
importos
importmachine
uart=machine.UART(0,115200)
os.dupterm(uart)
known_nets={
'<net>':{'pwd':'<password>'},
'<net>':{'pwd':'<password>','wlan_config':('10.0.0.114','255.255.0.0','10.0
.0.1','10.0.0.1')},#(ip,subnet_mask,gateway,DNS_server)
}
ifmachine.reset_cause()!=machine.SOFT_RESET:
fromnetworkimportWLAN
wl=WLAN()
wl.mode(WLAN.STA)
original_ssid=wl.ssid()
original_auth=wl.auth()
print("Scanningforknownwifinets")
available_nets=wl.scan()
nets=frozenset([e.ssidforeinavailable_nets])
known_nets_names=frozenset([keyforkeyinknown_nets])
net_to_use=list(nets&known_nets_names)
try:
net_to_use=net_to_use[0]
net_properties=known_nets[net_to_use]
pwd=net_properties['pwd']
sec=[e.secforeinavailable_netsife.ssid==net_to_use][0]
if'wlan_config'innet_properties:
wl.ifconfig(config=net_properties['wlan_config'])
wl.connect(net_to_use,(sec,pwd),timeout=10000)
whilenotwl.isconnected():
machine.idle()#savepowerwhilewaiting
print("Connectedto"+net_to_use+"withIPaddress:"+wl.ifconfig()[0])
exceptExceptionase:
print("Failedtoconnecttoanyknownnetwork,goingintoAPmode")
wl.init(mode=WLAN.AP,ssid=original_ssid,auth=original_auth,channel=6,anten
na=WLAN.INT_ANT)
ConnectingtoaWPA2-Enterprisenetwork
ConnectingwithEAP-TLS:
Beforeconnecting,obtainandcopythepublicandprivatekeystothedevice,e.g.under
location /flash/cert.Ifitisrequiredtovalidatetheserver’spublickey,anappropriateCA
certificate(chain)mustalsobeprovided.
4.2.2WLAN
154
fromnetworkimportWLAN
wlan=WLAN(mode=WLAN.STA)
wlan.connect(ssid='mywifi',auth=(WLAN.WPA2_ENT,),identity='myidentity',ca_certs='/f
lash/cert/ca.pem',keyfile='/flash/cert/client.key',certfile='/flash/cert/client.crt'
)
ConnectingwithEAP-PEAPorEAP-TTLS:
IncaseofEAP-PEAP(orEAP-TTLS),theclientkeyandcertificatearenotnecessary,onlya
usernameandpasswordpair.Ifitisrequiredtovalidatetheserver’spublickey,an
appropriateCAcertificate(chain)mustalsobeprovided.
fromnetworkimportWLAN
wlan=WLAN(mode=WLAN.STA)
wlan.connect(ssid='mywifi',auth=(WLAN.WPA2_ENT,'username','password'),identity='my
identity',ca_certs='/flash/cert/ca.pem')
4.2.2WLAN
155
Bluetooth
Atpresent,basicBLEfunctionalityisavailable.Morefeatureswillbeimplementedinthe
nearfuture,suchaspairing.Thispagewillbeupdatedinlinewiththesefeatures.
Fullinfoon bluetoothcanbefoundwithinBluetoothpageoftheFirmwareAPIReference.
ScanforBLEDevices
Scanforalloftheadvertisingdeviceswithinrangeofthescanningdevice.
bluetooth.start_scan(10)#startsscanningandstopafter10seconds
bluetooth.start_scan(-1)#startsscanningindefinitelyuntilbluetooth.stop_scan()i
scalled
RawDatafromaBLEDevice
Aquickusageexamplethatscansandprintstherawdatafromadvertisements.
fromnetworkimportBluetooth
bluetooth=Bluetooth()
bluetooth.start_scan(-1)#startscanningwithnotimeout
whileTrue:
print(bluetooth.get_adv())
ConnecttoaBLEDevice
Connectingtoadevicethatissendingadvertisements.
4.2.3Bluetooth
156
fromnetworkimportBluetooth
importubinascii
bluetooth=Bluetooth()
#scanuntilwecanconnecttoanyBLEdevicearound
bluetooth.start_scan(-1)
adv=None
whileTrue:
adv=bluetooth.get_adv()
ifadv:
try:
bluetooth.connect(adv.mac)
except:
#startscanningagain
bluetooth.start_scan(-1)
continue
break
print("Connectedtodevicewithaddr={}".format(ubinascii.hexlify(adv.mac)))
ConnecttoaBLEDeviceandRetrieveData
Connectingtoadevicenamed'HeartRate'andreceivingdatafromit’sservices.
4.2.3Bluetooth
157
fromnetworkimportBluetooth
importtime
bt=Bluetooth()
bt.start_scan(-1)
whileTrue:
adv=bt.get_adv()
ifadvandbt.resolve_adv_data(adv.data,Bluetooth.ADV_NAME_CMPL)=='HeartRate':
try:
conn=bt.connect(adv.mac)
services=conn.services()
forserviceinservices:
time.sleep(0.050)
iftype(service.uuid())==bytes:
print('Readingcharsfromservice={}'.format(service.uuid()))
else:
print('Readingcharsfromservice=%x'%service.uuid())
chars=service.characteristics()
forcharinchars:
if(char.properties()&Bluetooth.PROP_READ):
print('char{}value={}'.format(char.uuid(),char.read()))
conn.disconnect()
break
except:
pass
else:
time.sleep(0.050)
RetrievetheName&ManufacturerfromaBLEDevice
Using resolve_adv_data()toattempttoretrievethenameandmanufacturerdatafromthe
advertiser.
4.2.3Bluetooth
158
importubinascii
fromnetworkimportBluetooth
bluetooth=Bluetooth()
bluetooth.start_scan(20)
whilebluetooth.isscanning():
adv=bluetooth.get_adv()
ifadv:
#trytogetthecompletename
print(bluetooth.resolve_adv_data(adv.data,Bluetooth.ADV_NAME_CMPL))
mfg_data=bluetooth.resolve_adv_data(adv.data,Bluetooth.ADV_MANUFACTURER_DAT
A)
ifmfg_data:
#trytogetthemanufacturerdata(Apple'siBeacondataissenthere)
print(ubinascii.hexlify(mfg_data))
4.2.3Bluetooth
159
HTTPS
Basicconnectionusing ssl.wrap_socket().
importsocket
importssl
s=socket.socket()
ss=ssl.wrap_socket(s)
ss.connect(socket.getaddrinfo('www.google.com',443)[0][-1])
Belowisanexampleusingcertificateswiththeblynkcloud.
Certificatewasdownloadedfromtheblynkexamplesfolderandplacedin /flash/cert/on
thedevice.
importsocket
importssl
s=socket.socket()
ss=ssl.wrap_socket(s,cert_reqs=ssl.CERT_REQUIRED,ca_certs='/flash/cert/ca.pem')
ss.connect(socket.getaddrinfo('cloud.blynk.cc',8441)[0][-1])
Formoreinfo,checkthe sslmoduleintheAPIreference.
4.2.4HTTPS
160
MQTT
MQTTisalightweightmessagingprotocolthatisidealforsendingsmallpacketsofdatato
andfromIoTdevicesviaWiFi.
ThebrokerusedinthisexampleistheIOAdafruit)platform,whichisfreeandallowsfor
tinkeringwithMQTT.
VisitIOAdafruitandcreateanaccount.You'llneedtogetholdofanAPIKeyaswellasyour
credentials.VisitthisguideformoreinformationaboutMQTTandhowtouseitwith
Adafruit'sBroker.
ThisexamplewillsendamessagetoatopicontheAdafruitMQTTbrokerandthenalso
subscribetothesametopic,inordertoshowhowtousethesubscribefunctionality.
frommqttimportMQTTClient
fromnetworkimportWLAN
importmachine
importtime
defsub_cb(topic,msg):
print(msg)
wlan=WLAN(mode=WLAN.STA)
wlan.connect("yourwifinetwork",auth=(WLAN.WPA2,"wifipassword"),timeout=5000)
whilenotwlan.isconnected():
machine.idle()
print("ConnectedtoWiFi\n")
client=MQTTClient("device_id","io.adafruit.com",user="your_username",password="you
r_api_key",port=1883)
client.set_callback(sub_cb)
client.connect()
client.subscribe(topic="youraccount/feeds/lights")
whileTrue:
print("SendingON")
client.publish(topic="youraccount/feeds/lights",msg="ON")
time.sleep(1)
print("SendingOFF")
client.publish(topic="youraccount/feeds/lights",msg="OFF")
client.check_msg()
time.sleep(1)
4.2.5MQTT
161
4.2.5MQTT
162
AmazonWebServices
TheAWSIoTplatformenablesdevicestoconnecttotheAmazoncloudandletsapplications
inthecloudinteractwithInternet-connectedthings.CommonIoTapplicationseithercollect
andprocesstelemetryfromdevicesorenableuserstocontroladeviceremotely.Things
reporttheirstatebypublishingmessages,inJSONformat,onMQTTtopics.
FormoreinformationseethisPDFFile.
GettingStartedwithAWSIoT
Creatingthemessagebroker(Amazonwebsite):
SignintotheAWSManagementConsole
NavigatetotheIoTConsolebyclickingontheAWSIoTlink
Intheleftnavigationpane,chooseRegister/Manage
Clickonthecreatebutton,giveyourdeviceanameandpresscreate
Clickonthedevicethathasbeencreated
OntheDetailspage,intheleftnavigationpane,chooseSecurity
OntheCertificatespage,chooseCreatecertificate
Downloadallthecertificates,thenpresstheActivateandtheAttachaPolicybuttons.
Seeimage
ClickontheCreateNewPolicybutton
OntheCreatePolicypage,chooseapolicynameandtheactionstoauthorise.
Gotothecertificatespage,clickonthethreedotsofyourcertificateandattachthe
policytothecertificateasshowninthediagram
Settingupthedevice(Pycomdevice):
DownloadthelatestsamplecodefromthePycomGitHubRepository.
ConnecttothedeviceviaFTPandputtherootCAcertificate,theclientcertificate
(*.pem.crt)andtheprivatekey( *.private.pem.key)inthe /flash/certfolder.
UpdatetheconfigfilewithyourWiFisettings,theAWSHostandthecertificatepaths.
Putthe config.pyandthe main.pyinthedeviceflash
Configuration( config.py):
4.2.6AWS
163
ThisfilecontainstheWiFi,certificatepathsandapplicationspecificsettingsthatneedtobe
updatedbytheuser.
#WiFiconfiguration
WIFI_SSID='my_wifi_ssid'
WIFI_PASS='my_wifi_password'
#AWSgeneralconfiguration
AWS_PORT=8883
AWS_HOST='aws_host_url'
AWS_ROOT_CA='/flash/cert/aws_root.ca'
AWS_CLIENT_CERT='/flash/cert/aws_client.cert'
AWS_PRIVATE_KEY='/flash/cert/aws_private.key'
##################Subscribe/Publishclient#################
CLIENT_ID='PycomPublishClient'
TOPIC='PublishTopic'
OFFLINE_QUEUE_SIZE=-1
DRAINING_FREQ=2
CONN_DISCONN_TIMEOUT=10
MQTT_OPER_TIMEOUT=5
LAST_WILL_TOPIC='PublishTopic'
LAST_WILL_MSG='ToAll:Lastwillmessage'
#######################Shadowupdater########################
#THING_NAME="mythingname"
#CLIENT_ID="ShadowUpdater"
#CONN_DISCONN_TIMEOUT=10
#MQTT_OPER_TIMEOUT=5
#######################DeltaListener########################
#THING_NAME="mythingname"
#CLIENT_ID="DeltaListener"
#CONN_DISCONN_TIMEOUT=10
#MQTT_OPER_TIMEOUT=5
#######################ShadowEcho########################
#THING_NAME="mythingname"
#CLIENT_ID="ShadowEcho"
#CONN_DISCONN_TIMEOUT=10
#MQTT_OPER_TIMEOUT=5
Subscibe/Publish( main.py)
Tosubscribetoatopic:
GototheAWSIotpage,clickonmanageandchooseyourdevice
Fromthelefthandside,chooseActivityandthenclickMQTTclient.
Choosethetopicnameyouenteredintheconfigurationfile.
4.2.6AWS
164
Messagesshouldbepublishedasshowninthediagram
#userspecifiedcallbackfunction
defcustomCallback(client,userdata,message):
print("Receivedanewmessage:")
print(message.payload)
print("fromtopic:")
print(message.topic)
print("--------------\n\n")
#configuretheMQTTclient
pycomAwsMQTTClient=AWSIoTMQTTClient(config.CLIENT_ID)
pycomAwsMQTTClient.configureEndpoint(config.AWS_HOST,config.AWS_PORT)
pycomAwsMQTTClient.configureCredentials(config.AWS_ROOT_CA,config.AWS_PRIVATE_KEY,co
nfig.AWS_CLIENT_CERT)
pycomAwsMQTTClient.configureOfflinePublishQueueing(config.OFFLINE_QUEUE_SIZE)
pycomAwsMQTTClient.configureDrainingFrequency(config.DRAINING_FREQ)
pycomAwsMQTTClient.configureConnectDisconnectTimeout(config.CONN_DISCONN_TIMEOUT)
pycomAwsMQTTClient.configureMQTTOperationTimeout(config.MQTT_OPER_TIMEOUT)
pycomAwsMQTTClient.configureLastWill(config.LAST_WILL_TOPIC,config.LAST_WILL_MSG,1)
#ConnecttoMQTTHost
ifpycomAwsMQTTClient.connect():
print('AWSconnectionsucceeded')
#Subscribetotopic
pycomAwsMQTTClient.subscribe(config.TOPIC,1,customCallback)
time.sleep(2)
#Sendmessagetohost
loopCount=0
whileloopCount<8:
pycomAwsMQTTClient.publish(config.TOPIC,"NewMessage"+str(loopCount),1)
loopCount+=1
time.sleep(5.0)
Shadowupdater( main.py)
4.2.6AWS
165
#userspecifiedcallbackfunctions
defcustomShadowCallback_Update(payload,responseStatus,token):
ifresponseStatus=="timeout":
print("Updaterequest"+token+"timeout!")
ifresponseStatus=="accepted":
payloadDict=json.loads(payload)
print("Updaterequestwithtoken:"+token+"accepted!")
print("property:"+str(payloadDict["state"]["desired"]["property"]))
ifresponseStatus=="rejected":
print("Updaterequest"+token+"rejected!")
defcustomShadowCallback_Delete(payload,responseStatus,token):
ifresponseStatus=="timeout":
print("Deleterequest"+token+"timeout!")
ifresponseStatus=="accepted":
print("Deleterequestwithtoken:"+token+"accepted!")
ifresponseStatus=="rejected":
print("Deleterequest"+token+"rejected!")
#configuretheMQTTclient
pycomAwsMQTTShadowClient=AWSIoTMQTTShadowClient(config.CLIENT_ID)
pycomAwsMQTTShadowClient.configureEndpoint(config.AWS_HOST,config.AWS_PORT)
pycomAwsMQTTShadowClient.configureCredentials(config.AWS_ROOT_CA,config.AWS_PRIVATE_K
EY,config.AWS_CLIENT_CERT)
pycomAwsMQTTShadowClient.configureConnectDisconnectTimeout(config.CONN_DISCONN_TIMEOUT
)
pycomAwsMQTTShadowClient.configureMQTTOperationTimeout(config.MQTT_OPER_TIMEOUT)
#ConnecttoMQTTHost
ifpycomAwsMQTTShadowClient.connect():
print('AWSconnectionsucceeded')
deviceShadowHandler=pycomAwsMQTTShadowClient.createShadowHandlerWithName(config.THIN
G_NAME,True)
#DeleteshadowJSONdoc
deviceShadowHandler.shadowDelete(customShadowCallback_Delete,5)
#Updateshadowinaloop
loopCount=0
whileTrue:
JSONPayload='{"state":{"desired":{"property":'+str(loopCount)+'}}}'
deviceShadowHandler.shadowUpdate(JSONPayload,customShadowCallback_Update,5)
loopCount+=1
time.sleep(5)
DeltaListener( main.py)
4.2.6AWS
166
#CustomShadowcallback
defcustomShadowCallback_Delta(payload,responseStatus,token):
payloadDict=json.loads(payload)
print("property:"+str(payloadDict["state"]["property"]))
print("version:"+str(payloadDict["version"]))
#configuretheMQTTclient
pycomAwsMQTTShadowClient=AWSIoTMQTTShadowClient(config.CLIENT_ID)
pycomAwsMQTTShadowClient.configureEndpoint(config.AWS_HOST,config.AWS_PORT)
pycomAwsMQTTShadowClient.configureCredentials(config.AWS_ROOT_CA,config.AWS_PRIVATE_K
EY,config.AWS_CLIENT_CERT)
pycomAwsMQTTShadowClient.configureConnectDisconnectTimeout(config.CONN_DISCONN_TIMEOUT
)
pycomAwsMQTTShadowClient.configureMQTTOperationTimeout(config.MQTT_OPER_TIMEOUT)
#ConnecttoMQTTHost
ifpycomAwsMQTTShadowClient.connect():
print('AWSconnectionsucceeded')
deviceShadowHandler=pycomAwsMQTTShadowClient.createShadowHandlerWithName(config.THIN
G_NAME,True)
#Listenondeltas
deviceShadowHandler.shadowRegisterDeltaCallback(customShadowCallback_Delta)
#Loopforever
whileTrue:
time.sleep(1)
4.2.6AWS
167
ADC
ThisexampleisasimpleADCsample.Formoreinformationpleasesee ADC.
frommachineimportADC
adc=ADC(0)
adc_c=adc.channel(pin='P13')
adc_c()
adc_c.value()
Calibration
CurrentlytheESP32'sADCisnotcalibratedfromthefactory.Thismeansitmustbe
calibratedeachtimeyouwishtouseit.Todothisyoumustfirstlymeasuretheinternal
voltagereference.Thefollowingcodewillconnectthe1.1vreferenceto P22
frommachineimportADC
adc=ADC()
#OutputVrefofP22
adc.vref_to_pin('P22')
Nowthatthevoltagereferenceisexternallyaccessibleyoushouldmeasureitwiththemost
accuratevoltmeteryouhaveaccessto.Notedownthereadinginmillivolts,e.g. 1120.To
disconnectthe1.1vreferencefrom P22pleaseresetyourmodule.Youcannowcalibrate
theADCbytellingitthetruevalueoftheinternalreference.Youshouldthencheckyour
calibrationbyconnectingtheADCtoaknownvoltagesource.
#Setcalibration-seenoteabove
adc.vref(1100)
#Checkcalibrationbyreadingaknownvoltage
adc_c=adc.channel(pin='P16',attn=ADC.ATTN_11DB)
print(adc_c.voltage())
4.2.7ADC
168
I2C
ThefollowingexamplereceivesdatafromalightsensorusingI2C.Sensorusedisthe
BH1750FVIDigitalLightSensor.
importtime
frommachineimportI2C
importbh1750fvi
i2c=I2C(0,I2C.MASTER,baudrate=100000)
light_sensor=bh1750fvi.BH1750FVI(i2c,addr=i2c.scan()[0])
while(True):
data=light_sensor.read()
print(data)
time.sleep(1)
DriversfortheBH1750FVI
Placethissamplecodeintoafilenamed bh1750fvi.py.Thiscanthenbeimportedasa
library.
#SimpledriverfortheBH1750FVIdigitallightsensor
classBH1750FVI:
MEASUREMENT_TIME=const(120)
def__init__(self,i2c,addr=0x23,period=150):
self.i2c=i2c
self.period=period
self.addr=addr
self.time=0
self.value=0
self.i2c.writeto(addr,bytes([0x10]))#startcontinuos1Luxreadingsevery1
20ms
defread(self):
self.time+=self.period
ifself.time>=MEASUREMENT_TIME:
self.time=0
data=self.i2c.readfrom(self.addr,2)
self.value=(((data[0]<<8)+data[1])*1200)//1000
returnself.value
4.2.8I2C
169
LightsensorandLoRa
Thisisthesamecode,withaddedLoRaconnectivity,sendingtheluxvaluefromthelight
sensortoanotherLoRaenableddevice.
importsocket
importtime
importpycom
importstruct
fromnetworkimportLoRa
frommachineimportI2C
importbh1750fvi
LORA_PKG_FORMAT="!BH"
LORA_CONFIRM_FORMAT="!BB"
DEVICE_ID=1
pycom.heartbeat(False)
lora=LoRa(mode=LoRa.LORA,tx_iq=True,region=LoRa.EU868)
lora_sock=socket.socket(socket.AF_LORA,socket.SOCK_RAW)
lora_sock.setblocking(False)
i2c=I2C(0,I2C.MASTER,baudrate=100000)
light_sensor=bh1750fvi.BH1750FVI(i2c,addr=i2c.scan()[0])
while(True):
msg=struct.pack(LORA_PKG_FORMAT,DEVICE_ID,light_sensor.read())
lora_sock.send(msg)
pycom.rgbled(0x150000)
wait=5
while(wait>0):
wait=wait-0.1
time.sleep(0.1)
recv_data=lora_sock.recv(64)
if(len(recv_data)>=2):
status,device_id=struct.unpack(LORA_CONFIRM_FORMAT,recv_data)
if(device_id==DEVICE_IDandstatus==200):
pycom.rgbled(0x001500)
wait=0
time.sleep(1)
4.2.8I2C
170
4.2.8I2C
171
OnewireDriver
ThistutorialexplainshowtoconnectandreaddatafromaDS18x20temperaturesensor.
Theonewirelibraryisalsoavailableatthepycom-librariesGitHubRepository.
Basicusage
importtime
frommachineimportPin
fromonewireimportDS18X20
fromonewireimportOneWire
#DS18B20datalineconnectedtopinP10
ow=OneWire(Pin('P10'))
temp=DS18X20(ow)
whileTrue:
print(temp.read_temp_async())
time.sleep(1)
temp.start_conversion()
time.sleep(1)
Library
#!/usr/bin/envpython3
"""
OneWirelibraryforMicroPython
"""
importtime
importmachine
classOneWire:
CMD_SEARCHROM=const(0xf0)
CMD_READROM=const(0x33)
CMD_MATCHROM=const(0x55)
CMD_SKIPROM=const(0xcc)
def__init__(self,pin):
self.pin=pin
self.pin.init(pin.OPEN_DRAIN,pin.PULL_UP)
defreset(self):
"""
4.2.9OnewireDriver
172
Performtheonewireresetfunction.
ReturnsTrueifadeviceassertedapresencepulse,Falseotherwise.
"""
sleep_us=time.sleep_us
disable_irq=machine.disable_irq
enable_irq=machine.enable_irq
pin=self.pin
pin(0)
sleep_us(480)
i=disable_irq()
pin(1)
sleep_us(60)
status=notpin()
enable_irq(i)
sleep_us(420)
returnstatus
defread_bit(self):
sleep_us=time.sleep_us
enable_irq=machine.enable_irq
pin=self.pin
pin(1)#halfofthedevicesdon'tmatchCRCwithoutthisline
i=machine.disable_irq()
pin(0)
sleep_us(1)
pin(1)
sleep_us(1)
value=pin()
enable_irq(i)
sleep_us(40)
returnvalue
defread_byte(self):
value=0
foriinrange(8):
value|=self.read_bit()<<i
returnvalue
defread_bytes(self,count):
buf=bytearray(count)
foriinrange(count):
buf[i]=self.read_byte()
returnbuf
defwrite_bit(self,value):
sleep_us=time.sleep_us
pin=self.pin
i=machine.disable_irq()
pin(0)
sleep_us(1)
4.2.9OnewireDriver
173
pin(value)
sleep_us(60)
pin(1)
sleep_us(1)
machine.enable_irq(i)
defwrite_byte(self,value):
foriinrange(8):
self.write_bit(value&1)
value>>=1
defwrite_bytes(self,buf):
forbinbuf:
self.write_byte(b)
defselect_rom(self,rom):
"""
Selectaspecificdevicetotalkto.Passinromasabytearray(8bytes).
"""
self.reset()
self.write_byte(CMD_MATCHROM)
self.write_bytes(rom)
defcrc8(self,data):
"""
ComputeCRC
"""
crc=0
foriinrange(len(data)):
byte=data[i]
forbinrange(8):
fb_bit=(crc^byte)&0x01
iffb_bit==0x01:
crc=crc^0x18
crc=(crc>>1)&0x7f
iffb_bit==0x01:
crc=crc|0x80
byte=byte>>1
returncrc
defscan(self):
"""
ReturnalistofROMsforallattacheddevices.
EachROMisreturnedasabytesobjectof8bytes.
"""
devices=[]
diff=65
rom=False
foriinrange(0xff):
rom,diff=self._search_rom(rom,diff)
ifrom:
devices+=[rom]
ifdiff==0:
4.2.9OnewireDriver
174
break
returndevices
def_search_rom(self,l_rom,diff):
ifnotself.reset():
returnNone,0
self.write_byte(CMD_SEARCHROM)
ifnotl_rom:
l_rom=bytearray(8)
rom=bytearray(8)
next_diff=0
i=64
forbyteinrange(8):
r_b=0
forbitinrange(8):
b=self.read_bit()
ifself.read_bit():
ifb:#therearenodevicesorthereisanerroronthebus
returnNone,0
else:
ifnotb:#collision,twodeviceswithdifferentbitmeaning
ifdiff>ior((l_rom[byte]&(1<<bit))anddiff!=i):
b=1
next_diff=i
self.write_bit(b)
ifb:
r_b|=1<<bit
i-=1
rom[byte]=r_b
returnrom,next_diff
classDS18X20(object):
def__init__(self,onewire):
self.ow=onewire
self.roms=[romforrominself.ow.scan()ifrom[0]==0x10orrom[0]==0x28
]
defisbusy(self):
"""
CheckswetheroneoftheDS18x20devicesonthebusisbusy
performingatemperatureconversion
"""
returnnotself.ow.read_bit()
defstart_conversion(self,rom=None):
"""
StartthetempconversionononeDS18x20device.
Passthe8-bytebytesobjectwiththeROMofthespecificdeviceyouwanttor
ead.
IfonlyoneDS18x20deviceisattachedtothebusyoumayomittheromparamet
er.
"""
rom=romorself.roms[0]
4.2.9OnewireDriver
175
ow=self.ow
ow.reset()
ow.select_rom(rom)
ow.write_byte(0x44)#ConvertTemp
defread_temp_async(self,rom=None):
"""
ReadthetemperatureofoneDS18x20deviceiftheconversioniscomplete,
otherwisereturnNone.
"""
ifself.isbusy():
returnNone
rom=romorself.roms[0]
ow=self.ow
ow.reset()
ow.select_rom(rom)
ow.write_byte(0xbe)#Readscratch
data=ow.read_bytes(9)
returnself.convert_temp(rom[0],data)
defconvert_temp(self,rom0,data):
"""
Converttherawtemperaturedataintodegreescelsiusandreturnasafixedpo
intwith2decimalplaces.
"""
temp_lsb=data[0]
temp_msb=data[1]
ifrom0==0x10:
iftemp_msb!=0:
#convertnegativenumber
temp_read=temp_lsb>>1|0x80#truncatebit0byshifting,fillh
ighbitwith1.
temp_read=-((~temp_read+1)&0xff)#nowconvertfromtwo'scomple
ment
else:
temp_read=temp_lsb>>1#truncatebit0byshifting
count_remain=data[6]
count_per_c=data[7]
temp=100*temp_read-25+(count_per_c-count_remain)//count_per_c
returntemp
elifrom0==0x28:
return(temp_msb<<8|temp_lsb)*100//16
else:
assertFalse
4.2.9OnewireDriver
176
Threading
MicroPythonsupportsspawningthreadsbythe _threadmodule.Thefollowingexample
demonstratestheuseofthismodule.Athreadissimplydefinedasafunctionthatcan
receiveanynumberofparameters.Below3threadsarestarted,eachoneperformaprintat
adifferentinterval.
import_thread
importtime
defth_func(delay,id):
whileTrue:
time.sleep(delay)
print('Runningthread%d'%id)
foriinrange(3):
_thread.start_new_thread(th_func,(i+1,i))
UsingLocks:
import_thread
a_lock=_thread.allocate_lock()
witha_lock:
print("a_lockislockedwhilethisexecutes")
4.2.10Threading
177
RGBLED
BydefaulttheheartbeatLEDflashesinbluecolouronceevery4stosignalthatthesystem
isalive.Thiscanbeoverriddenthroughthe pycommodule.
importpycom
pycom.heartbeat(False)
pycom.rgbled(0xff00)#turnontheRGBLEDingreencolour
TheheartbeatLEDisalsousedtoindicatethatanerrorwasdetected.
ThefollowingpieceofcodeusestheRGBLEDtomakeatrafficlightthatrunsfor10cycles.
importpycom
importtime
pycom.heartbeat(False)
forcyclesinrange(10):#stopafter10cycles
pycom.rgbled(0x007f00)#green
time.sleep(5)
pycom.rgbled(0x7f7f00)#yellow
time.sleep(1.5)
pycom.rgbled(0x7f0000)#red
time.sleep(4)
Hereistheexpectedresult:
4.2.11RGBLED
178
4.2.11RGBLED
179
Timers
Detailedinformationaboutthisclasscanbefoundin Timer.
Chronometer
TheChronometercanbeusedtomeasurehowmuchtimehaselapsedinablockofcode.
Thefollowingexampleusesasimplestopwatch.
frommachineimportTimer
importtime
chrono=Timer.Chrono()
chrono.start()
time.sleep(1.25)#simulatethefirstlaptook1.25seconds
lap=chrono.read()#readelapsedtimewithoutstopping
time.sleep(1.5)
chrono.stop()
total=chrono.read()
print()
print("\ntheracertook%fsecondstofinishtherace"%total)
print("%fsecondsinthefirstlap"%lap)
print("%fsecondsinthelastlap"%(total-lap))
Alarm
TheAlarmcanbeusedtogetinterruptsataspecificinterval.Thefollowingcodeexecutesa
callbackeverysecondfor10seconds.
4.2.12Timers
180
frommachineimportTimer
classClock:
def__init__(self):
self.seconds=0
self.__alarm=Timer.Alarm(self._seconds_handler,1,periodic=True)
def_seconds_handler(self,alarm):
self.seconds+=1
print("%02dsecondshavepassed"%self.seconds)
ifself.seconds==10:
alarm.callback(None)#stopcountingafter10seconds
clock=Clock()
Therearenorestrictionstowhatcanbedoneinaninterrupt.Forexample,itispossible
toevendonetworkrequestswithaninterrupt.However,itisimportanttokeepinmind
thatinterruptsarehandledsequentially,soit’sgoodpracticetokeepthemshort.More
informationcanbefoundin InterruptHandling.
4.2.12Timers
181
PIRSensor
ThiscodereadsPIRsensortriggersfromthissimplePIRsensorandsendsanHTTP
requestforeverytrigger,inthiscasetoaDomoticzinstallation.Whenmotionisconstantly
detected,thisPIRsensorkeepsthepinhigh,inwhichcasethiscodewillkeepsending
HTTPrequestsevery10seconds(configurablewiththehold_timevariable).
Main( main.py)
importtime
fromnetworkimportWLAN
frommachineimportPin
fromdomoticzimportDomoticz
wl=WLAN(WLAN.STA)
d=Domoticz("<ip>",8080,"<hash>")
#config
hold_time_sec=10
#flags
last_trigger=-10
pir=Pin('G4',mode=Pin.IN,pull=Pin.PULL_UP)
#mainloop
print("Startingmainloop")
whileTrue:
ifpir()==1:
iftime.time()-last_trigger>hold_time_sec:
last_trigger=time.time()
print("Presencedetected,sendingHTTPrequest")
try:
return_code=d.setVariable('Presence:LivingRoom','1')
print("Requestresult:"+str(return_code))
exceptExceptionase:
print("Requestfailed")
print(e)
else:
last_trigger=0
print("Nopresence")
time.sleep_ms(500)
print("Exitedmainloop")
4.2.13PIRSensor
182
Boot( boot.py)
FormoreWiFiscripts,seethewlanstepbysteptutorial.
importos
importmachine
uart=machine.UART(0,115200)
os.dupterm(uart)
known_nets={
'NetworkID':{'pwd':'<password>','wlan_config':('10.0.0.8','255.255.0.
0','10.0.0.1','10.0.0.1')},
}
fromnetworkimportWLAN
wl=WLAN()
ifmachine.reset_cause()!=machine.SOFT_RESET:
wl.mode(WLAN.STA)
original_ssid=wl.ssid()
original_auth=wl.auth()
print("Scanningforknownwifinets")
available_nets=wl.scan()
nets=frozenset([e.ssidforeinavailable_nets])
known_nets_names=frozenset([keyforkeyinknown_nets])
net_to_use=list(nets&known_nets_names)
try:
net_to_use=net_to_use[0]
net_properties=known_nets[net_to_use]
pwd=net_properties['pwd']
sec=[e.secforeinavailable_netsife.ssid==net_to_use][0]
if'wlan_config'innet_properties:
wl.ifconfig(config=net_properties['wlan_config'])
wl.connect(net_to_use,(sec,pwd),timeout=10000)
whilenotwl.isconnected():
machine.idle()#savepowerwhilewaiting
print("Connectedto"+net_to_use+"withIPaddress:"+wl.ifconfig()[0])
exceptExceptionase:
print("Failedtoconnecttoanyknownnetwork,goingintoAPmode")
wl.init(mode=WLAN.AP,ssid=original_ssid,auth=original_auth,channel=6,anten
na=WLAN.INT_ANT)
DomoticzWrapper( domoticz.py)
4.2.13PIRSensor
183
importsocket
classDomoticz:
def__init__(self,ip,port,basic):
self.basic=basic
self.ip=ip
self.port=port
defsetLight(self,idx,command):
returnself.sendRequest("type=command¶m=switchlight&idx="+idx+"&switchcmd="
+command)
defsetVariable(self,name,value):
returnself.sendRequest("type=command¶m=updateuservariable&vtype=0&vname="
+name+"&vvalue="+value)
defsendRequest(self,path):
try:
s=socket.socket()
s.connect((self.ip,self.port))
s.send(b"GET/json.htm?"+path+"HTTP/1.1\r\nHost:pycom.io\r\nAuthorizatio
n:Basic"+self.basic+"\r\n\r\n")
status=str(s.readline(),'utf8')
code=status.split("")[1]
s.close()
returncode
exceptException:
print("HTTPrequestfailed")
return0
4.2.13PIRSensor
184
ModbusProtocol
Modbusisamessagingprotocolthatdefinesthepacketstructurefortransferringdata
betweendevicesinamaster/slavearchitecture.Theprotocolisindependentofthe
transmissionmediumandisusuallytransmittedoverTCP(MODBUSTCP)orserial
communication(MODBUSRTU).Modbusisintendedasarequest/replyprotocoland
deliversservicesspecifiedbyfunctioncodes.Thefunctioncodeintherequesttellsthe
addressedslavewhatkindofactiontoperform.Thefunctioncodesmostcommonly
supportedbydevicesarelistedbelow.
FunctionName FunctionCode
ReadCoils 0x01
ReadDiscreteInputs 0x02
ReadHoldingRegisters 0x03
ReadInputRegisters 0x04
WriteSingleCoil 0x05
WriteSingleRegister 0x06
WriteMultipleCoils 0x0F
WriteMultipleRegisters 0x10
FormoreinformationontheMODBUSRTUseethefollowingPDFFile.Informationonthe
MODBUSTCPcanbefoundhere.
PycomModbusLibrary
PythonlibrariesandsamplecodethatsupportModbusTCPandModbusRTUareavailable
atthefollowingGitHubRepository.Tousethislibrary,connecttothetargetPycomdevice
viaftpanduploadtheuModbusfolderto /flash.Adescriptionofthesupportedfunction
codesisfoundbelow.
ReadCoils
Thisfunctioncoderequeststhestatus(ON/OFF)ofdiscretecoilsonaremotedevice.The
slavedeviceaddress,theaddressofthefirstcoilandthenumberofcoilsmustbespecified
intherequest.Theaddressofthefirstcoilis0andamaximumof2000contiguouscoilscan
beread.Pythonsamplecodeisshownbelow.
4.2.14Modbus
185
slave_addr=0x0A
starting_address=0x00
coil_quantity=100
coil_status=modbus_obj.read_coils(slave_addr,starting_address,coil_quantity)
print('Coilstatus:'+''.join('{:d}'.format(x)forxincoil_status))
ReadDiscreteInputs
Thiscommandisusedtoreadthestatus(ON/OFF)ofdiscreteinputsonaremotedevice.
Theslaveaddress,theaddressofthefirstinput,andthequantityofinputstobereadmust
bespecified.Theaddressofthefirstinputis0andamaximumof2000continuousinputs
canberead.ThePythonsamplecodeisshownbelow.
slave_addr=0x0A
starting_address=0x0
input_quantity=100
input_status=modbus_obj.read_discrete_inputs(slave_addr,starting_address,input_qua
ntity)
print('Inputstatus:'+''.join('{:d}'.format(x)forxininput_status))
ReadHoldingRegisters
Thisfunctioncodeisusedtoreadthecontentsofanalogueoutputholdingregisters.The
slaveaddress,thestartingregisteraddress,thenumberofregisterstoreadandthesignof
thedatamustbespecified.Registeraddressesstartat0andamaximumof125continuous
registerscanberead.
slave_addr=0x0A
starting_address=0x00
register_quantity=100
signed=True
register_value=modbus_obj.read_holding_registers(slave_addr,starting_address,regis
ter_quantity,signed)
print('Holdingregistervalue:'+''.join('{:d}'.format(x)forxinregister_value))
ReadInputRegisters
Thiscommandisusedtoreadupto125continuousinputregistersonaremotedevice.The
slaveaddress,thestartingregisteraddress,thenumberofinputregistersandthesignofthe
datamustbespecified.Theaddressofthefirstinputregistersis0.
4.2.14Modbus
186
slave_addr=0x0A
starting_address=0x00
register_quantity=100
signed=True
register_value=modbus_obj.read_input_registers(slave_addr,starting_address,registe
r_quantity,signed)
print('Inputregistervalue:'+''.join('{:d}'.format(x)forxinregister_value))
WriteSingleCoil
Thisfunctioncodeisusedtowritethestateofadiscretecoilonaremotedevice.Avalueof
0xFF00meansthecoilshouldbesettoON,whileavalueof 0x0000meansthecoilshould
besettoOFF.ThePythonsamplecodetosetthecoilataddress 0x00,toanONstateis
shownbelow.
slave_addr=0x0A
output_address=0x00
output_value=0xFF00
return_flag=modbus_obj.write_single_coil(slave_addr,output_address,output_value)
output_flag='Success'ifreturn_flagelse'Failure'
print('Writingsinglecoilstatus:'+output_flag)
WriteSingleRegister
Thiscommandisusedtowritethecontentsofananalogoutputholdingregisteronaremote
device.Theslaveaddress,theregisteraddress,theregistervalue,andthesignatureofthe
datamustbespecified.Asforalltheothercommands,theregisteraddressesstartfrom0.
slave_addr=0x0A
register_address=0x01
register_value=-32768
signed=True
return_flag=modbus_obj.write_single_register(slave_addr,register_address,register_
value,signed)
output_flag='Success'ifreturn_flagelse'Failure'
print('Writingsinglecoilstatus:'+output_flag)
WriteMultipleCoils
4.2.14Modbus
187
Thisfunctioncodeisusedtosetacontinuoussequenceofcoils,inaremotedevice,to
eitherONorOFF.Theslaveaddress,thestartingaddressofthecoilsandanarraywiththe
coilstatesmustbespecified.
slave_addr=0x0A
starting_address=0x00
output_values=[1,1,1,0,0,1,1,1,0,0,1,1,1]
return_flag=modbus_obj.write_multiple_coils(slave_addr,starting_address,output_val
ues)
output_flag='Success'ifreturn_flagelse'Failure'
print('Writingmultiplecoilstatus:'+output_flag)
WriteMultipleRegisters
Thiscommandisusedtowritethecontentsofacontinuoussequenceofanalogueregisters
onaremotedevice.Theslaveaddress,thestartingregisteraddress,theregistervalues,
andthesignatureofthedatamustbespecified.Theaddressofthefirstregisteris0anda
maximumof125registervaluescanbewritten.ThePythonsamplecodeisshownbelow.
slave_addr=0x0A
register_address=0x01
register_values=[2,-4,6,-256,1024]
signed=True
return_flag=modbus_obj.write_multiple_registers(slave_addr,register_address,regist
er_values,signed)
output_flag='Success'ifreturn_flagelse'Failure'
print('Writingmultipleregisterstatus:'+output_flag)
4.2.14Modbus
188
Overview
Pycommodulescomewiththeabilitytoupdatethedevicesfirmware,whileitisstillrunning,
wecallthisan"overtheair"(OTA)update.Thepycomlibraryprovidesseveralfunctionsto
achievethis.Thisexamplewilldemonstratehowyoucouldpotentiallyusethisfunctionality
toupdatedeployeddevices.Thefullsourcecodeofthisexamplecanbefoundhere.
Method
Herewewilldescribeonepossibleupdatemethodologyyoucouldusethatisimplemented
bythisexample.
ImagineyouasmartmeteringcompanyandyouwishtorolloutanupdateforyourPycom
basedsmartmeter.ThesemetersusuallysenddatabackviaLoRa.UnfortunatelyLoRa
downlinkmessageshaveaverylimitedsizeandseveralhundredifnotthousandwouldbe
requiredtouploadacompletefirmwareimage.Togetaroundthisyoucanhaveyourdevices
sendingtheirregulardataviaLoRaandwhentheyreceiveaspecialcommandviaa
downlinkmessage,thedeviceswillconnecttoaWiFinetwork.Itisunfeasibletoask
customerstoallowyourdevicetoconnecttotheirhomenetworksoinsteadthisnetwork
couldbeprovidedbyavehicle.Thisvehiclewilltravelaroundacertaingeographicareain
whichthedeviceshavebeensentthespecialdownlinkmessagetoinitiatetheupdate.The
deviceswilllookfortheWiFinetworkbeingbroadcastbythevehicleandconnect.The
deviceswillthenconnecttoaserverrunningonthisWiFinetwork.Thisserver(alsoshown
inthisexample)willgeneratemanifestfilesthatinstructthedeviceonwhatitshouldupdate,
andwheretogettheupdatedatafrom.
Server
Codeavailablehere.
ThisscriptrunsaHTTPserveronport 8000thatprovisionsovertheair(OTA)update
manifestsinJSONformataswellasservingtheupdatecontent.Thisscriptshouldberunin
adirectorythatcontainseveryversionoftheenddevicescode,inthefollowingstructure:
4.2.15OTAupdate
189
-serverdirectory
|-this_script.py
|-1.0.0
||-flash
|||-lib
||||-lib_a.py
|||-main.py
|||-boot.py
||-sd
||-some_asset.txt
||-asset_that_will_be_removed.wav
|-1.0.1
||-flash
|||-lib
||||-lib_a.py
||||-new_lib.py
|||-main.py
|||-boot.py
||-sd
||-some_asset.txt
|-firmware_1.0.0.bin
|-firmware_1.0.1.bin
Thetopleveldirectorythatcontainsthisscriptcancontainoneoftwothings:
Updatedirectory:Theseshouldbenamedwithaversionnumbercompatiblewiththe
pythonLooseVersionversioningscheme
(http://epydoc.sourceforge.net/stdlib/distutils.version.LooseVersion-class.html).They
shouldcontaintheentirefilesystemoftheenddeviceforthecorrespondingversion
number.
Firmware:Thesefilesshouldbenamedintheformat firmare_VERSION.bin,where
VERSIONisaaversionnumbercompatiblewiththepythonLooseVersionversioning
scheme(http://epydoc.sourceforge.net/stdlib/distutils.version.LooseVersion-class.html).
Thisfileshouldbeintheformatofthe appimg.bincreatedbythePycomfirmwarebuild
scripts.
Howtouse
Oncethedirectoryhasbeensetupasdescribedaboveyousimplyneedtostartthisscript
usingpython3.OncestartedthisscriptwillrunaHTTPserveronport 8000(thiscanbe
changedbychangingthePORTvariable).Thisserverwillserveallthefilesindirectoryas
expectedalongwithoneadditionalspecialfile, manifest.json.Thisfiledoesnotexiston
4.2.15OTAupdate
190
thefilesystembutisinsteadgeneratedwhenrequestedandcontainstherequiredchanges
tobringtheenddevicefromitscurrentversiontothelatestavailableversion.Youcansee
anexampleofthisbypointingyourwebbrowserat:
http://127.0.0.1:8000/manifest.json?current_ver=1.0.0
The current_verfieldattheendoftheURLshouldbesettothecurrentfirmwareversionof
theenddevice.Thegeneratedmanifestwillcontainlistsofwhichfilesarenew,have
changedorneedtobedeletedalongwithSHA1hashesofthefiles.Belowisanexampleof
whatsuchamanifestmightlooklike:
{
"delete":[
"flash/old_file.py",
"flash/other_old_file.py"
],
"firmware":{
"URL":"http://192.168.1.144:8000/firmware_1.0.1b.bin",
"hash":"ccc6914a457eb4af8855ec02f6909316526bdd08"
},
"new":[
{
"URL":"http://192.168.1.144:8000/1.0.1b/flash/lib/new_lib.py",
"dst_path":"flash/lib/new_lib.py",
"hash":"1095df8213aac2983efd68dba9420c8efc9c7c4a"
}
],
"update":[
{
"URL":"http://192.168.1.144:8000/1.0.1b/flash/changed_file.py",
"dst_path":"flash/changed_file.py",
"hash":"1095df8213aac2983efd68dba9420c8efc9c7c4a"
}
],
"version":"1.0.1b"
}
Themanifestcontainsthefollowingfields:
delete:Alistofpathstofileswhicharenolongerneeded
firmware:TheURLandSHA1hashofthefirmwareimage
new:theURL,pathonenddeviceandSHA1hashofallnewfiles
update:theURL,pathonenddeviceandSHA1hashofallfileswhichexistedbefore
buthavechanged.
version:Theversionnumberthatthismanifestwillupdatetheclientto
previous_version:Theversiontheclientiscurrentlyonbeforeapplyingthisupdate
4.2.15OTAupdate
191
Note:Theversionnumberofthefilesmightnotbethesameasthefirmware.Thehighest
availableversionnumber,higherthanthecurrentclientversionisusedforbothfirmwareand
files.Thismaydifferbetweenthetwo.
InorderfortheURL'stobeproperlyformattedyouarerequiredtosenda"host"header
alongwithyourHTTPgetrequeste.g:
GET/manifest.json?current_ver=1.0.0HTTP/1.0\r\nHost:192.168.1.144:8000\r\n\r\n
ClientLibrary
AMicroPytonlibraryforinterfacingwiththeserverdescribedaboveisavailablehere.
Thislibraryissplitintotwolayers.Thetoplevel OTAclassimplementsallthehighlevel
functionalitysuchasparsingtheJSONfile,makingbackcopiesoffilesbeingupdated
incasetheupdatefails,etc.Thelayerofthelibraryisagnostictoyourchosentransport
method.Belowthisisthe WiFiOTAclass.Thisclassimplementstheactualtransport
mechanismofhowthedevicefetchesthefilesandupdatemanifest(viaWiFiastheclass
namesuggests).Thereasonforthissplitissothatthehighlevelfunctionalitycanbereused
regardlessofwhattransportmechanismyouendupusing.Thiscouldbeimplementedon
topofBluetoothforexample,ortheseverchangedfromHTTPtoFTP.
Althoughtheabovecodeisfunctional,itisprovidedonlyasanexampleofhowanend
usermightimplementaOTAupdatemechanism.Itisnot100%featurecompletee.g.
eventhoughitdoesbackuppreviousversionsoffiles,therollbackprocedureisnot
implemented.Thisisleftoftheendusertodo.
Example
Belowisamexampleimplementingthemethodologypreviouslyexplainedinthistutorialto
initiateanOTAupdate.
TheexamplebelowwillonlyworkonaPycomdevicewithLoRacapabilities.Ifwantto
testitoutonadevicewithoutLoRafunctionalitythensimplycommentoutanycode
relatingtoLoRa.Leavingjustthe WiFiOTAinitialisationandthey ota.connect()and
ota.update()
4.2.15OTAupdate
192
fromnetworkimportLoRa,WLAN
importsocket
importtime
fromOTAimportWiFiOTA
fromtimeimportsleep
importpycom
importubinascii
fromconfigimportWIFI_SSID,WIFI_PW,SERVER_IP
#TurnonGREENLED
pycom.heartbeat(False)
pycom.rgbled(0xff00)
#SetupOTA
ota=WiFiOTA(WIFI_SSID,
WIFI_PW,
SERVER_IP,#Updateserveraddress
8000)#Updateserverport
#TurnoffWiFitosavepower
w=WLAN()
w.deinit()
#InitialiseLoRainLORAWANmode.
lora=LoRa(mode=LoRa.LORAWAN,region=LoRa.EU868)
app_eui=ubinascii.unhexlify('70B3D57ED0008CD6')
app_key=ubinascii.unhexlify('B57F36D88691CEC5EE8659320169A61C')
#joinanetworkusingOTAA(OvertheAirActivation)
lora.join(activation=LoRa.OTAA,auth=(app_eui,app_key),timeout=0)
#waituntilthemodulehasjoinedthenetwork
whilenotlora.has_joined():
time.sleep(2.5)
print('Notyetjoined...')
#createaLoRasocket
s=socket.socket(socket.AF_LORA,socket.SOCK_RAW)
#settheLoRaWANdatarate
s.setsockopt(socket.SOL_LORA,socket.SO_DR,5)
#makethesocketblocking
#(waitsforthedatatobesentandforthe2receivewindowstoexpire)
s.setblocking(True)
whileTrue:
#sendsomedata
s.send(bytes([0x04,0x05,0x06]))
4.2.15OTAupdate
193
#makethesocketnon-blocking
#(becauseifthere'snodatareceiveditwillblockforever...)
s.setblocking(False)
#getanydatareceived(ifany...)
data=s.recv(64)
#SomesortofOTAtrigger
ifdata==bytes([0x01,0x02,0x03]):
print("PerformingOTA")
#PerformOTA
ota.connect()
ota.update()
sleep(5)
4.2.15OTAupdate
194
RMT
Detailedinformationaboutthisclasscanbefoundin RMT.
TheRMT(RemoteControl)peripheraloftheESP32isprimarilydesignedtosendand
receiveinfraredremotecontrolsignalsthatuseon-off-keyingofacarrierfrequency,butdue
toitsdesignitcanbeusedtogeneratevarioustypesofsignals,thisclasswillallowyouto
dothis.
TheRMThas7channels,ofwhich5areavailableandcanbemappedtoanyGPIOpin
(Note:Pins P13- P18canonlybeusedasinputs).
Channel Resolution MaximumPulseWidth
0 Usedbyon-boardLED
1 Usedby pycom.pulses_get()
2 100nS 3.2768ms
3 100nS 3.2768ms
4 1000nS 32.768ms
5 1000nS 32.768ms
6 3125nS 102.4ms
7 3125nS 102.4ms
Transmitting
ThefollowingexamplescreateanRMTobjectonchannel4,configureitfortransmission
andsendsomedatainvariousforms.Theresolutionofchannel4is1000nanoseconds,the
givenvaluesareinterpretedaccordingly.
Inthisfirstexample,wedefinethesignalasatupleofbinaryvaluesthatdefinetheshapeof
thedesiredsignalalongwiththedurationofabit.
4.2.16RMT
195
frommachineimportRMT
#MapRMTchannel4toP21,whentheRMTisidle,itwilloutputLOW
rmt=RMT(channel=4,gpio="P21",tx_idle_level=RMT.LOW)
#Producesthepatternshownindata,whereeachbitlasts
#duration*channelresolution=10000*1000ns=10ms
data=(1,0,1,1,1,0,1,0,1)
duration=10000
rmt.pulses_send(duration,data)
Inthisexamplewedefinethesignalbyatupleofdurationsandwhatstatethesignalstarts
in.
frommachineimportRMT
#MapRMTchannel4toP21,whentheRMTisidle,itwilloutputLOW
rmt=RMT(channel=4,gpio="P21",tx_idle_level=RMT.LOW)
#Thelistofdurationsforeachpulsetobe,theseareinunitsofthechannels
#resolution:
#duration=Desiredpulselength/ChannelResolution
duration=(8000,11000,8000,11000,6000,13000,6000,3000,8000)
#`start_level`definesifthesignalstartsoffasLOWorHIGH,itwillthen
#togglestatebetweeneachduration
rmt.pulses_send(duration,start_level=RMT.HIGH)
4.2.16RMT
196
Thisthirdexample,isacombinationoftheabovetwostylesofdefiningasignal.Eachpulse
hasadefineddurationaswellasastate.Thisisusefulifyoudon'talwayswantthesignalto
togglestate.
frommachineimportRMT
#MapRMTchannel4toP21,whentheRMTisidle,itwilloutputLOW
rmt=RMT(channel=4,gpio="P21",tx_idle_level=RMT.LOW)
#Producesthepatternshownindata,whereeachbitlasts
#duration[i]*channelresolution=duration[i]*1000ns
data=(1,0,1,1,0,1)
duration=(400,200,100,300,200,400)
rmt.pulses_send(duration,data)
ThefollowingexamplecreatesanRMTobjectonchannel4andconfiguresitfor
transmissionwithcarriermodulation.
frommachineimportRMT
rmt=RMT(channel=4,
gpio="P21",
tx_idle_level=RMT.LOW,
#Carrier=100Hz,80%duty,modulesHIGHsignals
tx_carrier=(100,70,RMT.HIGH))
data=(1,0,1)
duration=10000
rmt.pulses_send(duration,data)
4.2.16RMT
197
ThefollowingexamplecreatesanRMTobjectonchannel2,configuresitforreceiving,then
waitsforthefirst,undefinednumberofpulseswithouttimeout
frommachineimportRMT
rmt=machine.RMT(channel=2)
rmt.init(gpio="P21",rx_idle_threshold=1000)
data=rmt.pulses_get()
If tx_idle_levelisnotsettotheoppositeofthethirdvalueinthe tx_carriertuple,
thecarrierwavewillcontinuetobegeneratedwhentheRMTchannelisidle.
Receiving
ThefollowingexamplecreatesanRMTobjectonchannel2,configuresitforreceivinga
undefinednumberofpulses,thenwaitsmaximumof1000usforthefirstpulse.
frommachineimportRMT
#SetsRMTchannel2toP21andsetsthemaximumlengthofavalidpulseto
#1000*channelresolution=1000*100ns=100us
rmt=machine.RMT(channel=2,gpio="P21",rx_idle_threshold=1000)
rmt.init()
#Getaundefinednumberofpulses,waitingamaximumof500usforthefirst
#pulse(unlikeotherplaceswheretheabsolutedurationwasbasedontheRMT
#channelsresolution,thisvalueisinus)untilapulselongerthan
#rx_idle_thresholdoccurs.
data=rmt.pulses_get(timeout=500)
ThefollowingexamplecreatesanRMTobjectonchannel2,configuresitforreceiving,filters
outpulseswithwidth<20*100nanoseconds,thenwaitsfor100pulses
4.2.16RMT
198
frommachineimportRMT
rmt=machine.RMT(channel=2,#Resolution=100ns
gpio="P21",
#Longestvalidpulse=1000*100ns=100us
rx_idle_threshold=1000,
#Filteroutpulsesshorterthan20*100ns=2us
rx_filter_threshold=20)
#Receive100pulses,pulsesshorterthan2usorlongerthan100uswillbe
#ignored.Thatmeansifitreceives80validpulsesbutthenthesignal
#doesn'tchangefor10hoursandthen20morepulsesoccur,thisfunction
#willwaitfor10h
data=rmt.pulses_get(pulses=100)
4.2.16RMT
199
LoPyTutorials
ThefollowingtutorialsdemonstratetheuseoftheLoRafunctionalityontheLoPy.LoRacan
workin2differentmodes;LoRa-MAC(whichwealsocallRaw-LoRa)andLoRaWANmode.
LoRa-MACmodebasicallyaccessesderadiodirectlyandpacketsaresentusingtheLoRa
modulationontheselectedfrequencywithoutanyheaders,addressinginformationor
encryption.OnlyaCRCisaddedatthetailofthepacketandthisisremovedbeforethe
receivedframeispassedontotheapplication.Thismodecanbeusedtobuildanyhigher
levelprotocolthatcanbenefitfromthelongrangefeaturesoftheLoRamodulation.Typical
usescasesincludeLoPytoLoPydirectcommunicationandaLoRapacketforwarder.
LoRaWANmodeimplementsthefullLoRaWANstackforaclassAdevice.Itsupportsboth
OTAAandABPconnectionmethods,aswellasadvancedfeatureslikeaddingandremoving
customchannelstosupport"special"frequenciesplanslikethethoseusedinNewZealand.
4.3LoRaExamples
200
LoRa-MAC(RawLoRa)
BasicLoRaconnectionexample,sendingandreceivingdata.InLoRa-MACmodethe
LoRaWANlayerisbypassedandtheradioisuseddirectly.Thedatasentisnotformattedor
encryptedinanyway,andnoaddressinginformationisaddedtotheframe.
Fortheexamplebelow,youwillneedtwoLoPys.A whileloopwitharandomdelaytimeis
usedtominimisethechancesofthe2LoPy’stransmittingatthesametime.Runthecode
belowonthe2LoPymodulesandyouwillseetheword'Hello'beingreceivedonbothsides.
fromnetworkimportLoRa
importsocket
importmachine
importtime
#initialiseLoRainLORAmode
#Pleasepicktheregionthatmatcheswhereyouareusingthedevice:
#Asia=LoRa.AS923
#Australia=LoRa.AU915
#Europe=LoRa.EU868
#UnitedStates=LoRa.US915
#moreparamscanalsobegiven,likefrequency,txpowerandspreadingfactor
lora=LoRa(mode=LoRa.LORA,region=LoRa.EU868)
#createarawLoRasocket
s=socket.socket(socket.AF_LORA,socket.SOCK_RAW)
whileTrue:
#sendsomedata
s.setblocking(True)
s.send('Hello')
#getanydatareceived...
s.setblocking(False)
data=s.recv(64)
print(data)
#waitarandomamountoftime
time.sleep(machine.rng()&0x0F)
4.3.1LoRa-MAC(RawLoRa)
201
LoRaWAN(OTAA)
OTAAstandsforOverTheAirAuthentication.WiththismethodtheLoPysendsaJoin
requesttotheLoRaWANGatewayusingthe APPEUIand APPKEYprovided.Ifthekeysare
correcttheGatewaywillreplytotheLoPywithajoinacceptmessageandfromthatpointon
theLoPyisabletosendandreceivepacketsto/fromtheGateway.Ifthekeysareincorrect
noresponsewillbereceivedandthe has_joined()methodwillalwaysreturn False.
Theexamplebelowattemptstogetanydatareceivedaftersendingtheframe.Keepinmind
thattheGatewaymightnotbesendinganydataback,thereforewemakethesocketnon-
blockingbeforeattemptingtoreceive,inordertopreventgettingstuckwaitingforapacket
thatwillneverarrive.
4.3.2LoRaWANwithOTAA
202
fromnetworkimportLoRa
importsocket
importtime
importubinascii
#InitialiseLoRainLORAWANmode.
#Pleasepicktheregionthatmatcheswhereyouareusingthedevice:
#Asia=LoRa.AS923
#Australia=LoRa.AU915
#Europe=LoRa.EU868
#UnitedStates=LoRa.US915
lora=LoRa(mode=LoRa.LORAWAN,region=LoRa.EU868)
#createanOTAAauthenticationparameters
app_eui=ubinascii.unhexlify('ADA4DAE3AC12676B')
app_key=ubinascii.unhexlify('11B0282A189B75B0B4D2D8C7FA38548B')
#joinanetworkusingOTAA(OvertheAirActivation)
lora.join(activation=LoRa.OTAA,auth=(app_eui,app_key),timeout=0)
#waituntilthemodulehasjoinedthenetwork
whilenotlora.has_joined():
time.sleep(2.5)
print('Notyetjoined...')
#createaLoRasocket
s=socket.socket(socket.AF_LORA,socket.SOCK_RAW)
#settheLoRaWANdatarate
s.setsockopt(socket.SOL_LORA,socket.SO_DR,5)
#makethesocketblocking
#(waitsforthedatatobesentandforthe2receivewindowstoexpire)
s.setblocking(True)
#sendsomedata
s.send(bytes([0x01,0x02,0x03]))
#makethesocketnon-blocking
#(becauseifthere'snodatareceiveditwillblockforever...)
s.setblocking(False)
#getanydatareceived(ifany...)
data=s.recv(64)
print(data)
4.3.2LoRaWANwithOTAA
203
LoRaWAN(ABP)
ABPstandsforAuthenticationByPersonalisation.Itmeansthattheencryptionkeysare
configuredmanuallyonthedeviceandcanstartsendingframestotheGatewaywithout
needinga'handshake'proceduretoexchangethekeys(suchastheoneperformedduring
anOTAAjoinprocedure).
Theexamplebelowattemptstogetanydatareceivedaftersendingtheframe.Keepinmind
thattheGatewaymightnotbesendinganydataback,thereforewemakethesocketnon-
blockingbeforeattemptingtoreceive,inordertopreventgettingstuckwaitingforapacket
thatwillneverarrive.
4.3.3LoRaWANwithABP
204
fromnetworkimportLoRa
importsocket
importubinascii
importstruct
#InitialiseLoRainLORAWANmode.
#Pleasepicktheregionthatmatcheswhereyouareusingthedevice:
#Asia=LoRa.AS923
#Australia=LoRa.AU915
#Europe=LoRa.EU868
#UnitedStates=LoRa.US915
lora=LoRa(mode=LoRa.LORAWAN,region=LoRa.EU868)
#createanABPauthenticationparams
dev_addr=struct.unpack(">l",binascii.unhexlify('00000005'))[0]
nwk_swkey=ubinascii.unhexlify('2B7E151628AED2A6ABF7158809CF4F3C')
app_swkey=ubinascii.unhexlify('2B7E151628AED2A6ABF7158809CF4F3C')
#joinanetworkusingABP(ActivationByPersonalization)
lora.join(activation=LoRa.ABP,auth=(dev_addr,nwk_swkey,app_swkey))
#createaLoRasocket
s=socket.socket(socket.AF_LORA,socket.SOCK_RAW)
#settheLoRaWANdatarate
s.setsockopt(socket.SOL_LORA,socket.SO_DR,5)
#makethesocketblocking
#(waitsforthedatatobesentandforthe2receivewindowstoexpire)
s.setblocking(True)
#sendsomedata
s.send(bytes([0x01,0x02,0x03]))
#makethesocketnon-blocking
#(becauseifthere'snodatareceiveditwillblockforever...)
s.setblocking(False)
#getanydatareceived(ifany...)
data=s.recv(64)
print(data)
4.3.3LoRaWANwithABP
205
LoRaNano-Gateway(RawLoRa)
ThisexampleallowsarawLoRaconnectionbetweentwoLoPys(nodes)toasingleLoPy
actingasaNano-Gateway.
Formoreinformationanddiscussionsaboutthiscode,seethisforumpost.
GatewayCode
importsocket
importstruct
fromnetworkimportLoRa
#Abasicpackageheader,B:1byteforthedeviceId,B:1byteforthepkgsize,%ds:
Formattedstringforstring
_LORA_PKG_FORMAT="!BB%ds"
#Abasicackpackage,B:1byteforthedeviceId,B:1byteforthepkgsize,B:1by
tefortheOk(200)orerrormessages
_LORA_PKG_ACK_FORMAT="BBB"
#OpenaLoRaSocket,userx_iqtoavoidlisteningtoourownmessages
#Pleasepicktheregionthatmatcheswhereyouareusingthedevice:
#Asia=LoRa.AS923
#Australia=LoRa.AU915
#Europe=LoRa.EU868
#UnitedStates=LoRa.US915
lora=LoRa(mode=LoRa.LORA,rx_iq=True,region=LoRa.EU868)
lora_sock=socket.socket(socket.AF_LORA,socket.SOCK_RAW)
lora_sock.setblocking(False)
while(True):
recv_pkg=lora_sock.recv(512)
if(len(recv_pkg)>2):
recv_pkg_len=recv_pkg[1]
device_id,pkg_len,msg=struct.unpack(_LORA_PKG_FORMAT%recv_pkg_len,recv_
pkg)
#Iftheuart=machine.UART(0,115200)andos.dupterm(uart)aresetintheboot.pyth
isprintshouldappearintheserialport
print('Device:%d-Pkg:%s'%(device_id,msg))
ack_pkg=struct.pack(_LORA_PKG_ACK_FORMAT,device_id,1,200)
lora_sock.send(ack_pkg)
4.3.4LoRa-MACNano-Gateway
206
importos
importsocket
importtime
importstruct
fromnetworkimportLoRa
#Abasicpackageheader,B:1byteforthedeviceId,B:1byteforthepkgsize
_LORA_PKG_FORMAT="BB%ds"
_LORA_PKG_ACK_FORMAT="BBB"
DEVICE_ID=0x01
#OpenaLoraSocket,usetx_iqtoavoidlisteningtoourownmessages
#Pleasepicktheregionthatmatcheswhereyouareusingthedevice:
#Asia=LoRa.AS923
#Australia=LoRa.AU915
#Europe=LoRa.EU868
#UnitedStates=LoRa.US915
lora=LoRa(mode=LoRa.LORA,tx_iq=True,region=LoRa.EU868)
lora_sock=socket.socket(socket.AF_LORA,socket.SOCK_RAW)
lora_sock.setblocking(False)
while(True):
#Packagesendcontainingasimplestring
msg="Device1Here"
pkg=struct.pack(_LORA_PKG_FORMAT%len(msg),DEVICE_ID,len(msg),msg)
lora_sock.send(pkg)
#Waitfortheresponsefromthegateway.NOTE:Forthisdemothedevicedoesani
nfiniteloopforwhilewaitingtheresponse.Introduceamax_time_waitingforyouappl
ication
waiting_ack=True
while(waiting_ack):
recv_ack=lora_sock.recv(256)
if(len(recv_ack)>0):
device_id,pkg_len,ack=struct.unpack(_LORA_PKG_ACK_FORMAT,recv_ack)
if(device_id==DEVICE_ID):
if(ack==200):
waiting_ack=False
#Iftheuart=machine.UART(0,115200)andos.dupterm(uart)ares
etintheboot.pythisprintshouldappearintheserialport
print("ACK")
else:
waiting_ack=False
#Iftheuart=machine.UART(0,115200)andos.dupterm(uart)ares
etintheboot.pythisprintshouldappearintheserialport
print("MessageFailed")
time.sleep(5)
4.3.4LoRa-MACNano-Gateway
208
Thenodeisalwayssendingpackagesandwaitingforthe ackfromthegateway.
Toadaptthiscodetouserspecificneeds:
Putamaxwaitingtimeforthe acktoarriveandresendthepackageormarkitas
invalid
Increasethepackagesizechangingthe _LORA_PKG_FORMATto BH%ds.The Hwill
allowthekeepingof2bytesforsize(formoreinformationaboutstructformat)
Reducethepackagesizewithbitwisemanipulation
Reducethemessagesize(forthisdemo,astring)tosomethingmoreusefulfor
specificdevelopment
4.3.4LoRa-MACNano-Gateway
209
LoRaModuletoModuleConnection
ThisexampleshowshowtoconnecttwoPycodeLoRacapablemodules(nodes)viaraw
LoRa.
NodeA
fromnetworkimportLoRa
importsocket
importtime
#Pleasepicktheregionthatmatcheswhereyouareusingthedevice:
#Asia=LoRa.AS923
#Australia=LoRa.AU915
#Europe=LoRa.EU868
#UnitedStates=LoRa.US915
lora=LoRa(mode=LoRa.LORA,region=LoRa.EU868)
s=socket.socket(socket.AF_LORA,socket.SOCK_RAW)
s.setblocking(False)
whileTrue:
ifs.recv(64)==b'Ping':
s.send('Pong')
time.sleep(5)
NodeB
fromnetworkimportLoRa
importsocket
importtime
#Pleasepicktheregionthatmatcheswhereyouareusingthedevice:
#Asia=LoRa.AS923
#Australia=LoRa.AU915
#Europe=LoRa.EU868
#UnitedStates=LoRa.US915
lora=LoRa(mode=LoRa.LORA,region=LoRa.EU868)
s=socket.socket(socket.AF_LORA,socket.SOCK_RAW)
s.setblocking(False)
whileTrue:
s.send('Ping')
time.sleep(5)
4.3.5LoPytoLoPy
210
4.3.5LoPytoLoPy
211
LoRaWANNano-Gateway
ThisexampleallowstoconnectaLoPytoaLoRaWANnetworksuchasTheThingsNetwork
(TTN)orLoriottobeusedasanano-gateway.
ThisexampleusessettingsspecificallyforconnectingtoTheThingsNetworkwithinthe
European868MHzregion.Foranotherusage,pleaseseethe config.pyfileforrelevant
sectionsthatneedchanging.
UptodateversionsofthesesnippetscanbefoundatthefollowingGitHubRepository.For
moreinformationanddiscussionaboutthiscode,seethisforumpost.
Nano-Gateway
TheNano-Gatewaycodeissplitinto3files, main.py, config.pyand nanogateway.py.
Theseareusedtoconfigureandspecifyhowthegatewaywillconnecttoapreferred
networkandhowitcanactaspacketforwarder.
GatewayID
MostLoRaWANnetworkserversexpectaGatewayIDintheformofaunique64-bit
hexadecimalnumber(calledaEUI-64).TherecommendedpracticeistoproducethisID
fromyourboardbyexpandingtheWiFiMACaddress(a48-bitnumber,calledMAC-48).You
canobtainthatbyrunningthiscodepriortoconfiguration:
fromnetworkimportWLAN
importubinascii
wl=WLAN()
ubinascii.hexlify(wl.mac())[:6]+'FFFE'+ubinascii.hexlify(wl.mac())[6:]
Theresultwillbysomethinglike b'240ac4FFFE008d88'where 240ac4FFFE008d88isyour
GatewayIDtobeusedinyournetworkproviderconfiguration.
Main( main.py)
Thisfilerunsatbootandcallsthelibraryand config.pyfilestoinitialisethenano-gateway.
Onceconfigurationisset,thenano-gatewayisthenstarted.
4.3.6LoRaWANNano-Gateway
212
"""LoPyLoRaWANNanoGatewayexampleusage"""
importconfig
fromnanogatewayimportNanoGateway
if__name__=='__main__':
nanogw=NanoGateway(
id=config.GATEWAY_ID,
frequency=config.LORA_FREQUENCY,
datarate=config.LORA_GW_DR,
ssid=config.WIFI_SSID,
password=config.WIFI_PASS,
server=config.SERVER,
port=config.PORT,
ntp_server=config.NTP,
ntp_period=config.NTP_PERIOD_S
)
nanogw.start()
nanogw._log('YoumaynowpressENTERtoentertheREPL')
input()
Configuration( config.py)
Thisfilecontainssettingsfortheserverandnetworkitisconnectingto.Dependingonthe
nano-gatewayregionandprovider(TTN,Loriot,etc.)thesewillvary.Theprovidedexample
willworkwithTheThingsNetwork(TTN)intheEuropean,868Mhz,region.
TheGatewayIDisgeneratedinthescriptusingtheprocessdescribedabove.
PleasechangetheWIFI_SSIDandWIFI_PASSvariablestomatchyourdesiredWiFi
network
4.3.6LoRaWANNano-Gateway
213
"""LoPyLoRaWANNanoGatewayconfigurationoptions"""
importmachine
importubinascii
WIFI_MAC=ubinascii.hexlify(machine.unique_id()).upper()
#SettheGatewayIDtobethefirst3bytesofMACaddress+'FFFE'+last3byteso
fMACaddress
GATEWAY_ID=WIFI_MAC[:6]+"FFFE"+WIFI_MAC[6:12]
SERVER='router.eu.thethings.network'
PORT=1700
NTP="pool.ntp.org"
NTP_PERIOD_S=3600
WIFI_SSID='my-wifi'
WIFI_PASS='my-wifi-password'
#forEU868
LORA_FREQUENCY=868100000
LORA_GW_DR="SF7BW125"#DR_5
LORA_NODE_DR=5
#forUS915
#LORA_FREQUENCY=903900000
#LORA_GW_DR="SF7BW125"#DR_3
#LORA_NODE_DR=3
Library( nanogateway.py)
Thenano-gatewaylibrarycontrolsallofthepacketgenerationandforwardingfortheLoRa
data.Thisdoesnotrequireanyuserconfigurationandthelatestversionofthiscodeshould
bedownloadedfromthePycomGitHubRepository.
"""LoPyNanoGatewayclass"""
fromnetworkimportWLAN
fromnetworkimportLoRa
frommachineimportTimer
importos
importubinascii
importmachine
importjson
importtime
importerrno
import_thread
importsocket
4.3.6LoRaWANNano-Gateway
214
PROTOCOL_VERSION=const(2)
PUSH_DATA=const(0)
PUSH_ACK=const(1)
PULL_DATA=const(2)
PULL_ACK=const(4)
PULL_RESP=const(3)
TX_ERR_NONE="NONE"
TX_ERR_TOO_LATE="TOO_LATE"
TX_ERR_TOO_EARLY="TOO_EARLY"
TX_ERR_COLLISION_PACKET="COLLISION_PACKET"
TX_ERR_COLLISION_BEACON="COLLISION_BEACON"
TX_ERR_TX_FREQ="TX_FREQ"
TX_ERR_TX_POWER="TX_POWER"
TX_ERR_GPS_UNLOCKED="GPS_UNLOCKED"
STAT_PK={"stat":{"time":"","lati":0,
"long":0,"alti":0,
"rxnb":0,"rxok":0,
"rxfw":0,"ackr":100.0,
"dwnb":0,"txnb":0}}
RX_PK={"rxpk":[{"time":"","tmst":0,
"chan":0,"rfch":0,
"freq":868.1,"stat":1,
"modu":"LORA","datr":"SF7BW125",
"codr":"4/5","rssi":0,
"lsnr":0,"size":0,
"data":""}]}
TX_ACK_PK={"txpk_ack":{"error":""}}
classNanoGateway:
def__init__(self,id,frequency,datarate,ssid,password,server,port,ntp='poo
l.ntp.org',ntp_period=3600):
self.id=id
self.frequency=frequency
self.sf=self._dr_to_sf(datarate)
self.ssid=ssid
self.password=password
self.server=server
self.port=port
self.ntp=ntp
self.ntp_period=ntp_period
self.rxnb=0
self.rxok=0
self.rxfw=0
self.dwnb=0
4.3.6LoRaWANNano-Gateway
215
self.txnb=0
self.stat_alarm=None
self.pull_alarm=None
self.uplink_alarm=None
self.udp_lock=_thread.allocate_lock()
self.lora=None
self.lora_sock=None
defstart(self):
#ChangeWiFitoSTAmodeandconnect
self.wlan=WLAN(mode=WLAN.STA)
self._connect_to_wifi()
#GetatimeSync
self.rtc=machine.RTC()
self.rtc.ntp_sync(self.ntp,update_period=self.ntp_period)
#GettheserverIPandcreateanUDPsocket
self.server_ip=socket.getaddrinfo(self.server,self.port)[0][-1]
self.sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM,socket.IPPROTO_UD
P)
self.sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
self.sock.setblocking(False)
#Pushthefirsttimeimmediately
self._push_data(self._make_stat_packet())
#Createthealarms
self.stat_alarm=Timer.Alarm(handler=lambdat:self._push_data(self._make_sta
t_packet()),s=60,periodic=True)
self.pull_alarm=Timer.Alarm(handler=lambdau:self._pull_data(),s=25,perio
dic=True)
#StarttheUDPreceivethread
_thread.start_new_thread(self._udp_thread,())
#InitializeLoRainLORAmode
self.lora=LoRa(mode=LoRa.LORA,frequency=self.frequency,bandwidth=LoRa.BW_1
25KHZ,sf=self.sf,
preamble=8,coding_rate=LoRa.CODING_4_5,tx_iq=True)
#CreatearawLoRasocket
self.lora_sock=socket.socket(socket.AF_LORA,socket.SOCK_RAW)
self.lora_sock.setblocking(False)
self.lora_tx_done=False
self.lora.callback(trigger=(LoRa.RX_PACKET_EVENT|LoRa.TX_PACKET_EVENT),hand
ler=self._lora_cb)
defstop(self):
#TODO:CheckhowtostoptheNTPsync
4.3.6LoRaWANNano-Gateway
216
#TODO:Createacancelmethodforthealarm
#TODO:killtheUDPthread
self.sock.close()
def_connect_to_wifi(self):
self.wlan.connect(self.ssid,auth=(None,self.password))
whilenotself.wlan.isconnected():
time.sleep(0.5)
print("WiFiconnected!")
def_dr_to_sf(self,dr):
sf=dr[2:4]
ifsf[1]notin'0123456789':
sf=sf[:1]
returnint(sf)
def_sf_to_dr(self,sf):
return"SF7BW125"
def_make_stat_packet(self):
now=self.rtc.now()
STAT_PK["stat"]["time"]="%d-%02d-%02d%02d:%02d:%02dGMT"%(now[0],now[1],
now[2],now[3],now[4],now[5])
STAT_PK["stat"]["rxnb"]=self.rxnb
STAT_PK["stat"]["rxok"]=self.rxok
STAT_PK["stat"]["rxfw"]=self.rxfw
STAT_PK["stat"]["dwnb"]=self.dwnb
STAT_PK["stat"]["txnb"]=self.txnb
returnjson.dumps(STAT_PK)
def_make_node_packet(self,rx_data,rx_time,tmst,sf,rssi,snr):
RX_PK["rxpk"][0]["time"]="%d-%02d-%02dT%02d:%02d:%02d.%dZ"%(rx_time[0],rx
_time[1],rx_time[2],rx_time[3],rx_time[4],rx_time[5],rx_time[6])
RX_PK["rxpk"][0]["tmst"]=tmst
RX_PK["rxpk"][0]["datr"]=self._sf_to_dr(sf)
RX_PK["rxpk"][0]["rssi"]=rssi
RX_PK["rxpk"][0]["lsnr"]=float(snr)
RX_PK["rxpk"][0]["data"]=ubinascii.b2a_base64(rx_data)[:-1]
RX_PK["rxpk"][0]["size"]=len(rx_data)
returnjson.dumps(RX_PK)
def_push_data(self,data):
token=os.urandom(2)
packet=bytes([PROTOCOL_VERSION])+token+bytes([PUSH_DATA])+ubinascii.un
hexlify(self.id)+data
withself.udp_lock:
try:
self.sock.sendto(packet,self.server_ip)
exceptException:
print("PUSHexception")
def_pull_data(self):
token=os.urandom(2)
4.3.6LoRaWANNano-Gateway
217
packet=bytes([PROTOCOL_VERSION])+token+bytes([PULL_DATA])+ubinascii.un
hexlify(self.id)
withself.udp_lock:
try:
self.sock.sendto(packet,self.server_ip)
exceptException:
print("PULLexception")
def_ack_pull_rsp(self,token,error):
TX_ACK_PK["txpk_ack"]["error"]=error
resp=json.dumps(TX_ACK_PK)
packet=bytes([PROTOCOL_VERSION])+token+bytes([PULL_ACK])+ubinascii.unh
exlify(self.id)+resp
withself.udp_lock:
try:
self.sock.sendto(packet,self.server_ip)
exceptException:
print("PULLRSPACKexception")
def_lora_cb(self,lora):
events=lora.events()
ifevents&LoRa.RX_PACKET_EVENT:
self.rxnb+=1
self.rxok+=1
rx_data=self.lora_sock.recv(256)
stats=lora.stats()
self._push_data(self._make_node_packet(rx_data,self.rtc.now(),stats.time
stamp,stats.sf,stats.rssi,stats.snr))
self.rxfw+=1
ifevents&LoRa.TX_PACKET_EVENT:
self.txnb+=1
lora.init(mode=LoRa.LORA,frequency=self.frequency,bandwidth=LoRa.BW_125K
HZ,
sf=self.sf,preamble=8,coding_rate=LoRa.CODING_4_5,tx_iq=True)
def_send_down_link(self,data,tmst,datarate,frequency):
self.lora.init(mode=LoRa.LORA,frequency=frequency,bandwidth=LoRa.BW_125KHZ,
sf=self._dr_to_sf(datarate),preamble=8,coding_rate=LoRa.CODING
_4_5,
tx_iq=True)
whiletime.ticks_us()<tmst:
pass
self.lora_sock.send(data)
def_udp_thread(self):
whileTrue:
try:
data,src=self.sock.recvfrom(1024)
_token=data[1:3]
_type=data[3]
if_type==PUSH_ACK:
print("Pushack")
elif_type==PULL_ACK:
4.3.6LoRaWANNano-Gateway
218
print("Pullack")
elif_type==PULL_RESP:
self.dwnb+=1
ack_error=TX_ERR_NONE
tx_pk=json.loads(data[4:])
tmst=tx_pk["txpk"]["tmst"]
t_us=tmst-time.ticks_us()-5000
ift_us<0:
t_us+=0xFFFFFFFF
ift_us<20000000:
self.uplink_alarm=Timer.Alarm(handler=lambdax:self._send_d
own_link(ubinascii.a2b_base64(tx_pk["txpk"]["data"]),
tx_pk["txpk"]["tmst"]-10,tx_pk["txpk"]["datr"],
int(tx_pk["txpk"]["freq"]*1000000)),us=t_us)
else:
ack_error=TX_ERR_TOO_LATE
print("Downlinktimestamperror!,t_us:",t_us)
self._ack_pull_rsp(_token,ack_error)
print("Pullrsp")
exceptsocket.timeout:
pass
exceptOSErrorase:
ife.errno==errno.EAGAIN:
pass
else:
print("UDPrecvOSErrorException")
exceptException:
print("UDPrecvException")
#Waitbeforetryingtoreceiveagain
time.sleep(0.025)
RegisteringwithTTN
TosetupthegatewaywithTheThingsNetwork(TTN),navigatetotheirwebsiteand
create/registeranaccount.Enterausernameandanemailaddresstoverifywiththeir
platform.
4.3.6LoRaWANNano-Gateway
219
Onceanaccounthasbeenregistered,thenano-gatewaycanthenberegistered.Todothis,
navigatetotheTTNConsolewebpage.
RegisteringtheGateway
InsidetheTTNConsole,therearetwooptions, applicationsand gateways.Select
gatewaysandthenclickon registergateway.Thiswillallowforthesetupandregistration
ofanewnano-gateway.
4.3.6LoRaWANNano-Gateway
220
OntheRegisterGatewaypage,youwillneedtosetthefollowingsettings:
Theseareuniquetoeachgateway,locationandcountryspecificfrequency.Pleaseverify
thatcorrectsettingsareselectedotherwisethegatewaywillnotconnecttoTTN.
Youneedtotickthe"I'musingthelegacypacketforwarder"toenabletheright
settings.ThisisbecausetheNano-Gatewayusesthe'defacto'standardSemtechUDP
protocol.
4.3.6LoRaWANNano-Gateway
221
Option Value
Protocol PacketForwarder
GatewayEUI UserDefined(mustmatch config.py)
Description UserDefined
FrequencyPlan SelectCountry(e.g.EU-868MHz)
Location UserDefined
AntennaPlacement IndoororOutdoor
TheGatewayEUIshouldmatchyourGatewayIDfromthe config.pyfile.Wesuggestyou
followtheproceduredescribednearthetopofthisdocumenttocreateyourownunique
GatewayID.
Oncethesesettingshavebeenapplied,click RegisterGateway.AGatewayOverviewpage
willappear,withtheconfigurationsettingsshowing.Nextclickonthe GatewaySettingsand
configuretheRouteraddresstomatchthatofthegateway(default:
router.eu.thethings.network).
The Gatewayshouldnowbeconfigured.Next,oneormorenodescannowbeconfiguredto
usethenano-gatewayandTTNapplicationsmaybebuilt.
LoPyNode
4.3.6LoRaWANNano-Gateway
222
TherearetwomethodsofconnectingLoPydevicestothenano-gateway,OvertheAir
Activation(OTAA)andActivationByPersonalisation(ABP).Thecodeandinstructionsfor
registeringthesemethodsareshownbelow,followedbyinstructionforhowtoconnectthem
toanapplicationonTTN.
It’simportantthatthefollowingcodeexamples(alsoonGitHub)areusedtoconnectto
thenano-gatewayasitonlysupportssinglechannelconnections.
OTAA(OverTheAirActivation)
WhentheLoPyconnectsanapplication(viaTTN)usingOTAA,thenetworkconfigurationis
derivedautomaticallyduringahandshakebetweentheLoPyandnetworkserver.Notethat
thenetworkkeysderivedusingtheOTAAmethodologyarespecifictothedeviceandare
usedtoencryptandverifytransmissionsatthenetworklevel.
"""OTAANodeexamplecompatiblewiththeLoPyNanoGateway"""
fromnetworkimportLoRa
importsocket
importubinascii
importstruct
importtime
#InitializeLoRainLORAWANmode.
lora=LoRa(mode=LoRa.LORAWAN)
#createanOTAauthenticationparams
dev_eui=ubinascii.unhexlify('AABBCCDDEEFF7778')#thesesettingscanbefoundfromT
TN
app_eui=ubinascii.unhexlify('70B3D57EF0003BFD')#thesesettingscanbefoundfromT
TN
app_key=ubinascii.unhexlify('36AB7625FE77776881683B495300FFD6')#thesesettingscan
befoundfromTTN
#setthe3defaultchannelstothesamefrequency(mustbebeforesendingtheOTAAjo
inrequest)
lora.add_channel(0,frequency=868100000,dr_min=0,dr_max=5)
lora.add_channel(1,frequency=868100000,dr_min=0,dr_max=5)
lora.add_channel(2,frequency=868100000,dr_min=0,dr_max=5)
#joinanetworkusingOTAA
lora.join(activation=LoRa.OTAA,auth=(dev_eui,app_eui,app_key),timeout=0)
#waituntilthemodulehasjoinedthenetwork
whilenotlora.has_joined():
time.sleep(2.5)
4.3.6LoRaWANNano-Gateway
223
print('Notjoinedyet...')
#removeallthenon-defaultchannels
foriinrange(3,16):
lora.remove_channel(i)
#createaLoRasocket
s=socket.socket(socket.AF_LORA,socket.SOCK_RAW)
#settheLoRaWANdatarate
s.setsockopt(socket.SOL_LORA,socket.SO_DR,5)
#makethesocketnon-blocking
s.setblocking(False)
time.sleep(5.0)
"""Yourowncodecanbewrittenbelow!"""
foriinrange(200):
s.send(b'PKT#'+bytes([i]))
time.sleep(4)
rx=s.recv(256)
ifrx:
print(rx)
time.sleep(6)
ABP(ActivationByPersonalisation)
UsingABPjoinmoderequirestheusertodefinethefollowingvaluesandinputtheminto
boththeLoPyandtheTTNApplication:
DeviceAddress
ApplicationSessionKey
NetworkSessionKey
4.3.6LoRaWANNano-Gateway
224
"""ABPNodeexamplecompatiblewiththeLoPyNanoGateway"""
fromnetworkimportLoRa
importsocket
importubinascii
importstruct
importtime
#InitialiseLoRainLORAWANmode.
lora=LoRa(mode=LoRa.LORAWAN)
#createanABPauthenticationparams
dev_addr=struct.unpack(">l",ubinascii.unhexlify('2601147D'))[0]#thesesettingsca
nbefoundfromTTN
nwk_swkey=ubinascii.unhexlify('3C74F4F40CAE2221303BC24284FCF3AF')#thesesettingsc
anbefoundfromTTN
app_swkey=ubinascii.unhexlify('0FFA7072CC6FF69A102A0F39BEB0880F')#thesesettingsc
anbefoundfromTTN
#joinanetworkusingABP(ActivationByPersonalisation)
lora.join(activation=LoRa.ABP,auth=(dev_addr,nwk_swkey,app_swkey))
#removeallthenon-defaultchannels
foriinrange(3,16):
lora.remove_channel(i)
#setthe3defaultchannelstothesamefrequency
lora.add_channel(0,frequency=868100000,dr_min=0,dr_max=5)
lora.add_channel(1,frequency=868100000,dr_min=0,dr_max=5)
lora.add_channel(2,frequency=868100000,dr_min=0,dr_max=5)
#createaLoRasocket
s=socket.socket(socket.AF_LORA,socket.SOCK_RAW)
#settheLoRaWANdatarate
s.setsockopt(socket.SOL_LORA,socket.SO_DR,5)
#makethesocketnon-blocking
s.setblocking(False)
"""Yourowncodecanbewrittenbelow!"""
foriinrange(200):
s.send(b'PKT#'+bytes([i]))
time.sleep(4)
rx=s.recv(256)
ifrx:
print(rx)
time.sleep(6)
TTNApplications
4.3.6LoRaWANNano-Gateway
225
Nowthatthegateway&nodeshavebeensetup,aTTNApplicationcanbebuilt;i.e.what
happenstotheLoRadataonceitisreceivedbyTTN.Thereareanumberofdifferent
setups/systemsthatcanbeused,howeverthefollowingexampledemonstratestheHTTP
requestintegration.
RegisteringanApplication
Selectingthe ApplicationstabatthetopoftheTTNconsole,willbringupascreenfor
registeringapplications.Clickregisterandanewpage,similartotheonebelow,willopen.
Enteraunique ApplicationIDaswellasaDescription&HandlerRegistration.
NowtheLoPynodesmustberegisteredtosenddatauptothenewApplication.
RegisteringDevices(LoPy)
Toconnectnodestothenano-gateway,devicesneedtobeaddedtotheapplication.Todo
this,navigatetothe Devicestabonthe Applicationhomepageandclickthe Register
Devicebutton.
Inthe RegisterDevicepanel,completetheformsforthe DeviceIDandthe DeviceEUI.
The DeviceIDisuserspecifiedandisuniquetothedeviceinthisapplication.The Device
EUIisalsouserspecifiedbutmustconsistofexactly8bytes,giveninhexadecimal.
4.3.6LoRaWANNano-Gateway
226
Oncethedevicehasbeenadded,changethe ActivationMethodbetween OTAAand ABP
dependingonuserpreference.ThisoptioncanbefoundundertheSettingstab.
AddingApplicationIntegrations
NowthatthedataisarrivingontheTTNBackend,TTNcanbemanagedastowheredata
shouldbedeliveredto.Todothis,usethe IntegrationstabwithinthenewApplication’s
settings.
Uponclicking addintegration,ascreenwith4differentoptionswillappear.Thesehave
variousfunctionalityandmoreinformationaboutthemcanbefoundontheTTN
website/documentation.
Forthisexample,usethe HTTPIntegrationtoforwardtheLoRaWANPacketstoaremote
server/address.
4.3.6LoRaWANNano-Gateway
227
Click HTTPIntegrationtoconnectupanendpointthatcanreceivethedata.
Fortesting,awebsitecalledRequestBinmaybeusedtoreceivethedatathatTTNforwards
(viaPOSTRequest).Tosetthisup,navigatetoRequestBinandclickthe Createa
RequestBin.
CopytheURLthatisgeneratedandpastthisintothe URLformunderthe Application
Settings.
4.3.6LoRaWANNano-Gateway
228
ThisistheaddressthatTTNwillforwarddataonto.AssoonasaLoPystartssending
messages,TTNwillforwardtheseonto RequestBinandtheywillappearattheunique
RequestBinURL.
4.3.6LoRaWANNano-Gateway
229
RN2483toLoPy
ThisexampleshowshowtosenddatabetweenaMicrochipRN2483andaLoPyviaraw
LoRa.
RN2483
macpause
radiosetfreq868000000
radiosetmodlora
radiosetbw250
radiosetsfsf7
radiosetcr4/5
radiosetbw125
radiosetsync12
radiosetprlen8
#Transmitviaradiotx:
radiotx48656c6C6F#(shouldsend‘Hello’)
LoPy
fromnetworkimportLoRa
importsocket
lora=LoRa(mode=LoRa.LORA,frequency=868000000,bandwidth=LoRa.BW_125KHZ,sf=7,prea
mble=8,
coding_rate=LoRa.CODING_4_5,power_mode=LoRa.ALWAYS_ON,
tx_iq=False,rx_iq=False,public=False)
s=socket.socket(socket.AF_LORA,socket.SOCK_RAW)
#Thiskeepslisteningfordata"forever".
while(True):
s.recv(64)
4.3.7RN2483toLoPy
230
SiPyTutorials
ToensureyourdevicehasbeenprovisionedwithDeviceIDandPACnumber,please
updatetothelatestfirmware.
ThefollowingtutorialsdemonstratehowtoregisterandgetstartedwiththeSiPy.TheSiPy
canbeconfiguredforoperationinvariouscountriesbaseduponspecifiedRCZzones(see
the Sigfoxclassformoreinfo).TheSiPysupportsbothuplinkanddownlink Sigfox
messagesaswellasdevicetodevicecommunicationviaitsFSKMode Sigfox.
4.4SigfoxExamples
231
RegisteringwithSigfox
ToensurethedevicehasbeenprovisionedwithDeviceIDandPACnumber,pleaseupdate
tothelatestfirmware.
InordertosendaSigfoxmessage,thedeviceneedtoregisterwiththeSigfoxBackend.
Navigatetohttps://backend.sigfox.com/activatetofindthelistofSigfoxenabled
developmentkits.
Select Pycomtoproceed.
NextchooseaSigfoxOperatorforthecountrywherethedevicewillbeactivated.Findthe
specificcountryandselecttheoperatortocontinue.
4.4.1RegisterDevice
232
Nowneedtoenterthedevice'sDeviceIDandPACnumber.
TheDeviceIDandPACnumberareretrievablethroughacoupleofcommandsviathe
REPL.
fromnetworkimportSigfox
importubinascii
#initaliseSigfoxforRCZ1(YoumayneedadifferentRCZRegion)
sigfox=Sigfox(mode=Sigfox.SIGFOX,rcz=Sigfox.RCZ1)
#printSigfoxDeviceID
print(ubinascii.hexlify(sigfox.id()))
#printSigfoxPACnumber
print(ubinascii.hexlify(sigfox.pac()))
See SigfoxformoreinfoabouttheSigfoxClassandwhich RCZregiontouse.
4.4.1RegisterDevice
233
Oncethedevice'sDeviceIDandPACnumberhavebeenentered,createanaccount.
Providetherequiredinformationincludingemailaddressandclicktocontinue.
AnemailconfirmingthecreationofaSigfoxBackendaccountandthesuccessful
registrationofthedeviceshouldarriveattheusersinbox.
4.4.1RegisterDevice
234
HowToDisengageSequenceNumber
IfyourareexperiencingissueswithSigfoxconnectivity,thiscouldbeduetothesequence
numberbeingoutofsync.Topreventreplayonthenetwork,theSigfoxprotocoluses
sequencenumbers.Ifthereisalargedifferencebetweenthesequencenumbersentbythe
deviceandtheoneexpectedbythebackend,yourmessageisdroppedbythenetwork.
Youcanusethe Disengagesequencenumberbuttononthedeviceinformationoronthe
devicetypeinformationpageoftheSigfoxbackendtoresetthenumberexpectedbythe
backend.Ifthesequencenumberofyournextmessageisdifferentfromthelasttrashed
sequencenumber,themessagewillbeaccepted.
Issueswiththesequencenumbercanoccurwhenalotofmessagesaresentwhenoutside
ofSigfoxcoverageforinstance.
FirstlyyouwillneedtologintotheSigfoxBackend,navigatetodevice,andclickonthe
SigfoxIDoftheaffectedSiPy.
YoushouldnowseetheInformationpagewithanentry DeviceType:followedbyalink.
Pleasefollowthelink
4.4.2DisengageSequenceNumber
235
Finally,onthispageclickon Disengagesequencenumberbuttonintheupperrightcorner.
4.4.2DisengageSequenceNumber
236
LTETutorials
ThefollowingtutorialsdemonstratetheuseoftheLTECAT-M1andNB-IoTfunctionalityon
cellularenabledPycommodules.
OurcellularmodulessupportbothLTECAT-M1andNB-IoT,thesearenewlowerpower,
longrange,cellularprotocols.Thesearenotthesameasthefullversionof2G/3G/LTE
supportedbycellphones,andrequireyourlocalcarrierstosupportthem.Atthetimeof
writing,CAT-M1andNB-IoTconnectivityisnotwidelyavailablesobesuretocheckwith
localcarriersifsupportisavailablewhereyouare.
4.5LTEExamples
237
LTEclassforCatM1
PleaseensureyouhavethelatestSequansmodemfirmwareforthebestnetwork
compatibility.Instructionsforthiscanbefoundhere.
TheLTECatM1servicegivesfullIPaccessthroughthecellularmodem.
Oncethe lte.connect()functionhascompletedalltheIPsocketfunctions-includingSSL-
willberoutedthroughthisconnection.ThismeananycodeusingWLANcanbeadaptedto
CatM1bysimplyaddingtheconnectionsetupstepfirstanddisconnectafter.
ForexampletoconnectoverLTECatM1toGoogle'swebserveroversecureSSL:
importsocket
importssl
importtime
fromnetworkimportLTE
lte=LTE()#instantiatetheLTEobject
lte.attach()#attachthecellularmodemtoabasestation
whilenotlte.isattached():
time.sleep(0.25)
lte.connect()#startadatasessionandobtainanIPaddress
whilenotlte.isconnected():
time.sleep(0.25)
s=socket.socket()
s=ssl.wrap_socket(s)
s.connect(socket.getaddrinfo('www.google.com',443)[0][-1])
s.send(b"GET/HTTP/1.0\r\n\r\n")
print(s.recv(4096))
s.close()
lte.disconnect()
lte.dettach()
ThisalsoappliestoourMQTTandAWSexamples.
IMPORTANT:OncetheLTEradioisinitialised,itmustbede-initialisedbeforegoingto
deepsleepinordertoensureminimumpowerconsumption.ThisisrequiredduetotheLTE
radiobeingpoweredindependentlyandallowingusecaseswhichrequirethesystemtobe
takenoutfromdeepsleepbyaneventfromtheLTEnetwork(dataorSMSreceivedfor
instance).
4.5.1CAT-M1
238
WhenusingtheexpansionboardandtheFiPytogether,theRTS/CTSjumpersMUSTbe
removedasthosepinsarebeingusedbytheLTEradio.Keepingthosejumpersinplacewill
leadtoerraticoperationandhighercurrentconsumptionspeciallywhileindeepsleep.
4.5.1CAT-M1
239
LTEclassforNarrowBandIoT
Asshipped,PycommodulesonlysupportCAT-M1,inordertouseNB-IoTyouneedto
flashadifferentfirmwaretotheSequansmodem.Instructionsforthiscanbefound
here.
CurrentNB-IoTlimitations
AtthemomenttheNB-IoTfirmwaresuppliedbySequansonlysupportEricssonbase
stationsconfiguredforIn-Bandmode.Standaloneandguard-bandmodeswillbesupported
inalaterrelease.SupportforHuaweibasestationsisalsolimitedandonlylabtestingwith
HuaweieNodeBisrecommendedatthemoment.FullsupportforHuaweiisplannedfor
earlyQ22018.
NB-IoTusage:
ExamplewithVodafone:
fromnetworkimportLTE
lte=LTE()
lte.send_at_cmd('AT+CFUN=0')
lte.send_at_cmd('AT!="clearscanconfig"')
lte.send_at_cmd('AT!="addscanfreqband=20dl-earfcn=6300"')
lte.send_at_cmd('AT!="zsp0:npc1"')
lte.send_at_cmd('AT+CGDCONT=1,"IP","nb.inetd.gdsp"')
lte.send_at_cmd('AT+CFUN=1')
whilenotlte.isattached():
pass
lte.connect()
whilenotlte.isconnected():
pass
#nowusesocketasusual...
4.5.2NB-IoT
240
IMPORTANT:OncetheLTEradioisinitialised,itmustbede-initialisedbeforegoingto
deepsleepinordertoensureminimumpowerconsumption.ThisisrequiredduetotheLTE
radiobeingpoweredindependentlyandallowingusecaseswhichrequirethesystemtobe
takenoutfromdeepsleepbyaneventfromtheLTEnetwork(dataorSMSreceivedfor
instance).
WhenusingtheexpansionboardandtheFiPytogether,theRTS/CTSjumpersMUSTbe
removedasthosepinsarebeingusedbytheLTEradio.Keepingthosejumpersinplacewill
leadtoerraticoperationandhighercurrentconsumptionspeciallywhileindeepsleep.
4.5.2NB-IoT
241
HowtogettheIMEIofyourmodule
InordertoretrievetheIMEIofyourcellularenabledPycommoduleyouwillfirstlyneedto
makesureyouareonfirmwareversion 1.17.0.b1orhigher.Youcancheckyourfirmware
versionbyrunningthefollowingcodeonyoudeviceviatheinteractiveREPL.
>>>importos
>>>os.uname()
(sysname='GPy',nodename='GPy',release='1.17.0.b1',version='v1.8.6-849-d0dc708on20
18-02-27',machine='GPywithESP32')
Onceyouhaveacompatiblefirmware,youcanrunthefollowingcodetogetyourmodules
IMEInumber:
fromnetworkimportLTE
lte=LTE()
lte.send_at_cmd('AT+CGSN=1')
You’llgetareturnstringlikethis \r\n+CGSN:"354347xxxxxxxxx"\r\n\r\nOK.Thevalue
betweenthedoublequotesisyourIMEI.
4.5.3ModuleIMEI
242
FirmwareupgradetoolfortheSequans
MonarchSQN3330
Description
TheSequansMonarchSQN3330cellularradiofoundonthePycomFiPy,GPyandGO1
modulesrequiresadifferentfirmwaretooperateinCAT-M1orNB-IoTmode.
ThispagewillexplaintheprocesstoupgradethefirmwareofthecellularradioTheprocess
involvesstreamingthefirmwarefilefromtheESP32totheSQN3330.Currently,thefilehas
tobestoredinamicroSDcardfirstsothattheESP32canaccessiteasily.Wearecurrent
workingtoaddsupportforstreamingthefileviatheupdatertoolaswell.
Requirements
Beforeproceedingyouwillneed:
Pycomcellularenabledmodule(GPy,FiPy,G01)
FAT32formattedmicroSDcard(withatleast6MBoffreespace)
APycomExpansionBoardorshield(oramicroSDcardsocketbreakoutboard)
Usage
IfyourmoduleisrunningthefactoryLTEchipfirmware,youMUSTfirstperforman
updatetothelatestCAT-M1firmwarebeforetryingtoupgradetotheNB-IoTfirmware.
Skippingthisstepwillcauseyourradiotobecomeunresponsiveanditwillrequire
accesstothetestpointsinordertore-flashthefirmware.
Firstly,youwillneedtodownloadtherequiredlibraryfilesfromhere.Youwillneedtoplace
theseinadirectorycalled"lib"justlikeanyotherlibraries.Thiscanbedoneusingeither
FTPorPymakr
Nextyouneedtodownloadthefirmwarefilefromhere.Youwillneedtoplacethefirmware
onaFAT32formattedmicroSDcard,theninserttheSDcardintoaExpansionBoard,
Pytrack,PysenseorPyscan.Power-upthesystemandconnecttotheinteractiveREPLand
4.5.3ModemFirmwareUpdate
243
runthefollowingcode:
importsqnsupgrade
sqnsupgrade.run(path_to_firmware,921600)#path_to_firmwareexample:'/sd/FIPY_NB1_
35351.dup'
Thewholeprocesscantakebetween2and3minutesandatsomepointsitwillseemto
stall,thisisnormal,justbepatience.Youshouldseeanoutputlikethis:
<<<WelcometotheSQN3330firmwareupdater>>>
Enteringrecoverymode
Resetting.
StartingSTP(DONOTDISCONNECTPOWER!!!)
STPstarted
Sessionopened:version1,maxtransfer8192bytes
Sending4560505bytes:[########################################]100%
Codedownloaddone,returningtousermode
Resetting(DONOTDISCONNECTPOWER!!!).
.........
Deployingtheupgrade(DONOTDISCONNECTPOWER!!!)...
Resetting(DONOTDISCONNECTPOWER!!!)..
...
Upgradecompleted!
Hereisthecurrentfirmwareversion:
UE6.0.0.0-ER7
LR6.0.0.0-35351
OK
DONOTdisconnectpowerwhiletheupgradeprocessistakingplace,waitforittofinish!
Ifthemoduleget'sstuckinhereformorethan1minutewhileupgradingtotheNB-IoT
firmware,youcancyclepowerandretry.Inthiscaseitissafe.
Sending4560505bytes:[##]6%
4.5.3ModemFirmwareUpdate
244
SensorDemos
Accelerometer
Thisbasicexampleshowshowtoreadpitchandrollfromtheon-boardaccelerometerand
outputitincommaseparatedvalue(CSV)formatoverserial.
fromLIS2HH12importLIS2HH12
frompytrackimportPytrack
py=Pytrack()
acc=LIS2HH12()
whileTrue:
pitch=acc.pitch()
roll=acc.roll()
print('{},{}'.format(pitch,roll))
time.sleep_ms(100)
IfyouwanttovisualisethedataoutputbythisscriptaProcessingsketchisavailablehere
thatwillshowtheboardorientationin3D.
4.7PysenseExamples
246
4.7PysenseExamples
247
Introduction
Thischapterdescribesmodules(functionandclasslibraries)thatarebuiltintoMicroPython.
Thereareanumberofcategoriesfortheavailablemodules:
ModuleswhichimplementasubsetofstandardPythonfunctionalityandarenot
intendedtobeextendedbytheuser.
ModuleswhichimplementasubsetofPythonfunctionality,withaprovisionfor
extensionbytheuser(viaPythoncode).
ModuleswhichimplementMicroPythonextensionstothePythonstandardlibraries.
Modulesspecifictoaparticularportandthusnotportable.
Noteabouttheavailabilityofmodulesandtheircontents
Thisdocumentationingeneralaspirestodescribeallmodulesandfunctions/classeswhich
areimplementedinMicroPython.However,MicroPythonishighlyconfigurable,andeach
porttoaparticularboard/embeddedsystemmakesavailableonlyasubsetofMicroPython
libraries.Forofficiallysupportedports,thereisanefforttoeitherfilteroutnon-applicable
items,ormarkindividualdescriptionswith“Availability:”clausesdescribingwhichports
provideagivenfeature.Withthatinmind,pleasestillbewarnedthatsomefunctions/classes
inamodule(oreventheentiremodule)describedinthisdocumentationmaybeunavailable
inaparticularbuildofMicroPythononaparticularboard.Thebestplacetofindgeneral
informationoftheavailability/non-availabilityofaparticularfeatureisthe“General
Information”sectionwhichcontainsinformationpertainingtoaspecificport.
Beyondthebuilt-inlibrariesdescribedinthisdocumentation,manymoremodulesfromthe
Pythonstandardlibrary,aswellasfurtherMicroPythonextensionstoit,canbefoundinthe
micropython-librepository.
5.1Introduction
248
modulemachine
The machinemodulecontainsspecificfunctionsrelatedtotheboard.
QuickUsageExample
importmachine
help(machine)#displayallmembersfromthemachinemodule
machine.freq()#gettheCPUfrequency
machine.unique_id()#returnthe6-byteuniqueidoftheboard(theLoPy'sWiFiMACad
dress)
ResetFunctions
machine.reset()
ResetsthedeviceinamannersimilartopushingtheexternalRESETbutton.
machine.reset_cause()
Gettheresetcause.Seeconstantsforthepossiblereturnvalues.
InterruptFunctions
machine.disable_irq()
Disableinterruptrequests.ReturnsandintegerrepresentingthepreviousIRQstate.This
returnvaluecanbepassedto enable_irqtorestoretheIRQtoitsoriginalstate.
machine.enable_irq([state])
Enableinterruptrequests.Themostcommonuseofthisfunctionistopassthevalue
returnedby disable_irqtoexitacriticalsection.Anotheroptionsistoenableallinterrupts
whichcanbeachievedbycallingthefunctionwithnoparameters.
PowerFunctions
machine.freq()
ReturnsCPUfrequencyinhertz.
5.2.1machine
250
machine.idle()
GatestheclocktotheCPU,usefultoreducepowerconsumptionatanytimeduringshortor
longperiods.Peripheralscontinueworkingandexecutionresumesassoonasanyinterrupt
istriggered(onmanyportsthisincludessystemtimerinterruptoccurringatregularintervals
ontheorderofmillisecond).
machine.deepsleep([time_ms])
StopstheCPUandallperipherals,includingthenetworkinginterfaces(exceptforLTE).
Executionisresumedfromthemainscript,justaswithareset.Ifavalueinmillisecondsis
giventhenthedevicewillwakeupafterthatperiodoftime,otherwiseitwillremainindeep
sleepuntiltheresetbuttonispressed.
TheproductswithLTEconnectivity(FiPy,GPy,G01),requiretheLTEradiotobedisabled
separatelyviatheLTEclassbeforeenteringdeepsleep.ThisisrequiredduetotheLTE
radiobeingpoweredindependentlyandallowingusecaseswhichrequirethesystemtobe
takenoutfromdeepsleepbyaneventfromtheLTEnetwork(dataorSMSreceivedfor
instance).
machine.pin_deepsleep_wakeup(pins,mode,enable_pull)
Configurepinstowakeupfromdeepsleepmode.Thepinswhichhavethiscapabilityare:
P2,P3,P4,P6,P8toP10andP13toP23.
Theargumentsare:
pinsalistortuplecontainingthe GPIOtosetupfordeepsleepwakeup.
modeselectsthewaytheconfigure GPIOscanwakeupthemodule.Thepossible
valuesare: machine.WAKEUP_ALL_LOWand machine.WAKEUP_ANY_HIGH.
enable_pullifsetto Truekeepsthepulluporpulldownresistorsenabledduring
deepsleep.Ifthisvariableissetto True,then ULPorcapacitivetouchwakeupcannot
beusedincombinationwith GPIOwakeup.
machine.wake_reason()
Getthewakereason.Seeconstantsforthepossiblereturnvalues.Returnsatupleofthe
form: (wake_reason,gpio_list).WhenthewakeupreasoniseitherGPIOortouchpad,
thenthesecondelementofthetupleisalistwithGPIOsthatgeneratedthewakeup.
machine.remaining_sleep_time()
Returnstheremainingtimerduration(inmilliseconds)iftheESP32iswokenupfromdeep
sleepbysomethingotherthanthetimer.Forexample,ifyousetthetimerfor30seconds
(30000ms)anditwakesupafter10secondsthenthisfunctionwillreturn 20000.
5.2.1machine
251
MiscellaneousFunctions
machine.main(filename)
Setthe filenameofthemainscripttorunafter boot.pyisfinished.Ifthisfunctionisnot
calledthenthedefaultfile main.pywillbeexecuted.
Itonlymakessensetocallthisfunctionfromwithin boot.py.
machine.rng()
Returna24-bitsoftwaregeneratedrandomnumber.
machine.unique_id()
Returnsabytestringwithauniqueidentifierofaboard/SoC.Itwillvaryfromaboard/SoC
instancetoanother,ifunderlyinghardwareallows.Lengthvariesbyhardware(souse
substringofafullvalueifyouexpectashortID).InsomeMicroPythonports,IDcorresponds
tothenetworkMACaddress.
Use ubinascii.hexlify()toconvertthebytestringtohexadecimalformforeaseof
manipulationanduseelsewhere.
machine.info()
Returnsthehighwatermarkofthestackassociatedwithvarioussystemtasks,inwords(1
word=4bytesontheESP32).Ifthevalueiszerothenthetaskhaslikelyoverflowedits
stack.Ifthevalueisclosetozerothenthetaskhascomeclosetooverflowingitsstack.
Constants
ResetCauses
machine.PWRON_RESETmachine.HARD_RESETmachine.WDT_RESET
machine.DEEPSLEEP_RESETmachine.SOFT_RESETmachine.BROWN_OUT_RESET
WakeReasons
machine.PWRON_WAKEmachine.PIN_WAKEmachine.RTC_WAKEmachine.ULP_WAKE
PinWakeupModes
5.2.1machine
252
machine.WAKEUP_ALL_LOWmachine.WAKEUP_ANY_HIGH
5.2.1machine
253
classADC–AnalogtoDigitalConversion
QuickUsageExample
importmachine
adc=machine.ADC()#createanADCobject
apin=adc.channel(pin='P16')#createananalogpinonP16
val=apin()#readananalogvalue
Constructors
classmachine.ADC(id=0)
CreateanADCobject;associateachannelwithapin.Formoreinfocheckthehardware
section.
Methods
adc.init(*,bits=12)
EnabletheADCblock.Thismethodisautomaticallycalledonobjectcreation.
Bitscantakevaluesbetween9and12andselectsthenumberofbitsofresolutionof
theADCblock.
adc.deinit()
DisabletheADCblock.
adc.channel(*,pin,attn=ADC.ATTN_0DB)
Createananalogpin.
pinisakeyword-onlystringargument.Validpinsare P13to P20.
attnistheattenuationlevel.Thesupportedvaluesare:ADC.ATTN_0DB
ADC.ATTN_2_5DBADC.ATTN_6DBADC.ATTN_11DB
ReturnsaninstanceofADCChannel.Example:
#enableanADCchannelonP16
apin=adc.channel(pin='P16')
5.2.1.1ADC
254
adc.vref(vref)
Ifcalledwithoutanyarguments,thisfunctionreturnsthecurrentcalibratedvoltage(in
millivolts)ofthe 1.1vreference.Otherwiseitwillupdatethecalibratedvalue(inmillivolts)
oftheinternal 1.1vreference.
adc.vref_to_pin(pin)
Connectstheinternal 1.1vtoexternal GPIO.Itcanonlybeconnectedto P22, P21or
P6.Itisrecommendedtoonlyuse P6ontheWiPy,onothermodulesthispinis
connectedtotheradio.
Constants
ADC.ATTN_0DBADC.ATTN_2_5DBADC.ATTN_6DBADC.ATTN_11DB
ADCchannelattenuationvalues
classADCChannel
Readanalogvaluesfrominternal/externalsources.ADCchannelscanbeconnectedto
internalpointsofthe MCUorto GPIOpins.ADCchannelsarecreatedusingthe
ADC.channelmethod.
Methods
adcchannel()
Fastmethodtoreadthechannelvalue.
adcchannel.value()
Readthechannelvalue.
adcchannel.init()
(Re)initandenabletheADCchannel.Thismethodisautomaticallycalledonobjectcreation.
adcchannel.deinit()
DisabletheADCchannel.
adcchannel.voltage()
Readsthechannelsvalueandconvertsitintoavoltage(inmillivolts)
5.2.1.1ADC
255
adcchannel.value_to_voltage(value)
Convertstheprovidedvalueintoavoltage(inmillivolts)inthesamewayvoltagedoes.
ADCpininputrangeis 0-1.1V.Thismaximumvaluecanbeincreasedupto 3.3V
usingthehighestattenuationof 11dB.Donotexceedthemaximumof3.3V,toavoid
damagingthedevice.
5.2.1.1ADC
256
classDAC–DigitaltoAnalogConversion
TheDACisusedtooutputanalogvalues(aspecificvoltage)onpin P22orpin P21.The
voltagewillbebetween 0and 3.3V.
QuickUsageExample
importmachine
dac=machine.DAC('P22')#createaDACobject
dac.write(0.5)#setoutputto50%
dac_tone=machine.DAC('P21')#createaDACobject
dac_tone.tone(1000,0)#settoneoutputto1kHz
Constructors
classclassmachine.DAC(pin)
CreateaDACobject,thatwillletyouassociateachannelwitha pin. pincanbeastring
argument.
Methods
dac.init()
EnabletheDACblock.Thismethodisautomaticallycalledonobjectcreation.
dac.deinit()
DisabletheDACblock.
dac.write(value)
SettheDClevelforaDACpin. valueisafloatargument,withvaluesbetween0and1.
dac.tone(frequency,amplitude)
Setsuptonesignaltothespecified frequencyat amplitudescale. frequencycanbefrom
125Hzto 20kHzinstepsof 122Hz. amplitudeisanintegerspecifyingthetoneamplitude
towritetheDACpin.Amplitudevaluerepresents:
5.2.1.2DAC
257
0is0dBV(~3Vppat600Ohmload)
1is-6dBV(~1.5Vpp), 2is-12dBV(~0.8Vpp)
3is-18dBV(~0.4Vpp).ThegeneratedsignalisasinewavewithanDCoffsetof
VDD/2.
5.2.1.2DAC
258
classI2C–Two-WireSerialProtocol
I2Cisatwo-wireprotocolforcommunicatingbetweendevices.Atthephysicallevelit
consistsof2wires:SCLandSDA,theclockanddatalinesrespectively.
I2Cobjectsarecreatedattachedtoaspecificbus.Theycanbeinitialisedwhencreated,or
initialisedlateron.
ExampleusingdefaultPins
frommachineimportI2C
i2c=I2C(0)#createonbus0
i2c=I2C(0,I2C.MASTER)#createandinitasamaster
i2c=I2C(0,pins=('P10','P11'))#createandusenon-defaultPINassignments(P10
=SDA,P11=SCL)
i2c.init(I2C.MASTER,baudrate=20000)#initasamaster
i2c.deinit()#turnofftheperipheral
Exampleusingnon-defaultPins
frommachineimportI2C
i2c=I2C(0,pins=('P10','P11'))#createandusenon-defaultPINassignments(P10
=SDA,P11=SCL)
i2c.init(I2C.MASTER,baudrate=20000)#initasamaster
i2c.deinit()#turnofftheperipheral
Printingthe i2cobjectgivesyouinformationaboutitsconfiguration.
Amastermustspecifytherecipient’saddress:
i2c.init(I2C.MASTER)
i2c.writeto(0x42,'123')#send3bytestoslavewithaddress0x42
i2c.writeto(addr=0x42,b'456')#keywordforaddress
Masteralsohasothermethods:
5.2.1.3I2C
259
i2c.scan()#scanforslavesonthebus,returning
#alistofvalidaddresses
i2c.readfrom_mem(0x42,2,3)#read3bytesfrommemoryofslave0x42,
#startingataddress2intheslave
i2c.writeto_mem(0x42,2,'abc')#write'abc'(3bytes)tomemoryofslave0x42
#startingataddress2intheslave,timeoutafte
r1second
QuickUsageExample
frommachineimportI2C
#configuretheI2Cbus
i2c=I2C(0,I2C.MASTER,baudrate=100000)
i2c.scan()#returnslistofslaveaddresses
i2c.writeto(0x42,'hello')#send5bytestoslavewithaddress0x42
i2c.readfrom(0x42,5)#receive5bytesfromslave
i2c.readfrom_mem(0x42,0x10,2)#read2bytesfromslave0x42,slavememory0x10
i2c.writeto_mem(0x42,0x10,'xy')#write2bytestoslave0x42,slavememory0x10
Constructors
classmachine.I2C(bus,...)
ConstructanI2Cobjectonthegiven bus. buscanonlybe 0,1,2.Ifthe busisnot
given,thedefaultonewillbeselected( 0).Buses 0and 1usetheESP32I2Chardware
peripheralwhilebus 2isimplementedwithabit-bangedsoftwaredriver.
GeneralMethods
i2c.init(mode,*,baudrate=100000,pins=(SDA,SCL))
InitialisetheI2Cbuswiththegivenparameters:
modemustbeI2C.MASTER
baudrateistheSCLclockrate
pinsisanoptionaltuplewiththepinstoassigntotheI2Cbus.ThedefaultI2Cpinsare
P9(SDA)and P10(SCL)
i2c.scan()
ScanallI2Caddressesbetween 0x08and 0x77inclusiveandreturnalistofthosethat
respond.AdevicerespondsifitpullstheSDAlinelowafteritsaddress(includingareadbit)
issentonthebus.
5.2.1.3I2C
260
StandardBusOperations
ThefollowingmethodsimplementthestandardI2Cmasterreadandwriteoperationsthat
targetagivenslavedevice.
i2c.readfrom(addr,nbytes)
Read nbytesfromtheslavespecifiedby addr.Returnsabytesobjectwiththedataread.
i2c.readfrom_into(addr,buf)
Readinto buffromtheslavespecifiedby addr.Thenumberofbytesreadwillbethe
lengthof buf.
Returnvalueisthenumberofbytesread.
i2c.writeto(addr,buf,*,stop=True)
Writethebytesfrom buftotheslavespecifiedby addr.Theargument bufcanalsobe
anintegerwhichwillbetreatedasasinglebyte.If stopissetto Falsethenthestop
conditionwon’tbesentandtheI2Coperationmaybecontinued(typicallywitharead
transaction).
Returnvalueisthenumberofbyteswritten.
MemoryOperations
SomeI2Cdevicesactasamemorydevice(orsetofregisters)thatcanbereadfromand
writtento.InthiscasetherearetwoaddressesassociatedwithanI2Ctransaction:theslave
addressandthememoryaddress.Thefollowingmethodsareconveniencefunctionsto
communicatewithsuchdevices.
i2c.readfrom_mem(addr,memaddr,nbytes,*,addrsize=8)
Read nbytesfromtheslavespecifiedby addrstartingfromthememoryaddressspecified
by memaddr.The addrsizeargumentisspecifiedinbitsanditcanonlytake8or16.
i2c.readfrom_mem_into(addr,memaddr,buf,*,addrsize=8)
Readinto buffromtheslavespecifiedby addrstartingfromthememoryaddress
specifiedby memaddr.Thenumberofbytesreadisthelengthof buf.The addrsize
argumentisspecifiedinbitsanditcanonlytake8or16.
Thereturnvalueisthenumberofbytesread.
i2c.writeto_mem(addr,memaddr,buf*,addrsize=8)
5.2.1.3I2C
261
Write buftotheslavespecifiedby addrstartingfromthememoryaddressspecifiedby
memaddr.Theargument bufcanalsobeanintegerwhichwillbetreatedasasinglebyte.
The addrsizeargumentisspecifiedinbitsanditcanonlytake8or16.
Thereturnvalueisthenumberofbyteswritten.
Constants
I2C.MASTER
Usedtoinitialisethebustomastermode.
5.2.1.3I2C
262
classPin–ControlI/OPins
ApinisthebasicobjecttocontrolI/Opins(alsoknownasGPIO-general-purpose
input/output).Ithasmethodstosetthemodeofthepin(input,output,etc)andmethodsto
getandsetthedigitallogiclevel.Foranalogcontrolofapin,seetheADCclass.
QuickUsageExample
frommachineimportPin
#initialize`P9`ingpiomodeandmakeitanoutput
p_out=Pin('P9',mode=Pin.OUT)
p_out.value(1)
p_out.value(0)
p_out.toggle()
p_out(True)
#make`P10`aninputwiththepull-upenabled
p_in=Pin('P10',mode=Pin.IN,pull=Pin.PULL_UP)
p_in()#getvalue,0or1
Constructors
classmachine.Pin(id,...)
CreateanewPinobjectassociatedwiththestring id.Ifadditionalargumentsaregiven,
theyareusedtoinitialisethepin.Seepin.init().
frommachineimportPin
p=Pin('P10',mode=Pin.OUT,pull=None,alt=-1)
Methods
pin.init(mode,pull,*,alt)
Initialisethepin:
modecanbeoneof:
Pin.IN-inputpin.
Pin.OUT-outputpininpush-pullmode.
Pin.OPEN_DRAIN-inputoroutputpininopen-drainmode.
5.2.1.4Pin
263
pullcanbeoneof:
None-nopullupordownresistor.
Pin.PULL_UP-pullupresistorenabled.
Pin.PULL_DOWN-pulldownresistorenabled.
altistheidofthealternatefunction.
Returns: None.
pin.id()
Getthepinid.
pin.value([value])
Getorsetthedigitallogiclevelofthepin:
Withnoargument,return0or1dependingonthelogiclevelofthepin.
Withvaluegiven,setthelogiclevelofthepin.valuecanbeanythingthatconvertstoa
boolean.IfitconvertstoTrue,thepinissethigh,otherwiseitissetlow.
pin([value])
Pinobjectsarecallable.Thecallmethodprovidesa(fast)shortcuttosetandgetthevalue
ofthepin.
Example:
frommachineimportPin
pin=Pin('P12',mode=Pin.IN,pull=Pin.PULL_UP)
pin()#fastmethodtogetthevalue
Seepin.value()formoredetails.
pin.toggle()
Togglethevalueofthepin.
pin.mode([mode])
Getorsetthepinmode.
pin.pull([pull])
Getorsetthepinpull.
pin.hold([hold])
5.2.1.4Pin
264
Getorsetthepinhold.Youcanapplyaholdtoapinbypassing True(orclearitby
passing False).Whenapinisheld,itsvaluecannotbechangedbyusing Pin.value()or
Pin.toggle()untiltheholdisreleased.ThisCanbeusedtoretainthepinstatethrougha
coreresetandsystemresettriggeredbywatchdogtime-outorDeep-sleepevents.Onlypins
intheRTCpowerdomaincanretaintheirvaluethroughdeepsleeporreset.Theseare: P2,
P3,P4,P6,P8,P9,P10,P13,P14,P15,P16,P17,P18,P19,P20,P21,P22,P23.
pin.callback(trigger,handler=None,arg=None)
Setacallbacktobetriggeredwhentheinputlevelatthepinchanges.
triggeristhetypeofeventthattriggersthecallback.Possiblevaluesare:
Pin.IRQ_FALLINGinterruptonfallingedge.
Pin.IRQ_RISINGinterruptonrisingedge.
Pin.IRQ_LOW_LEVELinterruptonlowlevel.
Pin.IRQ_HIGH_LEVELinterruptonhighlevel.
ThevaluescanbeOR-edtogether,forinstance trigger=Pin.IRQ_FALLING|Pin.IRQ_RISING
handleristhefunctiontobecalledwhentheeventhappens.Thisfunctionwillreceive
oneargument.Set handlerto Nonetodisableit.
argisanoptionalargumenttopasstothecallback.Ifleftemptyorsetto None,the
functionwillreceivethePinobjectthattriggeredit.
Example:
frommachineimportPin
defpin_handler(arg):
print("gotaninterruptinpin%s"%(arg.id()))
p_in=Pin('P10',mode=Pin.IN,pull=Pin.PULL_UP)
p_in.callback(Pin.IRQ_FALLING|Pin.IRQ_RISING,pin_handler)
FormoreinformationonhowPycom’sproductshandleinterrupts,seehere.
Attributes
classpin.exp_board
ContainsallPinobjectssupportedbytheexpansionboard.Examples:
5.2.1.4Pin
265
Pin.exp_board.G16
led=Pin(Pin.exp_board.G16,mode=Pin.OUT)
Pin.exp_board.G16.id()
classpin.module
Containsall Pinobjectssupportedbythemodule.Examples:
Pin.module.P9
led=Pin(Pin.module.P9,mode=Pin.OUT)
Pin.module.P9.id()
Constants
Thefollowingconstantsareusedtoconfigurethepinobjects.Notethatnotallconstantsare
availableonallports.
Pin.INPin.OUTPin.OPEN_DRAIN
Selectsthepinmode.
Pin.PULL_UPPin.PULL_DOWN
Enablesthepulluporpulldownresistor.
5.2.1.4Pin
266
classPWM–PulseWidthModulation
QuickUsageExample
frommachineimportPWM
pwm=PWM(0,frequency=5000)#usePWMtimer0,withafrequencyof5KHz
#createpwmchannelonpinP12withadutycycleof50%
pwm_c=pwm.channel(0,pin='P12',duty_cycle=0.5)
pwm_c.duty_cycle(0.3)#changethedutycycleto30%
Constructors
classmachine.PWM(timer,frequency)
CreateaPWMobject.Thissetsupthe timertooscillateatthespecified frequency.
timerisanintegerfrom0to3. frequencyisanintegerfrom1Hzto78KHz(thisvalues
canchangeinfutureupgrades).
Methods
pwm.channel(id,pin*,duty_cycle=0.5)
ConnectaPWMchanneltoapin,settingtheinitialdutycycle. idisanintegerfrom0to7.
pinisastringargument. duty_cycleisakeyword-onlyfloatargument,withvalues
between0and1.Returnsaninstanceof PWMChannel.
classPWMChannel—PWMchannel
Methods
pwmchannel.duty_cycle(value)
SetthedutycycleforaPWMchannel. valueisafloatargument,withvaluesbetween0
and1.
5.2.1.5PWM
267
classRTC–RealTimeClock
TheRTCisusedtokeeptrackofthedateandtime.
QuickUsageExample
frommachineimportRTC
rtc=RTC()
rtc.init((2014,5,1,4,13,0,0,0))
print(rtc.now())
Constructors
classmachine.RTC(id=0,...)
CreateanRTCobject.Seeinitforparametersofinitialisation.
#idoftheRTCmaybesetifmultipleareconnected.Defaultstoid=0.
rtc=RTC(id=0)
Methods
rtc.init(datetime=None,source=RTC.INTERNAL_RC)
InitialisetheRTC.Theargumentsare:
datetimewhenpasseditsetsthecurrenttime.Itisatupleoftheform: (year,month,
day[,hour[,minute[,second[,microsecond[,tzinfo]]]]]).
sourceselectstheoscillatorthatdrivestheRTC.TheoptionsareRTC.INTERNAL_RC
andRTC.XTAL_32KHZ
Forexample:
#for2ndofFebruary2017at10:30am(TZ0)
rtc.init((2017,2,28,10,30,0,0,0))
tzinfoisignoredbythismethod.Use time.timezonetoachievesimilarresults.
5.2.1.6RTC
268
rtc.now()
Getgetthecurrent datetimetuple:
#returnsdatetimetuple
rtc.now()
rtc.ntp_sync(server,*,update_period=3600)
SetupautomaticfetchandupdatethetimeusingNTP(SNTP).
serveristheURLoftheNTPserver.Canbesetto Nonetodisabletheperiodic
updates.
update_periodisthenumberofsecondsbetweenupdates.Shortestperiodis15
seconds.
Canbeusedlike:
rtc.ntp_sync("pool.ntp.org")#thisisanexample.Youcanselectamorespecificserv
eraccordingtoyourgeographicallocation
rtc.synced()
Returns Trueifthelast ntp_synchasbeencompleted, Falseotherwise:
rtc.synced()
Constants
RTC.INTERNAL_RCRTC.XTAL_32KHZ
Clocksource
5.2.1.6RTC
269
classSPI–SerialPeripheralInterface
SPIisaserialprotocolthatisdrivenbyamaster.Atthephysicallevelthereare3lines:
SCK,MOSI,MISO.
SeeusagemodelofI2C;SPIisverysimilar.MaindifferenceisparameterstoinittheSPI
bus:
frommachineimportSPI
spi=SPI(0,mode=SPI.MASTER,baudrate=1000000,polarity=0,phase=0,firstbit=SPI.MSB)
Onlyrequiredparameterismode,mustbeSPI.MASTER.Polaritycanbe0or1,andisthe
leveltheidleclocklinesitsat.Phasecanbe0or1tosampledataonthefirstorsecond
clockedgerespectively.
QuickUsageExample
frommachineimportSPI
#configuretheSPImaster@2MHz
#thisusestheSPIdefaultpinsforCLK,MOSIandMISO(``P10``,``P11``and``P14``)
spi=SPI(0,mode=SPI.MASTER,baudrate=2000000,polarity=0,phase=0)
spi.write(bytes([0x01,0x02,0x03,0x04,0x05]))#send5bytesonthebus
spi.read(5)#receive5bytesonthebus
rbuf=bytearray(5)
spi.write_readinto(bytes([0x01,0x02,0x03,0x04,0x05]),rbuf)#sendareceive5byt
es
QuickUsageExampleusingnon-defaultpins
5.2.1.7SPI
270
frommachineimportSPI
#configuretheSPImaster@2MHz
#thisusestheSPInon-defaultpinsforCLK,MOSIandMISO(``P19``,``P20``and``P2
1``)
spi=SPI(0,mode=SPI.MASTER,baudrate=2000000,polarity=0,phase=0,pins=('P19','P20',
'P21'))
spi.write(bytes([0x01,0x02,0x03,0x04,0x05]))#send5bytesonthebus
spi.read(5)#receive5bytesonthebus
rbuf=bytearray(5)
spi.write_readinto(bytes([0x01,0x02,0x03,0x04,0x05]),rbuf)#sendareceive5byt
es
Constructors
classmachine.SPI(id,...)
ConstructanSPIobjectonthegivenbus. idcanbeonly0.Withnoadditionalparameters,
theSPIobjectiscreatedbutnotinitialised(ithasthesettingsfromthelastinitialisationofthe
bus,ifany).Ifextraargumentsaregiven,thebusisinitialised.Seeinitforparametersof
initialisation.
Methods
spi.init(mode,baudrate=1000000,*,polarity=0,phase=0,bits=8,firstbit=SPI.MSB,
pins=(CLK,MOSI,MISO))
InitialisetheSPIbuswiththegivenparameters:
modemustbeSPI.MASTER.
baudrateistheSCKclockrate.
polaritycanbe0or1,andistheleveltheidleclocklinesitsat.
phasecanbe0or1tosampledataonthefirstorsecondclockedgerespectively.
bitsisthewidthofeachtransfer,acceptedvaluesare8,16and32.
firstbitcanbeSPI.MSBorSPI.LSB.
pinsisanoptionaltuplewiththepinstoassigntotheSPIbus.Ifthepinsargumentis
notgiventhedefaultpinswillbeselected( P10asCLK, P11asMOSIand P14as
MISO).IfpinsispassedasNonethennopinassignmentwillbemade.
spi.deinit()
TurnofftheSPIbus.
spi.write(buf)
5.2.1.7SPI
271
Writethedatacontainedin buf.Returnsthenumberofbyteswritten.
spi.read(nbytes,*,write=0x00)
Readthe nbyteswhilewritingthedataspecifiedby write.Returnthenumberofbytes
read.
spi.readinto(buf,*,write=0x00)
Readintothebufferspecifiedby bufwhilewritingthedataspecifiedby write.Returnthe
numberofbytesread.
spi.write_readinto(write_buf,read_buf)
Writefrom write_bufandreadinto read_buf.Bothbuffersmusthavethesamelength.
Returnsthenumberofbyteswritten
Constants
SPI.MASTER
ForinitialisingtheSPIbustomaster
SPI.MSB
Setthefirstbittobethemostsignificantbit
SPI.LSB
Setthefirstbittobetheleastsignificantbit
5.2.1.7SPI
272
classUART–UniversalAsynchronous
Receiver/Transmitter
UARTimplementsthestandardUART/USARTduplexserialcommunicationsprotocol.Atthe
physicallevelitconsistsof2lines:RXDandTXD.Theunitofcommunicationisacharacter
(nottobeconfusedwithastringcharacter)whichcanbe5,6,7or8bitswide.
UARTobjectscanbecreatedandinitialisedusing:
frommachineimportUART
uart=UART(1,9600)#initwithgivenbaudrate
uart.init(9600,bits=8,parity=None,stop=1)#initwithgivenparameters
Bitscanbe 5,6,7,8.Paritycanbe None,UART.EVENorUART.ODD.Stopcanbe 1,
1.5or2.
AUARTobjectactslikeastreamobjectthereforereadingandwritingisdoneusingthe
standardstreammethods:
uart.read(10)#read10characters,returnsabytesobject
uart.readall()#readallavailablecharacters
uart.readline()#readaline
uart.readinto(buf)#readandstoreintothegivenbuffer
uart.write('abc')#writethe3characters
Tocheckifthereisanythingtoberead,use:
uart.any()#returnsthenumberofcharactersavailableforreading
QuickUsageExample
frommachineimportUART
#thisusestheUART_1defaultpinsforTXDandRXD(``P3``and``P4``)
uart=UART(1,baudrate=9600)
uart.write('hello')
uart.read(5)#readupto5bytes
QuickUsageExampleusingnon-defaultpins(TXD/RXD
only)
5.2.1.8UART
273
frommachineimportUART
#thisusestheUART_1non-defaultpinsforTXDandRXD(``P20``and``P21``)
uart=UART(1,baudrate=9600,pins=('P20','P21'))
uart.write('hello')
uart.read(5)#readupto5bytes
QuickUsageExampleusingnon-defaultpins(TXD/RXD
andflowcontrol)
frommachineimportUART
#thisusestheUART_1non-defaultpinsforTXD,RXD,RTSandCTS(``P20``,``P21``,`
`P22``and``P23``)
uart=UART(1,baudrate=9600,pins=('P20','P21','P22','P23'))
uart.write('hello')
uart.read(5)#readupto5bytes
Constructors
classmachine.UART(bus,...)
ConstructaUARTobjectonthegiven bus. buscanbe 0,1or2.Ifthe busisnot
given,thedefaultonewillbeselected( 0)ortheselectionwillbemadebasedonthegiven
pins.
OntheGPy/FiPyUART2isunavailablebecauseitisusedtocommunicatewiththe
cellularradio.
Methods
uart.init(baudrate=9600,bits=8,parity=None,stop=1,*,timeout_chars=2,pins=(TXD,
RXD,RTS,CTS))
InitialisetheUARTbuswiththegivenparameters:
baudrateistheclockrate.
bitsisthenumberofbitspercharacter.Canbe 5,6,7or8.
parityistheparity, None,UART.EVENorUART.ODD.
stopisthenumberofstopbits, 1or2.
timeout_charsRxtimeoutdefinedinnumberofcharacters.Thevaluegivenherewill
bemultipliedbythetimeacharacterstakestobetransmittedattheconfigured
baudrate.
5.2.1.8UART
274
pinsisa4or2itemlistindicatingtheTXD,RXD,RTSandCTSpins(inthatorder).
Anyofthepinscanbe NoneifonewantstheUARTtooperatewithlimitedfunctionality.
IftheRTSpinisgiventhetheRXpinmustbegivenaswell.ThesameappliestoCTS.
Whennopinsaregiven,thenthedefaultsetofTXD(P1)andRXD(P0)pinsistaken,
andhardwareflowcontrolwillbedisabled.If pins=None,nopinassignmentwillbe
made.
uart.deinit()
TurnofftheUARTbus.
uart.any()
Returnthenumberofcharactersavailableforreading.
uart.read([nbytes])
Readcharacters.If nbytesisspecifiedthenreadatmostthatmanybytes.
Returnvalue:abytesobjectcontainingthebytesreadin.Returns Noneontimeout.
uart.readall()
Readasmuchdataaspossible.
Returnvalue:abytesobjector Noneontimeout.
uart.readinto(buf[,nbytes])
Readbytesintothe buf.If nbytesisspecifiedthenreadatmostthatmanybytes.
Otherwise,readatmost len(buf)bytes.
Returnvalue:numberofbytesreadandstoredinto bufor Noneontimeout.
uart.readline()
Readaline,endinginanewlinecharacter.Ifsuchalineexists,returnisimmediate.Ifthe
timeoutelapses,allavailabledataisreturnedregardlessofwhetheranewlineexists.
Returnvalue:thelinereador Noneontimeoutifnodataisavailable.
uart.write(buf)
Writethebufferofbytestothebus.
Returnvalue:numberofbyteswrittenorNoneontimeout.
uart.sendbreak()
5.2.1.8UART
275
Sendabreakconditiononthebus.Thisdrivesthebuslowforadurationof13bits.Return
value: None.
uart.wait_tx_done(timeout_ms)
Waitsatmost timeout_msforthelastTxtransactiontocomplete.Returns Trueifalldata
hasbeensentandtheTXbufferhasnodatainit,otherwisereturns False.
Constants
UART.EVENUART.ODD
Paritytypes(alongwith None)
UART.RX_ANY
IRQtriggersources
5.2.1.8UART
276
classWDT–WatchdogTimer
TheWDTisusedtorestartthesystemwhentheapplicationcrashesandendsupintoanon
recoverablestate.Afterenabling,theapplicationmust"feed"thewatchdogperiodicallyto
preventitfromexpiringandresettingthesystem.
QuickUsageExample
frommachineimportWDT
wdt=WDT(timeout=2000)#enableitwithatimeoutof2seconds
wdt.feed()
Constructors
classmachine.WDT(id=0,timeout)
CreateaWDTobjectandstartit.The idcanonlybe 0.Seetheinitmethodforthe
parametersofinitialisation.
Methods
wdt.init(timeout)
Initialisesthewatchdogtimer.Thetimeoutmustbegiveninmilliseconds.Onceitisrunning
theWDTcannotbestoppedbutthetimeoutcanbere-configuredatanypointintime.
wdt.feed()
FeedtheWDTtopreventitfromresettingthesystem.Theapplicationshouldplacethiscall
inasensibleplaceensuringthattheWDTisonlyfedafterverifyingthateverythingis
functioningcorrectly.
5.2.1.9WDT
277
classTimer–MeasureTimeandSet
Alarms
Timerscanbeusedforagreatvarietyoftasks,likemeasuringtimespansorbeingnotified
thataspecificintervalhaselapsed.
Thesetwoconceptsaregroupedintotwodifferentsubclasses:
Chrono:usedtomeasuretimespans. Alarm:togetinterruptedafteraspecificinterval.
Youcancreateasmanyoftheseobjectsasneeded.
Constructors
classTimer.Chrono()
Createachronometerobject.
classTimer.Alarm(handler=None,s,*,ms,us,arg=None,periodic=False)
CreateanAlarmobject.
handler:willbecalledaftertheintervalhaselapsed.Ifsetto None,thealarmwillbe
disabledaftercreation.
arg:anoptionalargumentcanbepassedtothecallbackhandlerfunction.If Noneis
specified,thefunctionwillreceivetheobjectthattriggeredthealarm.
s,ms,us:theintervalcanbespecifiedinseconds(float),miliseconds(integer)or
microseconds(integer).Onlyoneatatimecanbespecified.
periodic:analarmcanbesettotriggerrepeatedlybysettingthisparameterto True.
Methods
Timer.sleep_us()
Delayforagivennumberofmicroseconds,shouldbepositiveor0(forspeed,thecondition
isnotenforced).Internallyitusesthesametimerastheotherelementsofthe Timerclass.
Itcompensatesforthecallingoverhead,soforexample,100usshouldbereallycloseto
100us.Fortimesbiggerthan10,000usitreleasestheGILtoletotherthreadsrun,so
exactitudeisnotguaranteedfordelayslongerthanthat.
5.2.1.10Timer
278
classChrono
Canbeusedtomeasuretimespans.
Methods
chrono.start()
Startthechronometer.
chrono.stop()
Stopthechronometer.
chrono.reset()
Resetthetimecountto0.
chrono.read()
Gettheelapsedtimeinseconds.
chrono.read_ms()
Gettheelapsedtimeinmilliseconds.
chrono.read_us()
Gettheelapsedtimeinmicroseconds.
Example:
5.2.1.10Timer
279
frommachineimportTimer
importtime
chrono=Timer.Chrono()
chrono.start()
time.sleep(1.25)#simulatethefirstlaptook1.25seconds
lap=chrono.read()#readelapsedtimewithoutstopping
time.sleep(1.5)
chrono.stop()
total=chrono.read()
print()
print("\ntheracertook%fsecondstofinishtherace"%total)
print("%fsecondsinthefirstlap"%lap)
print("%fsecondsinthelastlap"%(total-lap))
classAlarm–getinterruptedafteraspecificinterval
Methods
alarm.callback(handler,*,arg=None)
Specifyacallbackhandlerforthealarm.Ifsetto None,thealarmwillbedisabled.
Anoptionalargument argcanbepassedtothecallbackhandlerfunction.If Noneis
specified,thefunctionwillreceivetheobjectthattriggeredthealarm.
alarm.cancel()
Disablesthealarm.
Example:
frommachineimportTimer
classClock:
def__init__(self):
self.seconds=0
self.__alarm=Timer.Alarm(self._seconds_handler,1,periodic=True)
def_seconds_handler(self,alarm):
self.seconds+=1
print("%02dsecondshavepassed"%self.seconds)
ifself.seconds==10:
alarm.cancel()#stopcountingafter10seconds
clock=Clock()
5.2.1.10Timer
280
FormoreinformationonhowPycom’sproductshandleinterrupts,seenotes.
5.2.1.10Timer
281
classSD–SecuredigitalMemoryCard
TheSDcardclassallowstoconfigureandenablethememorycardmoduleofyourPycom
moduleandautomaticallymountitas /sdaspartofthefilesystem.Thereisasinglepin
combinationthatcanbeusedfortheSDcard,andthecurrentimplementationonlyworksin
1-bitmode.Thepinconnectionsareasfollows:
P8:DAT0, P23:SCLKand P4:CMD(noexternalpull-upresistorsareneeded)
IfyouhaveoneofthePycomexpansionboards,thensimplyinsertthecardintothemicro
SDsocketandrunyourscript.
MakesureyourSDcardisformattedeitherasFAT16orFAT32.
QuickExampleUsage:
frommachineimportSD
importos
sd=SD()
os.mount(sd,'/sd')
#checkthecontent
os.listdir('/sd')
#trysomestandardfileoperations
f=open('/sd/test.txt','w')
f.write('TestingSDcardwriteoperations')
f.close()
f=open('/sd/test.txt','r')
f.readall()
f.close()
Constructors
classmachine.SD(id,...)
CreateaSDcardobject.Seesd.init()forparametersifinitialisation.
Methods
5.2.1.11SD
282
classCAN–ControllerAreaNetwork
TheCANclasssupportsthefullCAN2.0specificationwithstandardandextendedframes,
aswellasacceptancefiltering.
TheESP32hasabuilt-inCANcontroller,butthetransceiverneedstobeaddedexternally.A
recommendeddeviceistheSN65HVD230.
QuickUsageExample
frommachineimportCAN
can=CAN(mode=CAN.NORMAL,baudrate=500000,pins=('P22','P23'))
can.send(id=12,data=bytes([1,2,3,4,5,6,7,8]))
can.recv()
Constructors
classmachine.CAN(bus=0,...)
CreateanCANobject.Seeinitforparametersofinitialisation.:
#only1CANperipheralisavailable,sothebusmustalwaysbe0
can=CAN(0,mode=CAN.NORMAL,baudrate=500000,pins=('P22','P23'))#pinorderis
Tx,Rx
Methods
can.init(mode=CAN.NORMAL,baudrate=500000,*,frame_format=CAN.FORMAT_STD,
rx_queue_len=128,pins=('P22','P23'))
InitializetheCANcontroller.Theargumentsare:
modecantakeeitherCAN.NORMALorCAN.SILENT.Silentmodeisusefulforsniffing
thebus.
baudratesetsupthebusspeed.Acceptablevaluesarebetween1and1000000.
frame_formatdefinestheframeformattobeacceptedbythereceiver.Usefulfor
filteringframesbasedontheidentifierlength.CantaleeitherCAN.FORMAT_STDor
CAN.FORMAT_EXTorCAN.FORMAT_BOTH.IfCAN.FORMAT_STDisselected,
extendedframeswon'tbereceivedandvice-versa.
5.2.1.12CAN
284
rx_queue_lendefinesthenumberofmessagesthancanbequeuedbythereceiver.
DuetoCANbeingahightrafficbus,largevaluesarerecommended(>=128),otherwise
messageswillbedroppedspeciallywhennofilteringisapplied.
pinsselectsthe Txand Rxpins(inthatorder).
can.deinit()
DisablestheCANbus.
#disabletheCANbus
can.deinit()
can.send(id,*,data=None,rtr=False,extended=False)
SendaCANframeonthebus
idistheidentifierofthemessage.
datacantakeupto8bytes.Itmustbeleftemptyisthemessagetobesentisa
remoterequest(rtr=True).
rtrsetittofalsetosendaremoterequest.
extntedspecifiesifthemessageidentifierwidthshouldbe11bit(standard)or29bit
(extended).
Canbeusedlike:
can.send(id=0x0020,data=bytes([0x01,0x02,0x03,0x04,0x05]),extended=True)#sen
ds5byteswithanextendedidentifier
can.send(id=0x010,data=bytes([0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08]))#sen
ds8byteswithanstandardidentifier
can.send(id=0x012,rtr=True)#sendsaremoterequestformessageid=0x12
can.recv(timeout=0)
Getamessagefromthereceivequeue,andoptionallyspecifyatimeoutvalueins(canbea
floatingpointvaluee.g. 0.2).Thisfunctionreturns Noneifnomessagesavailable.Ifa
messageispresent,itwillbereturnedasanamedtuplewiththefollowingform:
(id,data,rtr,extended)
>>>can.recv()
(id=0x012,data=b'123',rtr=False,extended=False)
can.soft_filter(mode,filter_list)
5.2.1.12CAN
285
Specifyasoftwarefilteracceptingonlythemessagesthatpassthefiltertest.
Thereare3possiblefiltermodes:
CAN.FILTER_LISTallowstopassthelistofIDsthatshouldbeaccepted.
CAN.FILTER_RANGEallowstopassalistortupleofIDrangesthatshouldbe
accepted.
CAN.FILTER_MASKallowstopassalistoftuplesoftheform: (filer,mask).
WithsoftwarefiltersallmessagesinthebusarereceivedbytheCANcontrollerbutonlythe
matchingonesarepassedtotheRXqueue.Thismeansthatthequeuewon'tbefilledup
withnonrelevantmessages,buttheinterruptoverheadwillremainasnormal.The
filter_listcancontainupto32elements.
Forexample:
can.soft_filter(CAN.FILTER_LIST,[0x100,0x200,0x300,0x400])#onlyacceptidentifi
ersfrom0x100,0x200,0x300and0x400
can.soft_filter(CAN.FILTER_RANGE,[(0x001,0x010),(0x020,0x030),(0x040,0x050)])#
onlyacceptidentifiersfrom0x001to0x010,from0x020to0x030andfrom0x040to0x
050.
can.soft_filter(CAN.FILTER_MASK,[(0x100,0x7FF),(0x200,0x7FC)])#moreoftheclass
icFilterandMaskmethod.
can.soft_filter(None)#disablesoftfilters,allmessagesareaccepted
can.callback(trigger,handler=None,arg=None)
Setacallbacktobetriggeredwhenanyofthis3eventsarepresent:
triggeristhetypeofeventthattriggersthecallback.Possiblevaluesare:
CAN.RX_FRAMEinterruptwheneveranewframeisreceived.
CAN.RX_FIFO_NOT_EMPTYinterruptwhenaframeisreceivedonanempty
FIFO.
CAN.RX_FIFO_OVERRUNinterruptwhenamessageisreceivedandtheFIFOis
full.
ThevaluescanbeOR-edtogether,forinstancetrigger=CAN.RX_FRAME|
CAN.RX_FIFO_OVERRUN
handleristhefunctiontobecalledwhentheeventhappens.Thisfunctionwillreceive
oneargument.SethandlertoNonetodisablethecallback.
argisanoptionalargumenttopasstothecallback.IfleftemptyorsettoNone,the
functionwillreceivetheCANobjectthattriggeredit.
5.2.1.12CAN
286
Itcanbeusedlikethis:
frommachineimportCAN
can=CAN(mode=CAN.NORMAL,baudrate=500000,pins=('P22','P23'))
defcan_cb(can_o):
print('CANRx:',can_o.recv())
can.callback(handler=can_cb,trigger=CAN.RX_FRAME)
can.events()
Thismethodreturnsavaluewithbitssets(ifany)indicatingtheeventsthathaveoccurredin
thebus.Pleasenotethatbycallingthisfunctiontheinternaleventsregistryiscleared
automatically,thereforecallingitimmediatelyforasecondtimewillmostlikelyreturnavalue
of0.
Constants
CAN.NORMALCAN.SILENTCAN.FORMAT_STDCAN.FORMAT_EXT
CAN.FORMAT_BOTHCAN.RX_FRAMECAN.RX_FIFO_NOT_EMPTY
CAN.RX_FIFO_OVERRUNCAN.FILTER_LISTCAN.FILTER_RANGECAN.FILTER_MASK
5.2.1.12CAN
287
classRMT–RemoteController
TheRMT(RemoteControl)moduleisprimarilydesignedtosendandreceiveinfrared
remotecontrolsignalsthatuseon-off-keyingofacarrierfrequency,butduetoitsdesignit
canbeusedtogeneratevarioustypesofsignals.
QuickUsageExample:sending
importmachine
#createaRMTobjectfortransmission
rmt=machine.RMT(channel=3,gpio="P20",tx_idle_level=0)
#createseriesofbitstosend
data=(1,0,1,0,1,0,1,0,1)
#definedurationofthebits,timeunitdependsontheselectedRMTchannel
duration=10000
#sendthesignal
rmt.send_pulses(duration,data)
QuickUsageExample:receiving
importmachine
#createaRMTobject
rmt=machine.RMT(channel=3)
#ConfigureRTMforreceiving
rmt.init(gpio="P20",rx_idle_threshold=12000)
#waitforanynumberofpulsesuntilonelongerthanrx_idle_threshold
data=rmt.recv_pulses()
Constructors
classmachine.RMT(channel,...)
ConstructanRMTobjectonthegivenchannel. channelcanbe2-7.Withnoadditional
parameters,theRMTobjectiscreatedbutnotinitialised.Ifextraargumentsaregiven,the
RMTisinitialisedfortransmissionorreception.See initforparametersofinitialisation.
Theresolutionwhichapulsecanbesent/receiveddependsontheselectedchannel:
5.2.1.13RMT
288
Channel Resolution MaximumPulseWidth
0 Usedbyon-boardLED
1 Usedby pycom.pulses_get()
2 100nS 3.2768ms
3 100nS 3.2768ms
4 1000nS 32.768ms
5 1000nS 32.768ms
6 3125nS 102.4ms
7 3125nS 102.4ms
Methods
rmt.init(gpio,rx_idle_threshold,rx_filter_threshold,tx_idle_level,tx_carrier)
InitialisetheRMTperipheralwiththegivenparameters:
gpioistheGPIOPintouse.
rx_idle_thresholdisthemaximumdurationofavalidpulse.Therepresentedtimeunit
(resolution)dependsontheselectedchannel,valuecanbe0-65535.
rx_filter_thresholdistheminimumdurationofavalidpulse.Therepresentedtime
unit(resolution)dependsontheselectedchannel,valuecanbe0-31.
tx_idle_levelistheoutputsignal'slevelafterthetransmissionisfinished,canbe
RMT.HIGHorRMT.LOW.
tx_carrieristhemodulationofthepulsestosend.
Either rx_idle_thresholdor tx_idle_levelmustbedefined,bothcannotbegivenatthe
sametimebecauseachannelcanbeconfiguredinRXorTXmodeonly.
rx_filter_thresholdisnotmandatoryparameter.Ifnotgiventhenallpulsesareaccepted
withdurationlessthan rx_idle_threshold. tx_carrierisnotmandatoryparameters.Ifnot
givennomodulationisusedonthesentpulses.
The tx_carrierparameterisatuplewiththefollowingstructure:
carrier_freq_hzisthecarrier'sfrequencyinHz.
carrier_duty_percentisthedutypercentofthecarrier'ssignal,canbe0%-100%.
carrier_levelisthelevelofthepulsetomodulate,canbeRMT.HIGHorRMT.LOW.
rmt.deinit()
DeinitialisetheRMTobject.
5.2.1.13RMT
289
IfanRMTobjectneedstobereconfiguredfromRX/TXtoTX/RX,theneitherfirst
deinit()mustbecalledorthe init()againwiththedesiredconfiguration.
rmt.pulses_get(pulses,timeout)
ReadsinpulsesfromtheGPIOpin.
pulsesifnotspecified,thisfunctionwillkeepreadingpulsesuntilthe
rx_idle_thresholdisexceeded.Ifitisspecifiedthisfunctionwillreturntheexactlythat
numberofpulses,ignoringanythingshorterthan rx_filter_thresholdorlongerthan
rx_idle_threshold.
timeoutisspecified,thisfunctionwillreturnifthefirstpulsedoesnotoccurwithin
timeoutmicroseconds.Ifnotspecified,itwillwaitindefinitely.
Returnvalue:Tupleofitemswiththefollowingstructure:(level,duration):
levelrepresentsthelevelofthereceivedbit/pulse,canbe0or1.
durationrepresentsthedurationofthereceivedpulse,thetimeunit(resolution)
dependsontheselectedchannel.
Maximumof128pulsescanbereceivedinarowwithoutreceiving"idle"signal.Ifthe
incomingpulsesequencecontainsmorethan128pulsestherestisdroppedandthe
receiverwaitsforanothersequenceofpulses.The pulses_getfunctioncanbecalled
toreceivemorethan128pulses,howevertheabovementionedlimitationshouldbe
keptinmindwhenevaluatingthereceiveddata.
rmt.pulses_send(duration,data,start_level)
Generatespulsesasdefinedbytheparametersbelow
durationrepresentsthedurationofthepulsestobesent,thetimeunit(resolution)
dependsontheselectedchannel.
dataTuplethatrepresentsthesequenceofpulsestobesent,mustbecomposedof0
or1elements.
start_leveldefinesthestate(HIGH/LOW)ofthefirstpulsegivenby durationif
dataisnotgiven.
datamustbeatupleand durationcanbeatupleorasinglenumber,with databeing
optional.Inthecasethatonly durationisprovided,itmustbeatupleandyoumustalso
provide start_levelwhichwilldictatethelevelofthefirstduration,thesignallevelthen
togglesbetweeneachdurationvalue.If dataisprovidedand durationisasinglenumber,
5.2.1.13RMT
290
classWLAN
ThisclassprovidesadriverfortheWiFinetworkprocessorinthemodule.Exampleusage:
importnetwork
importtime
#setupasastation
wlan=network.WLAN(mode=network.WLAN.STA)
wlan.connect('your-ssid',auth=(network.WLAN.WPA2,'your-key'))
whilenotwlan.isconnected():
time.sleep_ms(50)
print(wlan.ifconfig())
#nowusesocketasusual
QuickUsageExample
importmachine
fromnetworkimportWLAN
#configuretheWLANsubsysteminstationmode(thedefaultisAP)
wlan=WLAN(mode=WLAN.STA)
#goforfixedIPsettings(IP,Subnet,Gateway,DNS)
wlan.ifconfig(config=('192.168.0.107','255.255.255.0','192.168.0.1','192.168.0.1'))
wlan.scan()#scanforavailablenetworks
wlan.connect(ssid='mynetwork',auth=(WLAN.WPA2,'my_network_key'))
whilenotwlan.isconnected():
pass
print(wlan.ifconfig())
Constructors
classnetwork.WLAN(id=0,...)
CreateaWLANobject,andoptionallyconfigureit.Seeinitforparamsofconfiguration.
TheWLANconstructorisspecialinthesensethatifnoargumentsbesidesthe idare
given,itwillreturnthealreadyexistingWLANinstancewithoutre-configuringit.Thisis
becauseWLANisasystemfeatureoftheWiPy.Ifthealreadyexistinginstanceisnot
initialiseditwilldothesameastheotherconstructorsanwillinitialiseitwithdefault
values.
5.2.2.1WLAN
293
Methods
wlan.init(mode,*,ssid=None,auth=None,channel=1,antenna=None,
power_save=False,hidden=False)
SetorgettheWiFinetworkprocessorconfiguration.
Argumentsare:
modecanbeeitherWLAN.STA,WLAN.APorWLAN.STA_AP.
ssidisastringwiththeSSIDname.OnlyneededwhenmodeisWLAN.AP.
authisatuplewith(sec,key).Securitycanbe None,WLAN.WEP,WLAN.WPAor
WLAN.WPA2.Thekeyisastringwiththenetworkpassword.If secisWLAN.WEPthe
keymustbeastringrepresentinghexadecimalvalues(e.g. ABC1DE45BF).Onlyneeded
whenmodeisWLAN.AP.
channelanumberintherange1-11.OnlyneededwhenmodeisWLAN.AP.
antennaselectsbetweentheinternalandtheexternalantenna.Canbeeither
WLAN.INT_ANT,WLAN.EXT_ANT.Withourdevelopmentboardsitdefaultstousing
theinternalantenna,butinthecaseofanOEMmodule,theantennapin( P12)isnot
used,soit’sfreetobeusedforotherthings.
power_saveenablesordisablespowersavefunctionsinSTAmode.
hiddenonlyvalidinWLAN.APmodetocreateanaccesspointwithahiddenSSID
whensetto True.
Forexample,youcando:
#createandconfigureasanaccesspoint
wlan.init(mode=WLAN.AP,ssid='wipy-wlan',auth=(WLAN.WPA2,'www.wipy.io'),channel=7,a
ntenna=WLAN.INT_ANT)
or:
#configureasanstation
wlan.init(mode=WLAN.STA)
wlan.deinit()
DisablestheWiFiradio.
wlan.connect(ssid,*,auth=None,bssid=None,timeout=None,ca_certs=None,
keyfile=None,certfile=None,identity=None)
ConnecttoawifiaccesspointusingthegivenSSID,andothersecurityparameters.
5.2.2.1WLAN
294
authisatuplewith (sec,key).Securitycanbe None,WLAN.WEP,WLAN.WPA,
WLAN.WPA2orWLAN.WPA2_ENT.Thekeyisastringwiththenetworkpassword.If
secisWLAN.WEPthekeymustbeastringrepresentinghexadecimalvalues(e.g.
ABC1DE45BF).If secisWLAN.WPA2_ENTthenthe authtuplecanhaveeither3
elements: (sec,username,password),orjust1: (sec,).Whenpassingthe3element
tuple,the keyfileand certifleargumentsmustnotbegiven.
bssidistheMACaddressoftheAPtoconnectto.UsefulwhenthereareseveralAPs
withthesameSSID.
timeoutisthemaximumtimeinmillisecondstowaitfortheconnectiontosucceed.
ca_certsisthepathtotheCAcertificate.Thisargumentisnotmandatory. keyfileis
thepathtotheclientkey.Onlyusedif usernameand passwordarenotpartofthe
authtuple.
certfileisthepathtotheclientcertificate.Onlyusedif usernameand passwordare
notpartofthe authtuple.
identityisonlyusedincaseofWLAN.WPA2_ENTsecurity.
wlan.scan()
Performsanetworkscanandreturnsalistofnamedtupleswith (ssid,bssid,sec,
channel,rssi).Notethatchannelisalways Nonesincethisinfoisnotprovidedbythe
WiPy.
wlan.disconnect()
DisconnectfromtheWiFiaccesspoint.
wlan.isconnected()
IncaseofSTAmode,returns TrueifconnectedtoaWiFiaccesspointandhasavalidIP
address.InAPmodereturns Truewhenastationisconnected, Falseotherwise.
wlan.ifconfig(id=0,config=['dhcp'orconfigtuple])
When idis0,theconfigurationwillbeget/setontheStationinterface.When idis1the
configurationwillbedonefortheAPinterface.
Withnoparametersgivenreturnsa4-tupleof (ip,subnet_mask,gateway,DNS_server).
If dhcpispassedasaparameterthentheDHCPclientisenabledandtheIPparamsare
negotiatedwiththeAP.
Ifthe4-tupleconfigisgiventhenastaticIPisconfigured.Forinstance:
wlan.ifconfig(config=('192.168.0.4','255.255.255.0','192.168.0.1','8.8.8.8'))
5.2.2.1WLAN
295
wlan.mode([mode])
GetorsettheWLANmode.
wlan.ssid([ssid])
GetorsettheSSIDwheninAPmode.
wlan.auth([auth])
GetorsettheauthenticationtypewheninAPmode.
wlan.channel([channel])
Getorsetthechannel(onlyapplicableinAPmode).
wlan.antenna([antenna])
Getorsettheantennatype(externalorinternal).
wlan.mac()
Geta6-bytelong bytesobjectwiththeWiFIMACaddress.
Constants
WLAN.STAWLAN.APWLAN.STA_AP
WLANmode
WLAN.WEPWLAN.WPAWLAN.WPA2WLAN.WPA2_ENT
WLANnetworksecurity
WLAN.INT_ANTWLAN.EXT_ANT
Antennatype
5.2.2.1WLAN
296
classServer
The ServerclasscontrolsthebehaviourandtheconfigurationoftheFTPandtelnet
servicesrunningonthePycomdevice.Anychangesperformedusingthisclass’methods
willaffectboth.
Example:
importnetwork
server=network.Server()
server.deinit()#disabletheserver
#enabletheserveragainwithnewsettings
server.init(login=('user','password'),timeout=600)
QuickUsageExample
fromnetworkimportServer
#initwithnewuser,passwordandsecondstimeout
server=Server(login=('user','password'),timeout=60)
server.timeout(300)#changethetimeout
server.timeout()#getthetimeout
server.isrunning()#checkwhethertheserverisrunningornot
Constructors
classnetwork.Server(id,...)
Createaserverinstance,see initforparametersofinitialisation.
Methods
server.init(*,login=('micro','python'),timeout=300)
Init(andeffectivelystarttheserver).Optionallyanew user, passwordand timeout(in
seconds)canbepassed.
server.deinit()
Stoptheserver.
server.timeout([timeout_in_seconds])
5.2.2.2Server
297
classBluetooth
ThisclassprovidesadriverfortheBluetoothradiointhemodule.Currently,onlybasicBLE
functionalityisavailable.
QuickUsageExample
fromnetworkimportBluetooth
importtime
bt=Bluetooth()
bt.start_scan(-1)
whileTrue:
adv=bt.get_adv()
ifadvandbt.resolve_adv_data(adv.data,Bluetooth.ADV_NAME_CMPL)=='HeartRate':
try:
conn=bt.connect(adv.mac)
services=conn.services()
forserviceinservices:
time.sleep(0.050)
iftype(service.uuid())==bytes:
print('Readingcharsfromservice={}'.format(service.uuid()))
else:
print('Readingcharsfromservice=%x'%service.uuid())
chars=service.characteristics()
forcharinchars:
if(char.properties()&Bluetooth.PROP_READ):
print('char{}value={}'.format(char.uuid(),char.read()))
conn.disconnect()
break
except:
print("ErrorwhileconnectingorreadingfromtheBLEdevice")
break
else:
time.sleep(0.050)
BluetoothLowEnergy(BLE)
Bluetoothlowenergy(BLE)isasubsetofclassicBluetooth,designedforeasyconnecting
andcommunicatingbetweendevices(inparticularmobileplatforms).BLEusesa
methodologyknownasGenericAccessProfile(GAP)tocontrolconnectionsand
advertising.
5.2.2.3Bluetooth
299
GAPallowsfordevicestotakevariousrolesbutgenericflowworkswithdevicesthatare
eitheraServer(lowpower,resourceconstrained,sendingsmallpayloadsofdata)oraClient
device(commonlyamobiledevice,PCorPycomDevicewithlargeresourcesand
processingpower).PycomdevicescanactasbothaClientandaServer.
Constructors
classnetwork.Bluetooth(id=0,...)
CreateaBluetoothobject,andoptionallyconfigureit.Seeinitforparamsofconfiguration.
Example:
fromnetworkimportBluetooth
bluetooth=Bluetooth()
Methods
bluetooth.init(id=0,mode=Bluetooth.BLE,antenna=None)
idOnlyoneBluetoothperipheralavailablesomustalwaysbe0
modecurrentlytheonlysupportedmodeis Bluetooth.BLE
antennaselectsbetweentheinternalandtheexternalantenna.Canbeeither
Bluetooth.INT_ANT,Bluetooth.EXT_ANT.Withourdevelopmentboardsitdefaultsto
usingtheinternalantenna,butinthecaseofanOEMmodule,theantennapin( P12)is
notused,soit’sfreetobeusedforotherthings.
InitialisesandenablestheBluetoothradioinBLEmode.
bluetooth.deinit()
DisablestheBluetoothradio.
bluetooth.start_scan(timeout)
StartsperformingascanlisteningforBLEdevicessendingadvertisements.Thisfunction
alwaysreturnsimmediately,thescanningwillbeperformedonthebackground.Thereturn
valueis None.Afterstartingthescanthefunctionget_adv()canbeusedtoretrievethe
advertisementsmessagesfromtheFIFO.TheinternalFIFOhasspacetocache16
advertisements.
Theargumentsare:
timeoutspecifiestheamountoftimeinsecondstoscanforadvertisements,cannotbe
5.2.2.3Bluetooth
300
zero.Iftimeoutis>0,thentheBLEradiowilllistenforadvertisementsuntilthespecified
valueinsecondselapses.Iftimeout<0,thenthere’snotimeoutatall,andstop_scan()
needstobecalledtocancelthescanningprocess.
Examples:
bluetooth.start_scan(10)#startsscanningandstopafter10seconds
bluetooth.start_scan(-1)#startsscanningindefinitelyuntilbluetooth.stop_sc
an()iscalled
bluetooth.stop_scan()
Stopsanongoingscanningprocess.Returns None.
bluetooth.isscanning()
Returns TrueifaBluetoothscanisinprogress. Falseotherwise.
bluetooth.get_adv()
Getsannamedtuplewiththeadvertisementdatareceivedduringthescanning.Thetuple
hasthefollowingstructure: (mac,addr_type,adv_type,rssi,data)
macisthe6-bytelingmacaddressofthedevicethatsenttheadvertisement.
addr_typeistheaddresstype.Seetheconstantssectionbelowformoredetails.
adv_typeistheadvertisementtypereceived.Seetheconstantssectionbelowfromore
details.
rssiissignedintegerwiththesignalstrengthoftheadvertisement.
datacontainsthecomplete31bytesoftheadvertisementmessage.Inordertoparse
thedataandgetthespecifictypes,themethodresolve_adv_data()canbeused.
Exampleforgetting macaddressofanadvertiser:
importubinascii
bluetooth=Bluetooth()
bluetooth.start_scan(20)#scanfor20seconds
adv=bluetooth.get_adv()#
ubinascii.hexlify(adv.mac)#converthexadecimaltoascii
bluetooth.get_advertisements()
Sameasthe get_adv()method,butthisonereturnsalistwithalltheadvertisements
received.
5.2.2.3Bluetooth
301
bluetooth.resolve_adv_data(data,data_type)
Parsestheadvertisementdataandreturnstherequested data_typeifpresent.Ifthedata
typeisnotpresent,thefunctionreturns None.
Arguments:
dataisthebytesobjectwiththecompleteadvertisementdata.
data_typeisthedatatypetoresolvefromfromtheadvertisementdata.Seeconstants
sectionbelowfordetails.
Example:
importubinascii
fromnetworkimportBluetooth
bluetooth=Bluetooth()
bluetooth.start_scan(20)
whilebluetooth.isscanning():
adv=bluetooth.get_adv()
ifadv:
#trytogetthecompletename
print(bluetooth.resolve_adv_data(adv.data,Bluetooth.ADV_NAME_CMPL))
mfg_data=bluetooth.resolve_adv_data(adv.data,Bluetooth.ADV_MANUFACTURER_DAT
A)
ifmfg_data:
#trytogetthemanufacturerdata(Apple'siBeacondataissenthere)
print(ubinascii.hexlify(mfg_data))
bluetooth.connect(mac_addr)
OpensaBLEconnectionwiththedevicespecifiedbythe mac_addrargument.Thisfunction
blocksuntiltheconnectionsucceedsorfails.Iftheconnectionssucceedsitreturnsaobject
oftype GATTCConnection.
bluetooth.connect('112233eeddff')#macaddressisacceptedasastring
bluetooth.callback(trigger=None,handler=None,arg=None)
Createsacallbackthatwillbeexecutedwhenanyofthetriggersoccurs.Thearguments
are:
triggercanbeeitherBluetooth.NEW_ADV_EVENT,
Bluetooth.CLIENT_CONNECTEDorBluetooth.CLIENT_DISCONNECTED
handleristhefunctionthatwillbeexecutedwhenthecallbackistriggered.
5.2.2.3Bluetooth
302
argistheargumentthatgetspassedtothecallback.Ifnothingisgiventhebluetooth
objectitselfisused.
Anexampleofhowthismaybeusedcanbeseeninthebluetooth.events()method.
bluetooth.events()
Returnsavaluewithbitflagsidentifyingtheeventsthathaveoccurredsincethelastcall.
Callingthisfunctionclearstheevents.
Exampleofusage:
fromnetworkimportBluetooth
bluetooth=Bluetooth()
bluetooth.set_advertisement(name='LoPy',service_uuid=b'1234567890123456')
defconn_cb(bt_o):
events=bt_o.events()#thismethodreturnstheflagsandclearstheinternalr
egistry
ifevents&Bluetooth.CLIENT_CONNECTED:
print("Clientconnected")
elifevents&Bluetooth.CLIENT_DISCONNECTED:
print("Clientdisconnected")
bluetooth.callback(trigger=Bluetooth.CLIENT_CONNECTED|Bluetooth.CLIENT_DISCONNECTED,
handler=conn_cb)
bluetooth.advertise(True)
bluetooth.set_advertisement(*,name=None,manufacturer_data=None,
service_data=None,service_uuid=None)
Configurethedatatobesentwhileadvertising.Ifleftwiththedefaultof Nonethedatawon’t
bepartoftheadvertisementmessage.
Theargumentsare:
nameisthestringnametobeshownonadvertisements.
manufacturer_datamanufacturerdatatobeadvertised(hint:useitforiBeacons).
service_dataservicedatatobeadvertised.
service_uuiduuidoftheservicetobeadvertised.
Example:
bluetooth.set_advertisement(name="advert",manufacturer_data="lopy_v1")
5.2.2.3Bluetooth
303
bluetooth.advertise([Enable])
Startorstopsendingadvertisements.Theset_advertisement()methodmusthavebeen
calledpriortothisone.
bluetooth.service(uuid,*,isprimary=True,nbr_chars=1,start=True)
CreateanewserviceontheinternalGATTserver.Returnsaobjectoftype
BluetoothServerService.
Theargumentsare:
uuidistheUUIDoftheservice.Cantakeanintegerora16bytelongstringorbytes
object.
isprimaryselectsiftheserviceisaprimaryone.Takesa boolvalue.
nbr_charsspecifiesthenumberofcharacteristicsthattheservicewillcontain.
startif Truetheserviceisstartedimmediately.
bluetooth.service('abc123')
bluetooth.disconnect_client()
ClosestheBLEconnectionwiththeclient.
Constants
Bluetoothmode
Bluetooth.BLE
Advertisementtype
Bluetooth.CONN_ADVBluetooth.CONN_DIR_ADVBluetooth.DISC_ADV
Bluetooth.NON_CONN_ADVBluetooth.SCAN_RSP
Addresstype
Bluetooth.PUBLIC_ADDRBluetooth.RANDOM_ADDRBluetooth.PUBLIC_RPA_ADDR
Bluetooth.RANDOM_RPA_ADDR
Advertisementdatatype
Bluetooth.ADV_FLAGBluetooth.ADV_16SRV_PARTBluetooth.ADV_T16SRV_CMPL
Bluetooth.ADV_32SRV_PARTBluetooth.ADV_32SRV_CMPL
Bluetooth.ADV_128SRV_PARTBluetooth.ADV_128SRV_CMPL
5.2.2.3Bluetooth
304
Bluetooth.ADV_NAME_SHORTBluetooth.ADV_NAME_CMPLBluetooth.ADV_TX_PWR
Bluetooth.ADV_DEV_CLASSBluetooth.ADV_SERVICE_DATA
Bluetooth.ADV_APPEARANCEBluetooth.ADV_ADV_INT
Bluetooth.ADV_32SERVICE_DATABluetooth.ADV_128SERVICE_DATA
Bluetooth.ADV_MANUFACTURER_DATA
Characteristicproperties(bitvaluesthatcanbecombined)
Bluetooth.PROP_BROADCASTBluetooth.PROP_READBluetooth.PROP_WRITE_NR
Bluetooth.PROP_WRITEBluetooth.PROP_NOTIFYBluetooth.PROP_INDICATE
Bluetooth.PROP_AUTHBluetooth.PROP_EXT_PROP
Characteristiccallbackevents
Bluetooth.CHAR_READ_EVENTBluetooth.CHAR_WRITE_EVENT
Bluetooth.NEW_ADV_EVENTBluetooth.CLIENT_CONNECTED
Bluetooth.CLIENT_DISCONNECTEDBluetooth.CHAR_NOTIFY_EVENT
Antennatype
Bluetooth.INT_ANTBluetooth.EXT_ANT
5.2.2.3Bluetooth
305
GenericAttribute
GATTstandsfortheGenericAttributeProfileanditdefinesthewaythattwoBluetoothLow
EnergydevicescommunicatebetweeneachotherusingconceptscalledServicesand
Characteristics.GATTusesadataprotocolknownastheAttributeProtocol(ATT),whichis
usedtostore/manageServices,Characteristicsandrelateddatainalookuptable.
GATTcomesintouseonceaconnectionisestablishedbetweentwodevices,meaningthat
thedevicewillhavealreadygonethroughtheadvertisingprocessmanagedbyGAP.It’s
importanttorememberthatthisconnectionisexclusive;i.e.thatonlyoneclientisconnected
tooneserveratatime.Thismeansthattheclientwillstopadvertisingonceaconnection
hasbeenmade.Thisremainsthecase,untiltheconnectionisbrokenordisconnected.
TheGATTServer,whichholdstheATTlookupdataandserviceandcharacteristic
definitions,andtheGATTClient(thephone/tablet),whichsendsrequeststothisserver.
5.2.2.3Bluetooth
306
classGATTCConnection
TheGATTClientisthedevicethatrequestsdatafromtheserver,otherwiseknownasthe
masterdevice(commonlythismightbeaphone/tablet/PC).Alltransactionsareinitiatedby
themaster,whichreceivesaresponsefromtheslave.
connection.disconnect()
ClosestheBLEconnection.Returns None.
connection.isconnected()
Returns Trueiftheconnectionisstillopen. Falseotherwise.
Example:
fromnetworkimportBluetooth
importubinascii
bluetooth=Bluetooth()
#scanuntilwecanconnecttoanyBLEdevicearound
bluetooth.start_scan(-1)
adv=None
whileTrue:
adv=bluetooth.get_adv()
ifadv:
try:
bluetooth.connect(adv.mac)
except:
#startscanningagain
bluetooth.start_scan(-1)
continue
break
print("Connectedtodevicewithaddr={}".format(ubinascii.hexlify(adv.mac)))
connection.services()
PerformsaservicesearchontheconnectedBLEperipheral(server)areturnsalist
containingobjectsoftheclassGATTCServiceifthesearchsucceeds.
Example:
5.2.2.3Bluetooth
307
#assumingthataBLEconnectionisalreadyopen
services=connection.services()
print(services)
forserviceinservices:
print(service.uuid())
5.2.2.3Bluetooth
308
classGATTCService
Servicesareusedtocategorisedataupintospecificchunksofdataknownas
characteristics.Aservicemayhavemultiplecharacteristics,andeachservicehasaunique
numericIDcalledaUUID.
ThefollowingclassallowscontroloverClientservices.
service.isprimary()
Returns Trueiftheserviceisaprimaryone. Falseotherwise.
service.uuid()
ReturnstheUUIDoftheservice.Inthecaseof16-bitor32-bitlongUUIDs,thevalue
returnedisaninteger,butfor128-bitlongUUIDsthevaluereturnedisabytesobject.
service.instance()
ReturnstheinstanceIDoftheservice.
service.characteristics()
PerformsagetcharacteristicsrequestontheconnectedBLEperipheralareturnsalist
containingobjectsoftheclassGATTCCharacteristiciftherequestsucceeds.
5.2.2.3Bluetooth
309
classGATTCCharacteristic
ThesmallestconceptinGATTistheCharacteristic,whichencapsulatesasingledatapoint
(thoughitmaycontainanarrayofrelateddata,suchasX/Y/Zvaluesfroma3-axis
accelerometer,longitudeandlatitudefromaGPS,etc.).
ThefollowingclassallowsyoutomanagecharacteristicsfromaClient.
characteristic.uuid()
ReturnstheUUIDoftheservice.Inthecaseof16-bitor32-bitlongUUIDs,thevalue
returnedisaninteger,butfor128-bitlongUUIDsthevaluereturnedisabytesobject.
characteristic.instance()
ReturnstheinstanceIDoftheservice.
characteristic.properties()
Returnsanintegerindicatingthepropertiesofthecharacteristic.Propertiesarerepresented
bybitvaluesthatcanbeOR-edtogether.Seetheconstantssectionformoredetails.
characteristic.read()
Readthevalueofthecharacteristic,sendingarequesttotheGATTserver.Returnsabytes
objectrepresentingthecharacteristicvalue.
characteristic.value()
Returnsthelocallystoredvalueofthecharacteristicwithoutsendingareadrequesttothe
GATTserver.Ifthecharacteristicvaluehasn'tbeenreadfromtheGATTserveryet,thevalue
returnedwillbe0.
characteristic.write(value)
Writesthegivenvalueonthecharacteristic.Fornowitonlyacceptsbytesobject
representingthevaluetobewritten.
characteristic.write(b'x0f')
characteristic.callback(trigger=None,handler=None,arg=None)
Thismethodallowstoregisterfornotificationsonthecharacteristic.
5.2.2.3Bluetooth
310
triggercanmustbeBluetooth.CHAR_NOTIFY_EVENT.
handleristhefunctionthatwillbeexecutedwhenthecallbackistriggered.
argistheargumentthatgetspassedtothecallback.Ifnothingisgiven,the
characteristicobjectthatownsthecallbackwillbeused.
5.2.2.3Bluetooth
311
classGATTSService
TheGATTServerallowsthedevicetoactasaperipheralandholditsownATTlookupdata,
server&characteristicdefinitions.Inthismode,thedeviceactsasaslaveandamaster
mustinitiatearequest.
Servicesareusedtocategorisedataupintospecificchunksofdataknownas
characteristics.Aservicemayhavemultiplecharacteristics,andeachservicehasaunique
numericIDcalledaUUID.
ThefollowingclassallowscontroloverServerservices.
service.start()
Startstheserviceifnotalreadystarted.
service.stop()
Stopstheserviceifpreviouslystarted.
service.characteristic(uuid,*,permissions,properties,value)
Createsanewcharacteristicontheservice.Returnsanobjectoftheclass
GATTSCharacteristic.Theargumentsare:
uuidistheUUIDoftheservice.Cantakeanintegerora16bytelongstringorbytes
object.
permissionsconfiguresthepermissionsofthecharacteristic.Takesanintegerwitha
combinationoftheflags.
propertiessetstheproperties.TakesanintegerwithanOR-edcombinationofthe
flags.
valuesetstheinitialvalue.Cantakeaninteger,astringorabytesobject.
service.characteristic('temp',value=25)
5.2.2.3Bluetooth
312
classGATTSCharacteristic
ThesmallestconceptinGATTistheCharacteristic,whichencapsulatesasingledatapoint
(thoughitmaycontainanarrayofrelateddata,suchasX/Y/Zvaluesfroma3-axis
accelerometer,longitudeandlatitudefromaGPS,etc.).
ThefollowingclassallowsyoutomanageServercharacteristics.
characteristic.value([value])
Getsorsetsthevalueofthecharacteristic.Cantakeaninteger,astringorabytesobject.
characteristic.value(123)#setcharacteristicvaluetoanintegerwiththevalue123
characteristic.value()#getcharacteristicvalue
characteristic.callback(trigger=None,handler=None,arg=None)
Createsacallbackthatwillbeexecutedwhenanyofthetriggersoccurs.Thearguments
are:
triggercanbeeitherBluetooth.CHAR_READ_EVENTor
Bluetooth.CHAR_WRITE_EVENT.
handleristhefunctionthatwillbeexecutedwhenthecallbackistriggered.
argistheargumentthatgetspassedtothecallback.Ifnothingisgiven,the
characteristicobjectthatownsthecallbackwillbeused.
Anexampleofhowthiscouldbeimplementedcanbeseeninthecharacteristic.events()
section.
characteristic.events()
Returnsavaluewithbitflagsidentifyingtheeventsthathaveoccurredsincethelastcall.
Callingthisfunctionclearstheevents.
Anexampleofadvertisingandcreatingservicesonthedevice:
5.2.2.3Bluetooth
313
fromnetworkimportBluetooth
bluetooth=Bluetooth()
bluetooth.set_advertisement(name='LoPy',service_uuid=b'1234567890123456')
defconn_cb(bt_o):
events=bt_o.events()
ifevents&Bluetooth.CLIENT_CONNECTED:
print("Clientconnected")
elifevents&Bluetooth.CLIENT_DISCONNECTED:
print("Clientdisconnected")
bluetooth.callback(trigger=Bluetooth.CLIENT_CONNECTED|Bluetooth.CLIENT_DISCONNECTED,
handler=conn_cb)
bluetooth.advertise(True)
srv1=bluetooth.service(uuid=b'1234567890123456',isprimary=True)
chr1=srv1.characteristic(uuid=b'ab34567890123456',value=5)
char1_read_counter=0
defchar1_cb_handler(chr):
globalchar1_read_counter
char1_read_counter+=1
events=chr.events()
ifevents&Bluetooth.CHAR_WRITE_EVENT:
print("Writerequestwithvalue={}".format(chr.value()))
else:
ifchar1_read_counter<3:
print('Readrequestonchar1')
else:
return'ABCDEF'
char1_cb=chr1.callback(trigger=Bluetooth.CHAR_WRITE_EVENT|Bluetooth.CHAR_READ_EVEN
T,handler=char1_cb_handler)
srv2=bluetooth.service(uuid=1234,isprimary=True)
chr2=srv2.characteristic(uuid=4567,value=0x1234)
char2_read_counter=0xF0
defchar2_cb_handler(chr):
globalchar2_read_counter
char2_read_counter+=1
ifchar2_read_counter>0xF1:
returnchar2_read_counter
char2_cb=chr2.callback(trigger=Bluetooth.CHAR_READ_EVENT,handler=char2_cb_handler)
5.2.2.3Bluetooth
314
5.2.2.3Bluetooth
315
classLoRa
ThisclassprovidesaLoRaWAN1.0.2compliantdriverfortheLoRanetworkprocessorin
theLoPyandFiPy.BelowisanexampledemonstratingLoRaWANActivationby
Personalisationusage:
fromnetworkimportLoRa
importsocket
importubinascii
importstruct
#InitialiseLoRainLORAWANmode.
#Pleasepicktheregionthatmatcheswhereyouareusingthedevice:
#Asia=LoRa.AS923
#Australia=LoRa.AU915
#Europe=LoRa.EU868
#UnitedStates=LoRa.US915
lora=LoRa(mode=LoRa.LORAWAN,region=LoRa.EU868)
#createanABPauthenticationparams
dev_addr=struct.unpack(">l",binascii.unhexlify('00000005'))[0]
nwk_swkey=ubinascii.unhexlify('2B7E151628AED2A6ABF7158809CF4F3C')
app_swkey=ubinascii.unhexlify('2B7E151628AED2A6ABF7158809CF4F3C')
#joinanetworkusingABP(ActivationByPersonalisation)
lora.join(activation=LoRa.ABP,auth=(dev_addr,nwk_swkey,app_swkey))
#createaLoRasocket
s=socket.socket(socket.AF_LORA,socket.SOCK_RAW)
#settheLoRaWANdatarate
s.setsockopt(socket.SOL_LORA,socket.SO_DR,5)
#makethesocketnon-blocking
s.setblocking(False)
#sendsomedata
s.send(bytes([0x01,0x02,0x03]))
#getanydatareceived...
data=s.recv(64)
print(data)
Pleaseensurethatthereisanantennaconnectedtoyourdevicebefore
sending/receivingLoRamessagesasimproperuse(e.g.withoutanantenna),may
damagethedevice.
5.2.2.4LoRa
316
AdditionalExamples
ForvariousothercompleteLoRaexamples,checkhereforadditionalexamples.
Constructors
classnetwork.LoRa(id=0,...)
CreateandconfigureaLoRaobject.Seeinitforparamsofconfiguration.
lora=LoRa(mode=LoRa.LORAWAN,region=LoRa.EU868)
Methods
lora.init(mode,*,region=LoRa.EU868,frequency=868000000,tx_power=14,
bandwidth=LoRa.BW_125KHZ,sf=7,preamble=8,coding_rate=LoRa.CODING_4_5,
power_mode=LoRa.ALWAYS_ON,tx_iq=False,rx_iq=False,adr=False,public=True,
tx_retries=1,device_class=LoRa.CLASS_A)
ThismethodisusedtosettheLoRasubsystemconfigurationandtospecificrawLoRaor
LoRaWAN.
Theargumentsare:
modecanbeeitherLoRa.LORAorLoRa.LORAWAN.
regioncantakethefollowingvalues:LoRa.AS923,LoRa.AU915,LoRa.EU868or
LoRa.US915.Ifnotprovidedthiswilldefaultto LoRaEU868.Iftheyarenotspecified,this
willalsosetappropriatedefaultsfor frequencyand tx_power.
frequencyacceptsvaluesbetween863000000and870000000inthe868band,or
between902000000and928000000inthe915band.
tx_poweristhetransmitpowerindBm.Itacceptsbetween2and14forthe868band,
andbetween5and20inthe915band.
bandwidthisthechannelbandwidthinKHz.Inthe868bandtheacceptedvaluesare
LoRa.BW_125KHZandLoRa.BW_250KHZ.Inthe915bandtheacceptedvaluesare
LoRa.BW_125KHZandLoRa.BW_500KHZ.
sfsetsthedesiredspreadingfactor.Acceptsvaluesbetween7and12.
preambleconfiguresthenumberofpre-amblesymbols.Thedefaultvalueis8.
coding_ratecantakethefollowingvalues:LoRa.CODING_4_5,LoRa.CODING_4_6,
LoRa.CODING_4_7orLoRa.CODING_4_8.
power_modecanbeeitherLoRa.ALWAYS_ON,LoRa.TX_ONLYorLoRa.SLEEP.In
5.2.2.4LoRa
317
ALWAYS_ONmode,theradioisalwayslisteningforincoming-packetswhenevera
transmissionisnottakingplace.InTX_ONLYtheradiogoestosleepassoonasthe
transmissioncompletes.InSLEEPmodetheradioissenttosleeppermanentlyand
won’tacceptanycommandsuntilthepowermodeischanged.
tx_iqenablesTXIQinversion.
rx_iqenablesRXIQinversion.
adrenablesAdaptiveDataRate.
publicselectsbetweenthepublicandprivatesyncword.
tx_retriessetsthenumberofTXretriesinLoRa.LORAWANmode.
device_classsetstheLoRaWANdeviceclass.CanbeeitherLoRa.CLASS_Aor
LoRa.CLASS_C.
InLoRa.LORAWANmode,only adr, public, tx_retriesand device_classare
used.AlltheotherparamswillbeignoredastheyarehandledbytheLoRaWANstack
directly.Ontheotherhand,inLoRa.LORAmodefromthose4arguments,onlythe
publiconeisimportantinordertoprogramthesyncword.InLoRa.LORAmode adr,
tx_retriesand device_classareignoredsincetheyareonlyrelevanttothe
LoRaWANstack.
Forexample,youcando:
#initializeinrawLoRamode
lora.init(mode=LoRa.LORA,tx_power=14,sf=12)
or:
#initializeinLoRaWANmode
lora.init(mode=LoRa.LORAWAN)
lora.join(activation,auth,*,timeout=None,dr=None)
JoinaLoRaWANnetwork.Internallythestackwillautomaticallyretryevery15secondsuntil
aJoinAcceptmessageisreceived.
Theparametersare:
activation:canbeeitherLoRa.OTAAorLoRa.ABP.
auth:isatuplewiththeauthenticationdata.
timeout:isthemaximumtimeinmillisecondstowaitfortheJoinAcceptmessageto
bereceived.Ifnotimeout(orzero)isgiven,thecallreturnsimmediatelyandthestatus
ofthejoinrequestcanbecheckedwith lora.has_joined().
5.2.2.4LoRa
318
dr:isanoptionalvaluetospecifytheinitialdataratefortheJoinRequest.Possible
valuesare0to5forEU868,or0to4forUS915.
InthecaseofLoRa.OTAAtheauthenticationtupleis: (dev_eui,app_eui,app_key)where
dev_euiisoptional.IfitisnotprovidedtheLoRaMACwillbeused.Therefore,youcando
OTAAin2differentways:
lora.join(activation=LoRa.OTAA,auth=(app_eui,app_key),timeout=0)#thedeviceMAC
addressisusedasDEV_EUI
or
lora.join(activation=LoRa.OTAA,auth=(dev_eui,app_eui,app_key),timeout=0)#acusto
mDEV_EUIisspecified
Example:
fromnetworkimportLoRa
importsocket
importtime
importubinascii
#InitialiseLoRainLORAWANmode.
#Pleasepicktheregionthatmatcheswhereyouareusingthedevice:
#Asia=LoRa.AS923
#Australia=LoRa.AU915
#Europe=LoRa.EU868
#UnitedStates=LoRa.US915
lora=LoRa(mode=LoRa.LORAWAN,region=LoRa.EU868)
#createanOTAAauthenticationparameters
app_eui=ubinascii.unhexlify('ADA4DAE3AC12676B')
app_key=ubinascii.unhexlify('11B0282A189B75B0B4D2D8C7FA38548B')
#joinanetworkusingOTAA(OvertheAirActivation)
lora.join(activation=LoRa.OTAA,auth=(app_eui,app_key),timeout=0)
#waituntilthemodulehasjoinedthenetwork
whilenotlora.has_joined():
time.sleep(2.5)
print('Notyetjoined...')
InthecaseofLoRa.ABPtheauthenticationtupleis: (dev_addr,nwk_swkey,app_swkey).
Example:
5.2.2.4LoRa
319
fromnetworkimportLoRa
importsocket
importubinascii
importstruct
#InitialiseLoRainLORAWANmode.
#Pleasepicktheregionthatmatcheswhereyouareusingthedevice:
#Asia=LoRa.AS923
#Australia=LoRa.AU915
#Europe=LoRa.EU868
#UnitedStates=LoRa.US915
lora=LoRa(mode=LoRa.LORAWAN,region=LoRa.EU868)
#createanABPauthenticationparams
dev_addr=struct.unpack(">l",ubinascii.unhexlify('00000005'))[0]
nwk_swkey=ubinascii.unhexlify('2B7E151628AED2A6ABF7158809CF4F3C')
app_swkey=ubinascii.unhexlify('2B7E151628AED2A6ABF7158809CF4F3C')
#joinanetworkusingABP(ActivationByPersonalisation)
lora.join(activation=LoRa.ABP,auth=(dev_addr,nwk_swkey,app_swkey))
lora.bandwidth([bandwidth])
GetorsetthebandwidthinrawLoRamode(LoRa.LORA).CanbeeitherLoRa.BW_125KHZ
(0),LoRa.BW_250KHZ(1)orLoRa.BW_500KHZ(2):
#getrawLoRaBandwidth
lora.bandwidth()
#setrawLoRaBandwidth
lora.bandwidth(LoRa.BW_125KHZ)
lora.frequency([frequency])
GetorsetthefrequencyinrawLoRamode(LoRa.LORA).Theallowedrangeisbetween
863000000and870000000Hzforthe868MHzbandversionorbetween902000000and
928000000Hzforthe915MHzbandversion.
#getrawLoRaFrequency
lora.frequency()
#setrawLoRaFrequency
lora.frequency(868000000)
lora.coding_rate([coding_rate])
5.2.2.4LoRa
320
GetorsetthecodingrateinrawLoRamode(LoRa.LORA).Theallowedvaluesare:
LoRa.CODING_4_5(1),LoRa.CODING_4_6(2),LoRa.CODING_4_7(3)and
LoRa.CODING_4_8(4).
#getrawLoRaCodingRate
lora.coding_rate()
#setrawLoRaCodingRate
lora.coding_rate(LoRa.CODING_4_5)
lora.preamble([preamble])
GetorsetthenumberofpreamblesymbolsinrawLoRamode(LoRa.LORA):
#getrawLoRapreamblesymbols
lora.preamble()
#setrawLoRapreamblesymbols
lora.preamble(LoRa.CODING_4_5)
lora.sf([sf])
GetorsetthespreadingfactorvalueinrawLoRamode(LoRa.LORA).Theminimumvalue
is7andthemaximumis12:
#getrawLoRaspreadfactorvalue
lora.sf()
#setrawLoRaspreadfactorvalue
lora.sf(7)
lora.power_mode([power_mode])
GetorsetthepowermodeinrawLoRamode(LoRa.LORA).Theacceptedvaluesare:
LoRa.ALWAYS_ON,LoRa.TX_ONLYandLoRa.SLEEP:
lora.stats()
ReturnanamedtuplewithusefulinformationfromthelastreceivedLoRaorLoRaWAN
packet.Thenamedtuplehasthefollowingform:
(rx_timestamp,rssi,snr,sftx,sfrx,tx_trials,tx_power,tx_time_on_air,tx_counter,
tx_frequency)
Example:
5.2.2.4LoRa
321
lora.stats()
Where:
rx_timestampisaninternaltimestampofthelastreceivedpacketwithmicroseconds
precision.
rssiholdsthereceivedsignalstrengthindBm.
snrcontainsthesignaltonoiseratioiddB(asasingleprecisionfloat).
sfrxtellsthedatarate(inthecaseofLORAWANmode)orthespreadingfactor(inthe
caseofLORAmode)ofthelastpacketreceived.
sftxtellsthedatarate(inthecaseofLORAWANmode)orthespreadingfactor(inthe
caseofLORAmode)ofthelastpackettransmitted.
tx_trialsisthenumberoftxattemptsofthelasttransmittedpacket(onlyrelevantfor
LORAWANconfirmedpackets).
tx_poweristhepowerofthelasttransmission(indBm).
tx_time_on_airisthetimeonairofthelasttransmittedpacket(inms).
tx_counteristhenumberofpacketstransmitted.
tx_frequencyisthefrequencyusedforthelasttransmission.
lora.has_joined()
Returns TrueifaLoRaWANnetworkhasbeenjoined. Falseotherwise.:
lora.add_channel(index,*,frequency,dr_min,dr_max)
AddaLoRaWANchannelonthespecified index.Ifthere’salreadyachannelwiththat
indexitwillbereplacedwiththenewone.
Theargumentsare:
index:Indexofthechanneltoadd.Acceptsvaluesbetween0and15forEUand
between0and71forUS.
frequency:CentrefrequencyinHzofthechannel.
dr_min:Minimumdatarateofthechannel(0-7).
dr_max:Maximumdatarateofthechannel(0-7).
Examples:
lora.add_channel(index=0,frequency=868000000,dr_min=5,dr_max=6)
lora.remove_channel(index)
5.2.2.4LoRa
322
Removesthechannelfromthespecified index.Onthe868MHzbandthechannels0to2
cannotberemoved,theycanonlybereplacedbyotherchannelsusingthelora.add_channel
method.Awaytoremoveallchannelsexceptforoneistoaddthesamechannel,3timeson
indexes0,1and2.Anexamplecanbeseenbelow:
lora.remove_channel()
Onthe915MHzbandtherearenorestrictionsaroundthis.
lora.mac()
Returnsabyteobjectwiththe8-ByteMACaddressoftheLoRaradio.
lora.callback(trigger,handler=None,arg=None)
SpecifyacallbackhandlerfortheLoRaradio.The triggertypesare
LoRa.RX_PACKET_EVENT,LoRa.TX_PACKET_EVENTandLoRa.TX_FAILED_EVENT
TheLoRa.RX_PACKET_EVENTeventisraisedforeveryreceivedpacket.The
LoRa.TX_PACKET_EVENTeventisraisedassoonasthepackettransmissioncycleends,
whichincludestheendofthereceivewindows(evenifadownlinkisreceived,the
LoRa.TX_PACKET_EVENTwillcomelast).Inthecaseofnon-confirmedtransmissions,this
willoccurattheendofthereceivewindows,but,inthecaseofconfirmedtransmissions,this
eventwillonlyberaisedifthe ackisreceived.Ifthe ackisnotreceived
LoRa.TX_FAILED_EVENTwillberaisedafterthenumberof tx_retriesconfiguredhave
beenperformed.
Anexampleofhowthiscallbackfunctionscanbeseentheinmethodlora.events().
lora.ischannel_free(rssi_threshold)
ThismethodisusedtocheckforradioactivityonthecurrentLoRachannel,andifthe rssi
ofthemeasuredactivityislowerthanthe rssi_thresholdgiven,thereturnvaluewillbe
True,otherwise False.Example:
lora.ischannel_free(-100)
lora.set_battery_level(level)
SetthebatterylevelvaluethatwillbesentwhentheLoRaWANMACcommandthat
retrievesthebatterylevelisreceived.Thiscommandissentbythenetworkandhandled
automaticallybytheLoRaWANstack.ThevaluesshouldbeaccordingtotheLoRaWAN
specification:
5.2.2.4LoRa
323
0meansthattheend-deviceisconnectedtoanexternalpowersource.
1..254specifiesthebatterylevel,1beingatminimumand254beingatmaximum.
255meansthattheend-devicewasnotabletomeasurethebatterylevel.
lora.set_battery_level(127)#50%battery
lora.events()
Thismethodreturnsavaluewithbitssets(ifany)indicatingtheeventsthathavetriggered
thecallback.Pleasenotethatbycallingthisfunctiontheinternaleventsregistryiscleared
automatically,thereforecallingitimmediatelyforasecondtimewillmostlikelyreturnavalue
of0.
Example:
deflora_cb(lora):
events=lora.events()
ifevents&LoRa.RX_PACKET_EVENT:
print('Lorapacketreceived')
ifevents&LoRa.TX_PACKET_EVENT:
print('Lorapacketsent')
lora.callback(trigger=(LoRa.RX_PACKET_EVENT|LoRa.TX_PACKET_EVENT),handler=lora_cb)
lora.nvram_save()
SavetheLoRaWANstate(joinedstatus,networkkeys,packetcounters,etc)innon-volatile
memoryinordertobeabletorestorethestatewhencomingoutofdeepsleeporapower
cycle.
lora.nvram_save()
lora.nvram_restore()
RestoretheLoRaWANstate(joinedstatus,networkkeys,packetcounters,etc)fromnon-
volatilememory.Statemusthavebeenpreviouslystoredwithacallto nvram_savebefore
enteringdeepsleep.ThisisusefultobeabletosendaLoRaWANmessageimmediately
aftercomingoutofdeepsleepwithouthavingtojointhenetworkagain.Thiscanonlybe
usedifthecurrentregionmatchestheonesaved.
lora.nvram_restore()
lora.nvram_erase()
5.2.2.4LoRa
324
RemovetheLoRaWANstate(joinedstatus,networkkeys,packetcounters,etc)fromnon-
volatilememory.
lora.nvram_erase()
Constants
LoRa.LORALoRa.LORAWANLoRastackmode
LoRa.OTAALoRa.ABPLoRaWANjoinprocedure
LoRa.ALWAYS_ONLoRa.TX_ONLYLoRa.SLEEPRawLoRapowermode
LoRa.BW_125KHZLoRa.BW_250KHZLoRa.BW_500KHZRawLoRabandwidth
LoRa.CODING_4_5LoRa.CODING_4_6LoRa.CODING_4_7LoRa.CODING_4_8Raw
LoRacodingrate
LoRa.RX_PACKET_EVENTLoRa.TX_PACKET_EVENTLoRa.TX_FAILED_EVENT
Callbacktriggertypes(maybeORed)
LoRa.CLASS_ALoRa.CLASS_CLoRaWANdeviceclass
LoRa.AS923LoRa.AU915LoRa.EU868LoRa.US915LoRaWANregions
WorkingwithLoRaandLoRaWANSockets
LoRasocketsarecreatedinthefollowingway:
importsocket
s=socket.socket(socket.AF_LORA,socket.SOCK_RAW)
AndtheymustbecreatedafterinitialisingtheLoRanetworkcard.
LoRasocketssupportthefollowingstandardmethodsfromthesocketmodule:
socket.close()
Usage:
s.close()
socket.bind(port_number)
Usage:
5.2.2.4LoRa
325
s.bind(1)
Thebind()methodisonlyapplicablewhentheradioisconfiguredinLoRa.LORAWAN
mode.
socket.send(bytes)
Usage:
s.send(bytes([1,2,3]))
or:
s.send('Hello')
socket.recv(bufsize)
Usage:
s.recv(128)
socket.recvfrom(bufsize)
Thismethodisusefultoknowthedestinationportnumberofthemessagereceived.Returns
atupleoftheform: (data,port)
Usage:
s.recvfrom(128)
socket.setsockopt(level,optname,value)
Setthevalueofthegivensocketoption.Theneededsymbolicconstantsaredefinedinthe
socketmodule( SO_*etc.).InthecaseofLoRathevaluesarealwaysintegers.Examples:
5.2.2.4LoRa
326
#configuringthedatarate
s.setsockopt(socket.SOL_LORA,socket.SO_DR,5)
#selectingnon-confirmedtypeofmessages
s.setsockopt(socket.SOL_LORA,socket.SO_CONFIRMED,False)
#selectingconfirmedtypeofmessages
s.setsockopt(socket.SOL_LORA,socket.SO_CONFIRMED,True)
SocketoptionsareonlyapplicablewhentheLoRaradioisusedinLoRa.LORAWAN
mode.WhenusingtheradioinLoRa.LORAmode,usetheclassmethodstochangethe
spreadingfactor,bandwidthandcodingratetothedesiredvalues.
socket.settimeout(value)
Setsthesockettimeoutvalueinseconds.Acceptsfloatingpointvalues.
Usage:
s.settimeout(5.5)
socket.setblocking(flag)
Usage:
s.setblocking(True)
5.2.2.4LoRa
327
classSigfox
SigfoxisaLowPowerWideAreaNetworkprotocolthatenablesremotedevicestoconnect
usingultra-narrowband,UNBtechnology.Theprotocolisbi-directional,messagescanboth
besentuptoanddownfromtheSigfoxservers.
Whenoperatingin RCZ2and RCZ4themodulecanonlysendmessagesonthedefault
macro-channel(thisisduetoSigfoxnetworklimitations).Therefore,thedeviceneedsto
resetautomaticallytothedefaultmacro-channelafterevery2transmissions.However,
duetoFCCdutycyclelimitations,theremustaminimumofa20sdelayafterresettingto
thedefaultmacro-channel.OurAPItakescareofthis,(andinreallifeapplicationsyou
shouldnotbeintheneedtosendSigfoxmessagesthatoften),soitwillwaitforthe
necessaryamountoftimetomakesurethatthedutycyclerestrictionsarefulfilled.
Thismeansthatifyourunapieceoftestcodelike:
foriinrange(1,100):
#sendsomething
s.send('Hello'+str(i))
Therewillbea20seconddelayafterevery2packets.
ThisclassprovidesadriverfortheSigfoxnetworkprocessorintheSigfoxenabledPycom
devices.
QuickUsageExample
5.2.2.5Sigfox
328
fromnetworkimportSigfox
importsocket
#initSigfoxforRCZ1(Europe)
sigfox=Sigfox(mode=Sigfox.SIGFOX,rcz=Sigfox.RCZ1)
#createaSigfoxsocket
s=socket.socket(socket.AF_SIGFOX,socket.SOCK_RAW)
#makethesocketblocking
s.setblocking(True)
#configureitasuplinkonly
s.setsockopt(socket.SOL_SIGFOX,socket.SO_RX,False)
#sendsomebytes
s.send(bytes([1,2,3,4,5,6,7,8,9,10,11,12]))
Pleaseensurethatthereisanantennaconnectedtoyourdevicebefore
sending/receivingSigfoxmessagesasinproperuse(e.g.withoutanantenna),may
damagethedevice.
Constructors
classnetwork.Sigfox(id=0,...)
CreateandconfigureaSigfoxobject.Seeinitforparamsofconfiguration.Examples:
#configureradiofortheSigfoxnetwork,usingRCZ1(868MHz)
sigfox=Sigfox(mode=Sigfox.SIGFOX,rcz=Sigfox.RCZ1)
#configureradioforFSK,devicetodeviceacross912MHz
sigfox=Sigfox(mode=Sigfox.FSK,frequency=912000000)
Methods
sigfox.init(mode=Sigfox.SIGFOX,rcz=Sigfox.RCZ1,*,frequency=None)
SettheSigfoxradioconfiguration.
Theargumentsare:
modecanbeeitherSigfox.SIGFOXorSigfox.FSK.Sigfox.SIGFOXusestheSigfox
modulationandprotocolwhileSigfox.FSKallowstocreatepointtopointcommunication
5.2.2.5Sigfox
329
between2DevicesusingFSKmodulation.
rcztakesthefollowingvalues:Sigfox.RCZ1,Sigfox.RCZ2,Sigfox.RCZ3,
Sigfox.RCZ4.The rczargumentisonlyrequiredifthemodeisSigfox.SIGFOX.
frequencysetsthefrequencyvaluein FSKmode.Cantakevaluesbetween863and
928MHz.
TheSiPycomesin2differenthardwareflavours:a+14dBmTxpowerversionwhichcan
onlyworkwith RCZ1and RCZ3anda+22dBmversionwhichworksexclusivelyon
RCZ2and RCZ4.
sigfox.mac()
Returnsabyteobjectwiththe8-ByteMACaddressoftheSigfoxradio.
sigfox.id()
Returnsabyteobjectwiththe4-BytebytesobjectwiththeSigfoxID.
sigfox.rssi()
Returnsasignedintegerwithindicatingthesignalstrengthvalueofthelastreceivedpacket.
sigfox.pac()
Returnsabyteobjectwiththe8-BytebytesobjectwiththeSigfoxPAC.
Toreturnhuman-readablevaluesyoushouldimport ubinasciiandconvertbinary
valuestohexidecimalrepresentation.Forexample:
print(ubinascii.hexlify(sigfox.mac()))
sigfox.frequencies()
Returnsatupleoftheform: (uplink_frequency_hz,downlink_frequency_hz)
sigfox.public_key([public])
Setsorgetsthepublickeyflag.Whencalledpassinga TruevaluetheSigfoxpublickey
willbeusedtoencryptthepackets.Callingitwithoutargumentsreturnsthestateoftheflag.
5.2.2.5Sigfox
330
#enableencryptedpackets
sigfox.public_key(True)
#returnstateofpublic_key
sigfox.public_key()
Constants
sigfox.SIGFOXsigfox.FSKSigfoxradiomode.SIGFOXtospecifyusageoftheSigfoxPublic
Network. FSKtospecifydevicetodevicecommunication.
sigfox.RCZ1sigfox.RCZ2sigfox.RCZ3sigfox.RCZ4Sigfoxzones.
RCZ1tospecifyEurope,Oman&SouthAfrica.
RCZ2fortheUSA,Mexico&Brazil.RCZ3forJapan.
RCZ4forAustralia,NewZealand,Singapore,Taiwan,HongKong,Colombia&
Argentina.
WorkingwithSigfoxSockets
Sigfoxsocketsarecreatedinthefollowingway:
importsocket
s=socket.socket(socket.AF_SIGFOX,socket.SOCK_RAW)
AndtheymustbecreatedafterinitialisingtheSigfoxnetworkcard.
Sigfoxsocketssupportthefollowingstandardmethodsfromthe socketmodule:
socket.close()
Useittocloseanexistingsocket.
socket.send(bytes)
InSigfoxmodethemaximumdatasizeis12bytes.InFSKthemaximumis64.
#sendaSigfoxpayloadofbytes
s.send(bytes([1,2,3]))
#sendaSigfoxpayloadcontainingastring
s.send('Hello')
socket.recv(bufsize)
5.2.2.5Sigfox
331
ThismethodcanbeusedtoreceiveaSigfoxdownlinkorFSKmessage.
#sizeofbuffershouldbepassedforexpectedpayload,e.g.64bytes
s.recv(64)
socket.setsockopt(level,optname,value)
Setthevalueofthegivensocketoption.Theneededsymbolicconstantsaredefinedinthe
socketmodule( SO_*etc.).InthecaseofSigfoxthevaluesarealwaysaninteger.
Examples:
#waitforadownlinkaftersendingtheuplinkpacket
s.setsockopt(socket.SOL_SIGFOX,socket.SO_RX,True)
#makethesocketuplinkonly
s.setsockopt(socket.SOL_SIGFOX,socket.SO_RX,False)
#usethesockettosendaSigfoxOutOfBandmessage
s.setsockopt(socket.SOL_SIGFOX,socket.SO_OOB,True)
#disableOut-Of-Bandtousethesocketnormally
s.setsockopt(socket.SOL_SIGFOX,socket.SO_OOB,False)
#selectthebitvaluewhensendingbitonlypackets
s.setsockopt(socket.SOL_SIGFOX,socket.SO_BIT,False)
SendingaSigfoxpacketwithasinglebitisachievedbysendinganemptystring,i.e.:
importsocket
s=socket.socket(socket.AF_SIGFOX,socket.SOCK_RAW)
#senda1bit
s.setsockopt(socket.SOL_SIGFOX,socket.SO_BIT,True)
s.send('')
socket.settimeout(value)
#settimeoutforthesocket,e.g.5seconds
s.settimeout(5.0)
socket.setblocking(flag)
#specifiesifsocketshouldbeblockingbaseduponBooleanflag.
s.setblocking(True)
Ifthesocketissettoblocking,yourcodewillbewaituntilthesocketcompletes
sending/receiving.
SigfoxDownlink
5.2.2.5Sigfox
332
ASigfoxcapablePycomdevices(SiPy)canbothsendandreceivedatafromtheSigfox
network.Toreceivedata,amessagemustfirstbesentuptoSigfox,requestingadownlink
message.Thiscanbedonebypassinga Trueargumentintothe setsockopt()method.
s.setsockopt(socket.SOL_SIGFOX,socket.SO_RX,True)
Anexampleofthedownlinkprocedurecanbeseenbelow:
#initSigfoxforRCZ1(Europe)
sigfox=Sigfox(mode=Sigfox.SIGFOX,rcz=Sigfox.RCZ1)
#createaSigfoxsocket
s=socket.socket(socket.AF_SIGFOX,socket.SOCK_RAW)
#makethesocketblocking
s.setblocking(True)
#configureitasDOWNLINKspecifiedby'True'
s.setsockopt(socket.SOL_SIGFOX,socket.SO_RX,True)
#sendsomebytesandrequestDOWNLINK
s.send(bytes([1,2,3]))
#awaitDOWNLINKmessage
s.recv(32)
SigfoxFSK(DevicetoDevice)
TocommunicatebetweentwoSigfoxcapabledevices,itmaybeusedinFSKmode.Two
devicesarerequiredtobesettothesamefrequency,bothusingFSK.
Device1:
sigfox=Sigfox(mode=Sigfox.FSK,frequency=868000000)
s=socket.socket(socket.AF_SIGFOX,socket.SOCK_RAW)
s.setblocking(True)
whileTrue:
s.send('Device-1')
time.sleep(1)
print(s.recv(64))
Device2:
5.2.2.5Sigfox
333
sigfox=Sigfox(mode=Sigfox.FSK,frequency=868000000)
s=socket.socket(socket.AF_SIGFOX,socket.SOCK_RAW)
s.setblocking(True)
whileTrue:
s.send('Device-2')
time.sleep(1)
print(s.recv(64))
Remembertousethecorrectfrequencyforyourregion(868MHzforEurope,912MHz
forUSA,etc.)
5.2.2.5Sigfox
334
classLTE
TheLTEclassprovidesaccesstotheLTE-M/NB-IoTmodemontheGPyandFiPy.LTE-
M/NB-IoTarenewcategoriesofcellularprotocolsdevelopedbythe3GPPandoptimisedfor
longbatterylifepowerandlongerrange.Thesearenewprotocolscurrentlyintheprocessof
beingdeployedbymobilenetworksacrosstheworld.
TheGPyandFiPysupportbothnewLTE-Mprotocols:
Cat-M1:alsoknownasLTE-Mdefinesa1.4MHzradiochannelsizeandabout375
kbpsofthroughput.Itisoptimisedforcoverageandlongbatterylife,outperforming
2G/GPRS,whilebeingsimilartopreviousLTEstandards.
Cat-NB1alsoknownasNB-IoT,definesa200kHzradiochannelsizeandaround60
kbpsofuplinkspeed.It'soptimisedforultralowthroughputandspecificallydesignedfor
IoTdeviceswithaverylongbatterylife.NB-IoTsharessomefeatureswithLTEsuchas
operatinginlicensedspectrum,butit'saverydifferentprotocol.Itshouldbenotedthat
NB-IoThasmanyrestrictionsasdoesnotofferfullIPconnectivityanddoesnotsupport
mobility.Whenmovingbetweencells,youwillneedtoreconnect.
Pleasenote:TheGPyandFiPyonlysupportthetwoprotocolsaboveandarenot
compatiblewitholderLTEstandards.
TheSequansmodemusedonPycom'scellularenabledmodulescanonlyworkinone
ofthesemodesatatime.Inordertoswitchbetweenthetwoprotocolsyouneedtoflash
adifferentfirmwaretotheSequansmodem.Instructionsforthiscanbefoundhere.
ATCommands
TheATcommandsfortheSequansMonarchmodemontheGPy/FiPyareavailableina
PDFfile.
Constructors
classnetwork.LTE(id=0,...)
CreateandconfigureaLTEobject.Seeinitforparamsofconfiguration.
5.2.2.6LTE
335
fromnetworkimportLTE
lte=LTE()
Methods
lte.init(*,carrier=None)
ThismethodisusedtosetuptheLTEsubsystem.Aftera deinit()thismethodcantake
severalsecondstoreturnwaitingfortheLTEmodemtostart-up.Optionallyspecifyacarrier
name.Theavailableoptionsare: verizon,at&t,standard. standardisgenericforany
carrier,andit'salsotheoptionusedwhennoargumentsaregiven.
lte.deinit()
DisablesLTEmodemcompletely.Thisreducesthepowerconsumptiontotheminimum.Call
thisbeforeenteringdeepsleep.
lte.attach(*,band=None)
EnableradiofunctionalityandattachtotheLTECatM1networkauthorisedbytheinserted
SIMcard.Optionallyspecifythebandtoscanfornetworks.Ifnoband(or None)is
specified,all6bandswillbescanned.Thepossiblevaluesforthebandare: 3,4,12,13,
20and28.
lte.isattached()
Returns Trueifthecellularmodeisattachedtothenetwork. Falseotherwise.
lte.dettach()
DetachthemodemfromtheLTECatM1anddisabletheradiofunctionality.
lte.connect(*,cid=1)
StartadatasessionandobtainandIPaddress.OptionallyspecifyaCID(ConnectionID)for
thedatasession.Theargumentsare:
-`cid`isaConnectionID.Thisiscarrierspecific,forVerizonuse`cid=3`.Foroth
erslikeTelstraitshouldbe`cid=1`.
Forinstance,toattachandconnecttoVerizon:
5.2.2.6LTE
336
importtime
fromnetworkimportLTE
lte=LTE(carrier="verizon")
lte.attach(band=13)
whilenotlte.isattached():
time.sleep(0.5)
print('Attaching...')
lte.connect(cid=3)
whilenotlte.isconnected():
time.sleep(0.5)
print('Connecting...')
#Nowusesocketsasusual...
lte.isconnected()
Returns TrueifthereisanactiveLTEdatasessionandIPaddresshasbeenobtained.
Falseotherwise.
lte.disconnect()
Endthedatasessionwiththenetwork.
lte.send_at_cmd(cmd)
SendanATcommanddirectlytothemodem.Returnstherawresponsefromthemodemas
astringobject.IMPORTANT:Ifadatasessionisactive(i.e.themodemisconnected),
sendingtheATcommandsrequirestopauseandthenresumethedatasession.Thisisall
doneautomatically,butmakesthewholerequesttakearound2.5seconds.
Example:
lte.send_at_cmd('AT+CEREG?')#checkfornetworkregistrationmanually(samesaslt
e.isattached())
Optionallytheresponsecanbeparsedforprettyprinting:
defsend_at_cmd_pretty(cmd):
response=lte.send_at_cmd(cmd).split('\r\n')
forlineinresponse:
print(line)
send_at_cmd_pretty('AT!="showphy"')#getthePHYstatus
send_at_cmd_pretty('AT!="fsm"')#gettheSystemFSM
5.2.2.6LTE
337
lte.imei()
ReturnsastringobjectwiththeIMEInumberoftheLTEmodem.
lte.iccid()
ReturnsastringobjectwiththeICCIDnumberoftheSIMcard.
lte.reset()
Performahardwareresetonthecellularmodem.Thisfunctioncantakeupto5secondsto
returnasitwaitsforthemodemtoshutdownandreboot.
5.2.2.6LTE
338
classAES-AdvancedEncryption
Standard
AES(AdvancedEncryptionStandard)isasymmetricblockcipherstandardisedbyNIST.It
hasafixeddatablocksizeof16bytes.Itskeyscanbe128,192,or256bitslong.
AESisimplementedusingtheESP32hardwaremodule.
QuickUsageExample
fromcryptoimportAES
importcrypto
key=b'notsuchsecretkey'#128bit(16bytes)key
iv=crypto.getrandbits(128)#hardwaregeneratedrandomIV(neverreuseit)
cipher=AES(key,AES.MODE_CFB,iv)
msg=iv+cipher.encrypt(b'Attackatdawn')
#...afterproperlysenttheencryptedmessagesomewhere...
cipher=AES(key,AES.MODE_CFB,msg[:16])#onthedecryptionside
original=cipher.decrypt(msg[16:])
print(original)
Constructors
classucrypto.AES(key,mode,IV,*,counter,segment_size)
CreateanAESobjectthatwillletyouencryptanddecryptmessages.
Theargumentsare:
key(bytestring)isthesecretkeytouse.Itmustbe16(AES-128),24(AES-192),or
32(AES-256)byteslong.
modeisthechainingmodetouseforencryptionanddecryption.Defaultis
AES.MODE_ECB.
IV(bytestring)initialisationvector.Shouldbe16byteslong.Itisignoredinmodes
AES.MODE_ECBandAES.MODE_CRT.
counter(bytestring)usedonlyforAES.MODE_CTR.Shouldbe16byteslong.Should
notbereused.
5.2.3AES
339
segment_sizeisthenumberofbits plaintextand ciphertextaresegmentedin.Is
onlyusedinAES.MODE_CFB.SupportedvaluesareAES.SEGMENT_8and
AES.SEGMENT_128.
Methods
ucrypto.encrypt()
Encryptdatawiththekeyandtheparameterssetatinitialisation.
ucrypto.decrypt()
Decryptdatawiththekeyandtheparameterssetatinitialisation.
Constants
AES.MODE_ECB
ElectronicCodeBook.Simplestencryptionmode.Itdoesnothidedatapatternswell(see
thisarticleformoreinfo).
AES.MODE_CBC
Cipher-BlockChaining.AnInitialisationVector(IV)isrequired.
AES.MODE_CFB
Cipherfeedback. plaintextand ciphertextareprocessedinsegmentsof segment_size
bits.Worksastreamcipher.
AES.MODE_CTR
Countermode.Eachmessageblockisassociatedtoacounterwhichmustbeuniqueacross
allmessagesthatgetencryptedwiththesamekey.
AES.SEGMENT_8AES.SEGMENT_128
LengthofthesegmentforAES.MODE_CFB.
Toavoidsecurityissues,IVshouldalwaysbearandomnumberandshouldneverbe
reusedtoencrypttwodifferentmessages.ThesameappliestothecounterinCTR
mode.Youcanusecrypto.getrandbits()forthispurpose.
5.2.3AES
340
pycom–PycomDeviceFeatures
The pycommodulecontainsfunctionstocontrolspecificfeaturesofthePycomdevices,
suchastheheartbeatRGBLED.
QuickUsageExample
importpycom
pycom.heartbeat(False)#disabletheheartbeatLED
pycom.heartbeat(True)#enabletheheartbeatLED
pycom.heartbeat()#gettheheartbeatstate
pycom.rgbled(0xff00)#maketheLEDlightupingreencolor
Functions
pycom.heartbeat([enable])
Getorsetthestate(enabledordisabled)oftheheartbeatLED.Acceptsandreturnsboolean
values( Trueor False).
pycom.heartbeat_on_boot([enable])
AllowsyoupermanentlydisableorenabletheheartbeatLED.Oncethissettingisset,itwill
persistbetweenreboots.Note,thisonlycomesintoeffectonthenextboot,itdoesnotstop
thealreadyrunningheartbeat.
pycom.rgbled(color)
SetthecolouroftheRGBLED.Thecolourisspecifiedas24bitvaluerepresentingred,
greenandblue,wheretheredcolourisrepresentedbythe8mostsignificantbits.For
instance,passingthevalue 0x00FF00willlightuptheLEDinaverybrightgreen.
pycom.nvs_set(key,value)
SetthevalueofthespecifiedkeyintheNVRAMmemoryareaoftheexternalflash.Data
storedhereispreservedacrossresetsandpowercycles.Valuecanonlytake32-bitintegers
atthemoment.Example:
5.2.4pycom
341
importpycom
pycom.nvs_set('temp',25)
pycom.nvs_set('count',10)
pycom.nvs_get(key)
GetthevaluethespecifiedkeyfromtheNVRAMmemoryareaoftheexternalflash.
Example:
importpycom
pulses=pycom.nvs_get('count')
Ifanon-existingkeyisgiventhereturnedvaluewillbe None.
pycom.nvs_erase(key)
ErasethegivenkeyfromtheNVRAMmemoryarea.
pycom.nvs_erase_all()
ErasetheentireNVRAMmemoryarea.
pycom.wifi_on_boot([enable])
GetorsettheWiFionbootflag.Whenthisflagissetto True,theAPwiththedefaultSSID
(lopy-wlan-xxxforexample)willbeenabledaspartofthebootprocess.Iftheflagissetto
False,themodulewillbootwithWiFidisableduntilit'senabledbythescriptviathe WLAN
class.Thissettingisstoredinnon-volatilememorywhichpreservesitacrossresetsand
powercycles.Example:
importpycom
pycom.wifi_on_boot(True)#enableWiFionboot
pycom.wifi_on_boot()#getthewifionbootflag
pycom.wdt_on_boot([enable])
EnablestheWDTatboottimewiththetimeoutinmssetbythefunction
wdt_on_boot_timeout.Ifthisflagisset,theapplicationneedstoreconfiguretheWDTwitha
newtimeoutandfeeditregularlytoavoidareset.
5.2.4pycom
342
importpycom
pycom.wdt_on_boot(True)#enableWDTonboot
pycom.wdt_on_boot()#gettheWDTonbootflag
pycom.wdt_on_boot_timeout([timeout])
SetsorgetstheWDTonboottimeoutinmilliseconds.Theminimumvalueis5000ms.
importpycom
pycom.wdt_on_boot_timeout(10000)#setthetimeoutto5000ms
pycom.wdt_on_boot_timeout()#gettheWDTtimeoutvalue
pycom.pulses_get(pin,timeout)
Returnalistofpulsesat pin.Themethodsscansfortransitionsat pinandreturnsalist
oftuples,eachtellingthepinvalueandthedurationinmicrosecondsofthatvalue. pinisa
pinobject,whichmusthavesetto INPor OPEN_DRAINmode.Thescanstopsifnot
transitionsoccurswithin timeoutmilliseconds.
Example:
#gettherawdatafromaDHT11/DHT22/AM2302sensor
frommachineimportPin
frompycomimportpulses_get
fromtimeimportsleep_ms
pin=Pin("G7",mode=Pin.OPEN_DRAIN)
pin(0)
sleep_ms(20)
pin(1)
data=pulses_get(pin,100)
pycom.ota_start()
pycom.ota_write(buffer)
pycom.ota_finish()
Performafirmwareupdate.Thesemethodsareinternallyusedbyafirmwareupdatethough
FTP.Theupdatestartswithacallto ota_start(),followedbyaseriesofcallsto
ota_write(buffer),andisterminatedwith ota_finish().Afterreset,thenewimagegets
5.2.4pycom
343
active. buffershallholdtheimagedatatobewritten,inarbitrarysizes.Ablocksizeof
4096isrecommended.
Example:
#FirmwareupdatebyreadingtheimagefromtheSDcard
#
frompycomimportota_start,ota_write,ota_finish
fromosimportmount
frommachineimportSD
BLOCKSIZE=const(4096)
APPIMG="/sd/appimg.bin"
sd=SD()
mount(sd,'/sd')
withopen(APPIMG,"rb")asf:
buffer=bytearray(BLOCKSIZE)
mv=memoryview(buffer)
size=0
ota_start()
whileTrue:
chunk=f.readinto(buffer)
ifchunk>0:
ota_write(mv[:chunk])
size+=chunk
print("\r%7d"%size,end="")
else:
break
ota_finish()
Insteadofreadingthedatatobewrittenfromafile,itcanobviouslyalsobereceivedfroma
serverusinganysuitableprotocol,withouttheneedtostoreitinthedevicesfilesystem.
5.2.4pycom
344
Micropythonlibraries
ThefollowinglistcontainsthestandardPythonlibraries,MicroPython-specificlibrariesand
PycomspecificmodulesthatareavailableonthePycomdevices.
ThestandardPythonlibrarieshavebeen"micro-ified"tofitinwiththephilosophyof
MicroPython.Theyprovidethecorefunctionalityofthatmoduleandareintendedtobea
drop-inreplacementforthestandardPythonlibrary.
Somemodulesareavailablebyanu-name,andalsobytheirnon-u-name.Thenon-u-
namecanbeoverriddenbyafileofthatnameinyourpackagepath.Forexample,
importjsonwillfirstsearchforafile json.pyordirectory jsonandloadthat
packageifit'sfound.Ifnothingisfound,itwillfallbacktoloadingthebuilt-in ujson
module.
5.3MicroPythonModules
345
classmicropython–MicroPythonInternals
Controls
Functions
micropython.alloc_emergency_exception_buf(size)
AllocatesizebytesofRAMfortheemergencyexceptionbuffer(agoodsizeisaround100
bytes).ThebufferisusedtocreateexceptionsincaseswhennormalRAMallocationwould
fail(egwithinaninterrupthandler)andthereforegiveusefultracebackinformationinthese
situations.
Agoodwaytousethisfunctionistoplaceitatthestartofamainscript(e.g. boot.pyor
main.py)andthentheemergencyexceptionbufferwillbeactiveforallthecodefollowingit.
micropython.const(expr)
Usedtodeclarethattheexpressionisaconstantsothatthecompilecanoptimiseit.The
useofthisfunctionshouldbeasfollows:
frommicropythonimportconst
CONST_X=const(123)
CONST_Y=const(2*CONST_X+1)
Constantsdeclaredthiswayarestillaccessibleasglobalvariablesfromoutsidethemodule
theyaredeclaredin.Ontheotherhand,ifaconstantbeginswithanunderscorethenitis
hidden,itisnotavailableasaglobalvariable,anddoesnottakeupanymemoryduring
execution.
ThisconstfunctionisrecogniseddirectlybytheMicroPythonparserandisprovidedaspart
ofthe micropythonmodulemainlysothatscriptscanbewrittenwhichrununderboth
CPythonandMicroPython,byfollowingtheabovepattern.
micropython.opt_level([level])
If levelisgiventhenthisfunctionsetstheoptimisationlevelforsubsequentcompilationof
scripts,andreturns None.Otherwiseitreturnsthecurrentoptimisationlevel.
micropython.mem_info([verbose])
5.3.1micropython
346
Printinformationaboutcurrentlyusedmemory.Ifthe verboseargumentisgiventhenextra
informationisprinted.
Theinformationthatisprintedisimplementationdependent,butcurrentlyincludesthe
amountofstackandheapused.Inverbosemodeitprintsouttheentireheapindicating
whichblocksareusedandwhicharefree.
micropython.qstr_info([verbose])
Printinformationaboutcurrentlyinternedstrings.Ifthe verboseargumentisgiventhen
extrainformationisprinted.
Theinformationthatisprintedisimplementationdependent,butcurrentlyincludesthe
numberofinternedstringsandtheamountofRAMtheyuse.Inverbosemodeitprintsout
thenamesofallRAM-internedstrings.
micropython.stack_use()
Returnanintegerrepresentingthecurrentamountofstackthatisbeingused.Theabsolute
valueofthisisnotparticularlyuseful,ratheritshouldbeusedtocomputedifferencesin
stackusageatdifferentpoints.
micropython.heap_lock()
micropython.heap_unlock()
Lockorunlocktheheap.Whenlockednomemoryallocationcanoccuranda MemoryError
willberaisedifanyheapallocationisattempted.
Thesefunctionscanbenested,i.e. heap_lock()canbecalledmultipletimesinarowand
thelock-depthwillincrease,andthen heap_unlock()mustbecalledthesamenumberof
timestomaketheheapavailableagain.
micropython.kbd_intr(chr)
Setthecharacterthatwillraisea KeyboardInterruptexception.Bydefaultthisissetto3
duringscriptexecution,correspondingto Ctrl-C.Passing -1tothisfunctionwilldisable
captureof Ctrl-C,andpassing 3willrestoreit.
Thisfunctioncanbeusedtopreventthecapturingof Ctrl-Contheincomingstreamof
charactersthatisusuallyusedfortheREPL,incasethatstreamisusedforotherpurposes.
5.3.1micropython
347
uctypes–AccessBinaryDataina
StructuredFormat
Thismoduleimplements"foreigndatainterface"forMicroPython.Theideabehinditis
similartoCPython’s ctypesmodules,buttheactualAPIisdifferent,streamlinedand
optimisedforsmallsize.Thebasicideaofthemoduleistodefinedatastructurelayoutwith
aboutthesamepowerastheClanguageallows,andtheaccessitusingfamiliardot-syntax
toreferencesub-fields.
ModuleustructStandardPythonwaytoaccessbinarydatastructures(doesn’tscale
welltolargeandcomplexstructures).
DefiningStructureLayout
Structurelayoutisdefinedbya"descriptor"-aPythondictionarywhichencodesfieldnames
askeysandotherpropertiesrequiredtoaccessthemasassociatedvalues.Currently,
uctypesrequiresexplicitspecificationofoffsetsforeachfield.Offsetaregiveninbytesfrom
astructurestart.
Followingareencodingexamplesforvariousfieldtypes:
Scalartypes:
"field_name":uctypes.UINT32|0
Inotherwords,valueisscalartypeidentifierOR-edwithfieldoffset(inbytes)fromthestart
ofthestructure.
Recursivestructures:
"sub":(2,{
"b0":uctypes.UINT8|0,
"b1":uctypes.UINT8|1,
})
I.e.valueisa2-tuple,firstelementofwhichisoffset,andsecondisastructuredescriptor
dictionary(note:offsetsinrecursivedescriptorsarerelativetoastructureitdefines).
ArraysofPrimitiveTypes:
5.3.2uctypes
348
"arr":(uctypes.ARRAY|0,uctypes.UINT8|2),
I.e.valueisa2-tuple,firstelementofwhichisARRAYflagOR-edwithoffset,andsecondis
scalarelementtypeOR-ednumberofelementsinarray.
ArraysofAggregateTypes:
"arr2":(uctypes.ARRAY|0,2,{"b":uctypes.UINT8|0}),
I.e.valueisa3-tuple,firstelementofwhichisARRAYflagOR-edwithoffset,secondisa
numberofelementsinarray,andthirdisdescriptorofelementtype.
Pointertoaprimitivetype:
"ptr":(uctypes.PTR|0,uctypes.UINT8),
I.e.valueisa2-tuple,firstelementofwhichisPTRflagOR-edwithoffset,andsecondis
scalarelementtype.
Pointertoanaggregatetype:
"ptr2":(uctypes.PTR|0,{"b":uctypes.UINT8|0}),
I.e.valueisa2-tuple,firstelementofwhichisPTRflagOR-edwithoffset,secondis
descriptoroftypepointedto.
Bitfields:
"bitf0":uctypes.BFUINT16|0|0<<uctypes.BF_POS|8<<uctypes.BF_LEN,
I.e.valueistypeofscalarvaluecontaininggivenbitfield(typenamesaresimilartoscalar
types,butprefixeswith"BF"),OR-edwithoffsetforscalarvaluecontainingthebitfield,and
furtherOR-edwithvaluesforbitoffsetandbitlengthofthebitfieldwithinscalarvalue,
shiftedbyBF_POSandBF_LENpositions,respectively.Bitfieldpositioniscountedfromthe
leastsignificantbit,andisthenumberofright-mostbitofafield(inotherwords,it’sa
numberofbitsascalarneedstobeshiftedrighttoextrathebitfield).
Intheexampleabove,first UINT16valuewillbeextractedatoffset0(thisdetailmaybe
importantwhenaccessinghardwareregisters,whereparticularaccesssizeandalignment
arerequired),andthenbitfieldwhoserightmostbitisleast-significantbitofthis UINT16,and
5.3.2uctypes
349
lengthis8bits,willbeextracted-effectively,thiswillaccessleast-significantbyteof
UINT16.
Notethatbitfieldoperationsareindependentoftargetbyteendianness,inparticular,
exampleabovewillaccessleast-significantbyteof UINT16inbothlittle-andbig-endian
structures.Butitdependsontheleastsignificantbitbeingnumbered0.Sometargetsmay
usedifferentnumberingintheirnativeABI,but uctypesalwaysusesnormalisednumbering
describedabove.
ModuleContents
classuctypes.struct(addr,descriptor,layout_type=NATIVE)
Instantiatea"foreigndatastructure"objectbasedonstructureaddressinmemory,
descriptor(encodedasadictionary),andlayouttype(seebelow).
uctypes.LITTLE_ENDIAN
Layouttypeforalittle-endianpackedstructure.(Packedmeansthateveryfieldoccupies
exactlyasmanybytesasdefinedinthedescriptor,i.e.thealignmentis1).
uctypes.BIG_ENDIAN
Layouttypeforabig-endianpackedstructure.
uctypes.NATIVE
Layouttypeforanativestructure-withdataendiannessandalignmentconformingtothe
ABIofthesystemonwhichMicroPythonruns.
uctypes.sizeof(struct)
Returnsizeofdatastructureinbytes.Argumentcanbeeitherstructureclassorspecific
instantiatedstructureobject(oritsaggregatefield).
uctypes.addressof(obj)
Returnaddressofanobject.Argumentshouldbebytes, bytearrayorotherobject
supportingbufferprotocol(andaddressofthisbufferiswhatactuallyreturned).
uctypes.bytes_at(addr,size)
Capturememoryatthegivenaddressandsizeasbytesobject.Asbytesobjectis
immutable,memoryisactuallyduplicatedandcopiedintobytesobject,soifmemory
contentschangelater,createdobjectretainsoriginalvalue.
5.3.2uctypes
350
uctypes.bytearray_at(addr,size)
Capturememoryatthegivenaddressandsizeas bytearrayobject.Unlike bytes_at()
functionabove,memoryiscapturedbyreference,soitcanbebothwrittentoo,andyouwill
accesscurrentvalueatthegivenmemoryaddress.
StructureDescriptorsandInstantiatingStructureObjects
Givenastructuredescriptordictionaryanditslayouttype,youcaninstantiateaspecific
structureinstanceatagivenmemoryaddressusinguctypes.struct()constructor.Memory
addressusuallycomesfromfollowingsources:
Predefinedaddress,whenaccessinghardwareregistersonabaremetalsystem.
LookuptheseaddressesindatasheetforaparticularMCU/SoC.
AsareturnvaluefromacalltosomeFFI(ForeignFunctionInterface)function.
Fromuctypes.addressof(),whenyouwanttopassargumentstoanFFIfunction,or
alternatively,toaccesssomedataforI/O(forexample,datareadfromafileornetwork
socket).
Structureobjects
Structureobjectsallowaccessingindividualfieldsusingstandarddotnotation:
my_struct.substruct1.field1.Ifafieldisofscalartype,gettingitwillproduceaprimitive
value(Pythonintegerorfloat)correspondingtothevaluecontainedinafield.Ascalarfield
canalsobeassignedto.
Ifafieldisanarray,itsindividualelementscanbeaccessedwiththestandardsubscript
operator []-bothreadandassignedto.
Ifafieldisapointer,itcanbedereferencedusing [0]syntax(correspondingtoC *
operator,though [0]worksinCtoo).Subscriptingapointerwithotherintegervaluesbut0
aresupportedtoo,withthesamesemanticsasinC.
Summingup,accessingstructurefieldsgenerallyfollowsCsyntax,exceptforpointer
dereference,whenyouneedtouse [0]operatorinsteadof *.
Limitations
Accessingnon-scalarfieldsleadstoallocationofintermediateobjectstorepresentthem.
Thismeansthatspecialcareshouldbetakentolayoutastructurewhichneedstobe
accessedwhenmemoryallocationisdisabled(e.g.fromaninterrupt).The
recommendationsare:
5.3.2uctypes
351
Avoidnestedstructures.Forexample,insteadof
mcu_registers.peripheral_a.register1,defineseparatelayoutdescriptorsforeach
peripheral,tobeaccessedas peripheral_a.register1.
Avoidothernon-scalardata,likearray.Forexample,insteadof
peripheral_a.register[0]use peripheral_a.register0.
Notethattheserecommendationswillleadtodecreasedreadabilityandconcisenessof
layouts,sotheyshouldbeusedonlyiftheneedtoaccessstructurefieldswithoutallocation
isanticipated(it’sevenpossibletodefine2parallellayouts-onefornormalusage,anda
restrictedonetousewhenmemoryallocationisprohibited).
5.3.2uctypes
352
sys–SystemSpecificFunctions
Functions
sys.exit(retval=0)
Terminatecurrentprogramwithagivenexitcode.Underlyingly,thisfunctionraiseas
SystemExitexception.Ifanargumentisgiven,itsvaluegivenasanargumentto
SystemExit.
sys.print_exception(exc,file=sys.stdout)
Printexceptionwithatracebacktoafile-likeobjectfile(or sys.stdoutbydefault).
DifferencetoCPython
Thisissimplifiedversionofafunctionwhichappearsinthetracebackmodulein
CPython.Unlike traceback.print_exception(),thisfunctiontakesjustexceptionvalue
insteadofexceptiontype,exceptionvalue,andtracebackobject;fileargumentshould
bepositional;furtherargumentsarenotsupported.CPython-compatibletraceback
modulecanbefoundin micropython-lib.
Constants
sys.argv
Amutablelistofargumentsthecurrentprogramwasstartedwith.
sys.byteorder
Thebyteorderofthesystem("little"or"big").
sys.implementation
ObjectwithinformationaboutthecurrentPythonimplementation.ForMicroPython,ithas
followingattributes:
name-string"micropython"
version-tuple(major,minor,micro),e.g.(1,7,0)Thisobjectistherecommendedway
todistinguishMicroPythonfromotherPythonimplementations(notethatitstillmaynot
existintheveryminimalports).
DifferencetoCPython
5.3.3sys
353
CPythonmandatesmoreattributesforthisobject,buttheactualusefulbareminimumis
implementedinMicroPython.
sys.maxsize
Maximumvaluewhichanativeintegertypecanholdonthecurrentplatform,ormaximum
valuerepresentablebyMicroPythonintegertype,ifit’ssmallerthanplatformmaxvalue(that
isthecaseforMicroPythonportswithoutlongintsupport).
Thisattributeisusefulfordetecting"bitness"ofaplatform(32-bitvs64-bit,etc.).It’s
recommendedtonotcomparethisattributetosomevaluedirectly,butinsteadcountnumber
ofbitsinit:
bits=0
v=sys.maxsize
whilev:
bits+=1
v>>=1
ifbits>32:
#64-bit(ormore)platform
else:
#32-bit(orless)platform
#Notethaton32-bitplatform,valueofbitsmaybelessthan32
#(e.g.31)duetopeculiaritiesdescribedabove,souse">16",
#">32",">64"styleofcomparisons.
sys.modules
Dictionaryofloadedmodules.Onsomeports,itmaynotincludebuiltinmodules.
sys.path
Amutablelistofdirectoriestosearchforimportedmodules.
sys.platform
TheplatformthatMicroPythonisrunningon.ForOS/RTOSports,thisisusuallyanidentifier
oftheOS,e.g. linux.Forbaremetalports,itisanidentifierofaboard,e.g. pyboardfor
theoriginalMicroPythonreferenceboard.Itthuscanbeusedtodistinguishoneboardfrom
another.IfyouneedtocheckwhetheryourprogramrunsonMicroPython(vsotherPython
implementation),use sys.implementationinstead.
sys.stderr
Standarderrorstream.
sys.stdin
Standardinputstream.
5.3.3sys
354
sys.stdout
Standardoutputstream.
sys.version
Pythonlanguageversionthatthisimplementationconformsto,asastring.
sys.version_info
Pythonlanguageversionthatthisimplementationconformsto,asatupleofints.
5.3.3sys
355
uos–Basic"OperatingSystem"Services
The uosmodulecontainsfunctionsforfilesystemaccessand urandomfunction.
PortSpecifics
Thefilesystemhas /astherootdirectoryandtheavailablephysicaldrivesareaccessible
fromhere.Theyarecurrently:
/flash–theinternalflashfilesystem
/sd–theSDcard(ifitexists)
Functions
uos.uname()
Returninformationaboutthesystem,firmwarereleaseversion,andMicroPythoninterpreter
version.
uos.chdir(path)
Changecurrentdirectory.
uos.getcwd()
Getthecurrentdirectory.
uos.listdir([dir])
Withnoargument,listthecurrentdirectory.Otherwiselistthegivendirectory.
uos.mkdir(path)
Createanewdirectory.
uos.remove(path)
Removeafile.
uos.rmdir(path)
Removeadirectory.
5.3.4uos
356
uos.rename(old_path,new_path)
Renameafile.
uos.stat(path)
Getthestatusofafileordirectory.
Thereturnvalueisatuplewiththefollowing10values,inorder:
st_mode:protectionbits.
st_ino: inodenumber.(notimplemented,returns0)
st_dev:device.(notimplemented,returns0)
st_nlink:numberofhardlinks.(notimplemented,returns0)
st_uid:useridofowner.(notimplemented,returns0)
st_gid:groupidofowner.(notimplemented,returns0)
st_size:sizeoffileinbytes.
st_atime:timeofmostrecentaccess.
st_mtime:timeofmostrecentcontentmodification.
st_ctime:timeofmostrecentmetadatachange.
uos.getfree(path)
Returnsthefreespace(inKiB)inthedrivespecifiedbypath.
uos.sync()
Syncallfilesystems.
uos.urandom(n)
Returnabytesobjectwithnrandombytes.
uos.unlink(path)
Aliasforthe remove()method.
uos.mount(block_device,mount_point,*,readonly=False)
Mountsablockdevice(likeanSDobject)inthespecifiedmountpoint.Example:
os.mount(sd,'/sd')
uos.unmount(path)
Unmountsapreviouslymountedblockdevicefromthegivenpath.
5.3.4uos
357
uos.mkfs(block_deviceorpath)
Formatsthespecifiedpath,mustbeeither /flashor /sd.Ablockdevicecanalsobe
passedlikeanSDobjectbeforebeingmounted.
uos.dupterm(stream_object)
Duplicatetheterminal(theREPL)onthepassedstream-likeobject.Thegivenobjectmust
atleastimplementthe read()and write()methods.
Constants
uos.sep
Separationcharacterusedinpaths
5.3.4uos
358
array–ArraysofNumericData
SeePythonarrayformoreinformation.
Supportedformatcodes: b,B,h,H,i,I,l,L,q,Q,f,d(thelatter2dependingonthe
floating-pointsupport).
Classes
classarray.array(typecode[,iterable])
Createarraywithelementsofgiventype.Initialcontentsofthearrayaregivenbyan
iterable.Ifitisnotprovided,anemptyarrayiscreated.
array.append(val)
Appendnewelementtotheendofarray,growingit.
array.extend(iterable)
Appendnewelementsascontainedinaniterabletotheendofarray,growingit.
5.3.5array
359
cmath–MathematicalFunctionsfor
ComplexNumbers
The cmathmoduleprovidessomebasicmathematicalfunctionsforworkingwithcomplex
numbers.Floatingpointsupportrequiredforthismodule.
Functions
cmath.cos(z)
Returnthecosineof z.
cmath.exp(z)
Returntheexponentialof z.
cmath.log(z)
Returnthenaturallogarithmof z.Thebranchcutisalongthenegativerealaxis.
cmath.log10(z)
Returnthebase-10logarithmof z.Thebranchcutisalongthenegativerealaxis.
cmath.phase(z)
Returnsthephaseofthenumber z,intherange(-pi,+pi).
cmath.polar(z)
Returns,asatuple,thepolarformof z.
cmath.rect(r,phi)
Returnsthecomplexnumberwithmodulus randphase phi.
cmath.sin(z)
Returnthesineof z.
cmath.sqrt(z)
Returnthesquare-rootof z.
5.3.6cmath
360
math–MathematicalFunctions
Themathmoduleprovidessomebasicmathematicalfunctionsforworkingwithfloating-point
numbers.Floatingpointsupportrequiredforthismodule.
Functions
math.acos(x)
Returntheinversecosineof x.
math.acosh(x)
Returntheinversehyperboliccosineof x.
math.asin(x)
Returntheinversesineof x.
math.asinh(x)
Returntheinversehyperbolicsineof x.
math.atan(x)
Returntheinversetangentof x.
math.atan2(y,x)
Returntheprincipalvalueoftheinversetangentof y/x.
math.atanh(x)
Returntheinversehyperbolictangentof x.
math.ceil(x)
Returnaninteger,beingxroundedtowardspositiveinfinity.
math.copysign(x,y)
Returnxwiththesignof y.
math.cos(x)
5.3.7math
362
Returnthecosineof x.
math.cosh(x)
Returnthehyperboliccosineof x.
math.degrees(x)
Returnradians xconvertedtodegrees.
math.erf(x)
Returntheerrorfunctionof x.
math.erfc(x)
Returnthecomplementaryerrorfunctionof x.
math.exp(x)
Returntheexponentialof x.
math.expm1(x)
Return exp(x)-1.
math.fabs(x)
Returntheabsolutevalueof x.
math.floor(x)
Returnaninteger,being xroundedtowardsnegativeinfinity.
math.fmod(x,y)
Returntheremainderof x/y.
math.frexp(x)
Decomposesafloating-pointnumberintoitsmantissaandexponent.Thereturnedvalueis
thetuple (m,e)suchthat x==m*2**eexactly.If x==0thenthefunctionreturns
(0.0,0),otherwisetherelation 0.5<=abs(m)<1holds.
math.gamma(x)
Returnthegammafunctionof x.
5.3.7math
363
math.isfinite(x)
Return Trueif xisfinite.
math.isinf(x)
Return Trueif xisinfinite.
math.isnan(x)
Return Trueif xisnot-a-number
math.ldexp(x,exp)
Return x*(2**exp).
math.lgamma(x)
Returnthenaturallogarithmofthegammafunctionof x.
math.log(x)
Returnthenaturallogarithmof x.
math.log10(x)
Returnthebase-10logarithmof x.
math.log2(x)
Returnthebase-2logarithmof x.
math.modf(x)
Returnatupleoftwofloats,beingthefractionalandintegralpartsof x.Bothreturnvalues
havethesamesignas x.
math.pow(x,y)
Returns xtothepowerof y.
math.radians(x)
Returndegrees xconvertedtoradians.
math.sin(x)
Returnthesineof x.
5.3.7math
364
math.sinh(x)
Returnthehyperbolicsineof x.
math.sqrt(x)
Returnthesquarerootof x.
math.tan(x)
Returnthetangentof x.
math.tanh(x)
Returnthehyperbolictangentof x.
math.trunc(x)
Returnaninteger,being xroundedtowards 0.
Constants
math.e
Baseofthenaturallogarithm
math.pi
Theratioofacircle’scircumferencetoitsdiameter
5.3.7math
365
gc–GarbageCollector
Functions
gc.enable()
Enableautomaticgarbagecollection.
gc.disable()
Disableautomaticgarbagecollection.Heapmemorycanstillbeallocated,andgarbage
collectioncanstillbeinitiatedmanuallyusinggc.collect().
gc.collect()
Runagarbagecollection.
gc.mem_alloc()
ReturnthenumberofbytesofheapRAMthatareallocated.
gc.mem_free()
ReturnthenumberofbytesofavailableheapRAM.
5.3.8gc
366
ubinascii–Binary/ASCIIConversions
Thismoduleimplementsconversionsbetweenbinarydataandvariousencodingsofitin
ASCIIform(inbothdirections).
Functions
ubinascii.hexlify(data[,sep])
Convertbinarydatatohexadecimalrepresentation.Returnsbytesstring.
DifferencetoCPython
Ifadditionalargument, sepissupplied,itisusedasaseparatorbetweenhexadecimal
values.
ubinascii.unhexlify(data)
Converthexadecimaldatatobinaryrepresentation.Returnsbytesstring.(i.e.inverseof
hexlify)
ubinascii.a2b_base64(data)
ConvertBase64-encodeddatatobinaryrepresentation.Returnsbytesstring.
ubinascii.b2a_base64(data)
EncodebinarydatainBase64format.Returnsstring.
5.3.9ubinascii
367
ujson–JSONEncodingandDecoding
ThismodulesallowstoconvertbetweenPythonobjectsandtheJSONdataformat.
Functions
ujson.dumps(obj)
Return objrepresentedasaJSONstring.
ujson.loads(str)
ParsetheJSON strandreturnanobject.Raises ValueErrorifthestringisnotcorrectly
formed.
ujson.load(fp)
Parsecontentsof fp(a .read()-supportingfile-likeobjectcontainingaJSONdocument).
Raises ValueErrorifthecontentisnotcorrectlyformed.
5.3.10ujson
368
ure–regularexpressions
Thismoduleimplementsregularexpressionoperations.Regularexpressionsyntax
supportedisasubsetofCPythonremodule(andactuallyisasubsetofPOSIXextended
regularexpressions).
Supportedoperatorsare:
.Matchanycharacter. []Matchsetofcharacters.Individualcharactersandrangesare
supported.
^
$
?
*
+
??
*?
+?
Countedrepetitions ({m,n}),moreadvancedassertions,namedgroups,etc.arenot
supported.
Functions
ure.compile(regex)
Compileregularexpression,return regexobject.
ure.match(regex,string)
Matchregexagainst string.Matchalwayshappensfromstartingpositioninastring.
ure.search(regex,string)
Searchregexinastring.Unlikematch,thiswillsearchstringforfirstpositionwhichmatches
regex(whichstillmaybe0ifregexisanchored).
ure.DEBUG
Flagvalue,displaydebuginformationaboutcompiledexpression.
Regexobjects
5.3.11ure
369
Compiledregularexpression.Instancesofthisclassarecreatedusing ure.compile().
regex.match(string)
regex.search(string)
regex.split(string,max_split=-1)
Matchobjects
Matchobjectsasreturnedby match()and search()methods.
match.group([index])
Onlynumericgroupsaresupported.
5.3.11ure
370
usocket–SocketModule
ThismoduleprovidesaccesstotheBSDsocketinterface.
SeecorrespondingCPythonmoduleforcomparison.
SocketAddressFormat(s)
Functionsbelowwhichexpectanetworkaddress,acceptitintheformatof (ipv4_address,
port),where ipv4_addressisastringwithdot-notationnumericIPv4address,e.g.
8.8.8.8,andportisintegerportnumberintherange1-65535.Notethedomainnamesare
notacceptedas ipv4_address,theyshouldberesolvedfirstusing socket.getaddrinfo().
Functions
socket.socket(socket.AF_INET,socket.SOCK_STREAM,socket.IPPROTO_TCP)
Createanewsocketusingthegivenaddressfamily,sockettypeandprotocolnumber.
socket.getaddrinfo(host,port)
Translatethehost/portargumentintoasequenceof5-tuplesthatcontainallthenecessary
argumentsforcreatingasocketconnectedtothatservice.Thelistof5-tupleshasfollowing
structure:
(family,type,proto,canonname,sockaddr)Thefollowingexampleshowshowtoconnect
toagivenurl:
s=socket.socket()
s.connect(socket.getaddrinfo('www.micropython.org',80)[0][-1])
Exceptions
socket.errorsocket.timeout
Constants
socket.AF_INETsocket.AF_LORA
Familytypes
5.3.12usocket
371
socket.SOCK_STREAMsocket.SOCK_DGRAMsocket.SOCK_RAW
Sockettypes
socket.IPPROTO_UDPsocket.IPPROTO_TCP
Socketprotocols
socket.SOL_SOCKETsocket.SOL_LORAsocket.SOL_SIGFOX
Socketoptionslayers
socket.SO_REUSEADDR
IPsocketoptions
socket.SO_CONFIRMEDsocket.SO_DR
LoRasocketoptions
socket.SO_RXsocket.SO_TX_REPEATsocket.SO_OOBsocket.SO_BIT
Sigfoxsocketoptions
classSocket
Methods
socket.close()
Markthesocketclosed.Oncethathappens,allfutureoperationsonthesocketobjectwill
fail.Theremoteendwillreceivenomoredata(afterqueueddataisflushed).
Socketsareautomaticallyclosedwhentheyaregarbage-collected,butitisrecommendedto
close()themexplicitly,ortouseawithstatementaroundthem.
socket.bind(address)
Bindthe socketto address.Thesocketmustnotalreadybebound.The address
parametermustbeatuplecontainingtheIPaddressandtheport.
InthecaseofLoRasockets,theaddressparameterissimplyanintegerwiththeport
number,forinstance: s.bind(1)
5.3.12usocket
372
socket.listen([backlog])
Enableaservertoacceptconnections.Ifbacklogisspecified,itmustbeatleast0(ifit’s
lower,itwillbesetto0);andspecifiesthenumberofunacceptedconnectionsthatthe
systemwillallowbeforerefusingnewconnections.Ifnotspecified,adefaultreasonable
valueischosen.
socket.accept()
Acceptaconnection.Thesocketmustbeboundtoanaddressandlisteningforconnections.
Thereturnvalueisapair (conn,address)where connisanewsocketobjectusableto
sendandreceivedataontheconnection,and addressistheaddressboundtothesocket
ontheotherendoftheconnection.
socket.connect(address)
Connecttoaremotesocketat address.
socket.send(bytes)
Senddatatothesocket.Thesocketmustbeconnectedtoaremotesocket.
socket.sendall(bytes)
Aliasof socket.send(bytes).
socket.recv(bufsize)
Receivedatafromthesocket.Thereturnvalueisabytesobjectrepresentingthedata
received.Themaximumamountofdatatobereceivedatonceisspecifiedby bufsize.
socket.sendto(bytes,address)
Senddatatothesocket.Thesocketshouldnotbeconnectedtoaremotesocket,sincethe
destinationsocketisspecifiedbyaddress.
socket.recvfrom(bufsize)
Receivedatafromthesocket.Thereturnvalueisapair (bytes,address)where bytesis
abytesobjectrepresentingthedatareceivedand addressistheaddressofthesocket
sendingthedata.
socket.setsockopt(level,optname,value)
5.3.12usocket
373
Setthevalueofthegivensocketoption.Theneededsymbolicconstantsaredefinedinthe
socketmodule( SO_*etc.).Thevaluecanbeanintegerorabytes-likeobjectrepresenting
abuffer.
socket.settimeout(value)
Setatimeoutonblockingsocketoperations.Thevalueargumentcanbeanonnegative
floatingpointnumberexpressingseconds,or None.Ifanon-zerovalueisgiven,
subsequentsocketoperationswillraiseatimeoutexceptionifthetimeoutperiodvaluehas
elapsedbeforetheoperationhascompleted.Ifzeroisgiven,thesocketisputinnon-
blockingmode.IfNoneisgiven,thesocketisputinblockingmode.
socket.setblocking(flag)
Setblockingornon-blockingmodeofthesocket:ifflagisfalse,thesocketissettonon-
blocking,elsetoblockingmode.
Thismethodisashorthandforcertain settimeout()calls:
sock.setblocking(True)isequivalenttosock.settimeout(None)
sock.setblocking(False)isequivalenttosock.settimeout(0.0)
socket.makefile(mode='rb')
Returnafileobjectassociatedwiththesocket.Theexactreturnedtypedependsonthe
argumentsgiventomakefile().Thesupportislimitedtobinarymodesonly( rband wb).
CPython’sarguments: encoding, errors,and newlinearenotsupported.
Thesocketmustbeinblockingmode;itcanhaveatimeout,butthefileobject’sinternal
buffermayendupinainconsistentstateifatimeoutoccurs.
DifferencetoCPython
Closingthefileobjectreturnedby makefile()WILLclosetheoriginalsocketaswell.
socket.read(size)
Readuptosizebytesfromthesocket.Returnabytesobject.If sizeisnotgiven,it
behavesjustlikesocket.readall(),seebelow.
socket.readall()
ReadalldataavailablefromthesocketuntilEOF.Thisfunctionwillnotreturnuntilthesocket
isclosed.
5.3.12usocket
374
socket.readinto(buf[,nbytes])
Readbytesintothe buf.If nbytesisspecifiedthenreadatmostthatmanybytes.
Otherwise,readatmost len(buf)bytes.
Returnvalue:numberofbytesreadandstoredinto buf.
socket.readline()
Readaline,endinginanewlinecharacter.
Returnvalue:thelineread.
socket.write(buf)
Writethebufferofbytestothesocket.
Returnvalue:numberofbyteswritten.
5.3.12usocket
375
select–WaitforEventsonaSetof
Streams
Thismoduleprovidesfunctionstowaitforeventsonstreams(selectstreamswhichare
readyforoperations).
Pyboardspecifics
Pollingisanefficientwayofwaitingforread/writeactivityonmultipleobjects.Current
objectsthatsupportpollingare:pyb.UART,pyb.USB_VCP.
Functions
select.poll()
Createaninstanceofthe Pollclass.
select.select(rlist,wlist,xlist[,timeout])
Waitforactivityonasetofobjects.
Thisfunctionisprovidedforcompatibilityandisnotefficient.Usageof Pollis
recommendedinstead.
classPoll
Methods
poll.register(obj[,eventmask])
Register objforpolling. eventmaskislogicalORof:
select.POLLIN-dataavailableforreading
select.POLLOUT-moredatacanbewritten
select.POLLERR-erroroccurred
select.POLLHUP-endofstream/connectionterminationdetected eventmaskdefaultsto
select.POLLIN|select.POLLOUT.
poll.unregister(obj)
Unregister objfrompolling.
5.3.13select
376
poll.modify(obj,eventmask)
Modifythe eventmaskfor obj.
poll.poll([timeout])
Waitforatleastoneoftheregisteredobjectstobecomeready.Returnslistof( obj, event,
...)tuples, eventelementspecifieswhicheventshappenedwithastreamandisa
combinationof select.POLL*constantsdescribedabove.Theremaybeotherelementsin
tuple,dependingonaplatformandversion,sodon’tassumethatitssizeis2.Incaseof
timeout,anemptylistisreturned.
Timeoutisinmilliseconds.
5.3.13select
377
utime–TimeFunctions
The utimemoduleprovidesfunctionsforgettingthecurrenttimeanddate,measuringtime
intervals,andfordelays.
TimeEpoch:Pycom’sESP32portusesstandardforPOSIXsystemsepochof 1970-01-01
00:00:00UTC.
Maintainingactualcalendardate/time
ThisrequiresaRealTimeClock(RTC).OnsystemswithunderlyingOS(includingsome
RTOS),anRTCmaybeimplicit.Settingandmaintainingactualcalendartimeis
responsibilityofOS/RTOSandisdoneoutsideofMicroPython,itjustusesOSAPItoquery
date/time.Onbaremetalportshoweversystemtimedependson machine.RTC()object.The
currentcalendartimemaybesetusing machine.RTC().datetime(tuple)function,and
maintainedbyfollowingmeans:
Byabackupbattery(whichmaybeanadditional,optionalcomponentforaparticular
board).
Usingnetworkedtimeprotocol(requiressetupbyaport/user).
Setmanuallybyauseroneachpower-up(manyboardsthenmaintainRTCtimeacross
hardresets,thoughsomemayrequiresettingitagaininsuchcase).
Ifactualcalendartimeisnotmaintainedwithasystem/MicroPythonRTC,functionsbelow
whichrequirereferencetocurrentabsolutetimemaybehavenotasexpected.
Functions
utime.gmtime([secs])
ConvertatimeexpressedinsecondssincetheEpoch(seeabove)intoan8-tuplewhich
contains: (year,month,mday,hour,minute,second,weekday,yearday)If secsisnot
providedor None,thenthecurrenttimefromtheRTCisused.
yearincludesthecentury(forexample2014).
monthis1-12
mdayis1-31
houris0-23
minuteis0-59
secondis0-59
weekdayis0-6forMon-Sun
5.3.14utime
378
yeardayis1-366
utime.localtime([secs])
Like gmtime()butconvertstolocaltime.If secsisnotprovidedor None,thecurrenttime
fromtheRTCisused.
utime.mktime()
Thisisinversefunctionof localtime.It’sargumentisafull8-tuplewhichexpressesatime
asper localtime.Itreturnsanintegerwhichisthenumberofsecondssince Jan1,2000.
utime.sleep(seconds)
Sleepforthegivennumberof seconds. secondscanbeafloating-pointnumbertosleep
forafractionalnumberofseconds.NotethatotherMicroPythonportsmaynotaccept
floating-pointargument,forcompatibilitywiththemuse sleep_ms()and sleep_us()
functions.
utime.sleep_ms(ms)
Delayforgivennumberofmilliseconds,shouldbepositiveor0.
utime.sleep_us(us)
Delayforgivennumberofmicroseconds,shouldbepositiveor0
utime.ticks_ms()
Returnsuptime,inmilliseconds.
utime.ticks_us()
Justlike ticks_msabove,butinmicroseconds.
utime.ticks_cpu()
Sameas ticks_us,butfaster.
utime.ticks_diff(old,new)
Measureperiodbetweenconsecutivecallsto ticks_ms(), ticks_us(),or ticks_cpu().
Thevaluereturnedbythesefunctionsmaywraparoundatanytime,sodirectlysubtracting
themisnotsupported. ticks_diff()shouldbeusedinstead."old"valueshouldactually
precede"new"valueintime,orresultisundefined.Thisfunctionshouldnotbeusedto
5.3.14utime
379
measurearbitrarilylongperiodsoftime(because ticks_*()functionswraparoundand
usuallywouldhaveshortperiod).Theexpectedusagepatternisimplementingeventpolling
withtimeout:
#WaitforGPIOpintobeasserted,butatmost500us
start=time.ticks_us()
whilepin.value()==0:
iftime.ticks_diff(start,time.ticks_us())>500:
raiseTimeoutError
utime.time()
Returnsthenumberofseconds,asaninteger,sincetheEpoch,assumingthatunderlying
RTCisset.IfanRTCisnotset,thisfunctionreturnsnumberofsecondssincepowerupor
reset).IfyouwanttodevelopportableMicroPythonapplication,youshouldnotrelyonthis
functiontoprovidehigherthansecondprecision.Ifyouneedhigherprecision,use
ticks_ms()and ticks_us()functions,ifyouneedcalendartime, localtime()withoutan
argumentisabetterchoice.
utime.timezone([secs])
Setorgetthetimezoneoffset,inseconds.If secsisnotprovided,itreturnsthecurrent
value.
InMicroPython, time.timezoneworkstheoppositewaytoPython.InPython,togetthe
localtime,youwrite local_time=utc-timezone,whileinMicroPythonitis local_time
=utc+timezone.
5.3.14utime
380
uhashlib–HashingAlgorithm
Thismoduleimplementsbinarydatahashingalgorithms.MD5andSHAaresupported.By
limitationsinthehardware,onlyoneactivehashingoperationissupportedatatime.
Constructors
classuhashlib.md5([data])
CreateaMD5hasherobjectandoptionallyfeeddataintoit.
classuhashlib.sha1([data])
CreateaSHA-1hasherobjectandoptionallyfeeddataintoit.
classuhashlib.sha224([data])
CreateaSHA-224hasherobjectandoptionallyfeeddataintoit.
classuhashlib.sha256([data])
CreateaSHA-256hasherobjectandoptionallyfeeddataintoit.
classuhashlib.sha384([data])
CreateaSHA-384hasherobjectandoptionallyfeeddataintoit.
classuhashlib.sha512([data])
CreateaSHA-512hasherobjectandoptionallyfeeddataintoit.
Methods
hash.update(data)
Feedmorebinarydataintohash.
hash.digest()
Returnhashforalldatapassedthroughhash,asabytesobject.Afterthismethodiscalled,
moredatacannotbefedintohashanylonger.
hash.hexdigest()
5.3.15uhashlib
381
ThismethodisNOTimplemented.Use ubinascii.hexlify(hash.digest())toachievea
similareffect.
5.3.15uhashlib
382
ussl–sslmodule
ThismoduleprovidesaccesstoTransportLayerSecurity(oftenknownas"SecureSockets
Layer")encryptionandpeerauthenticationfacilitiesfornetworksockets,bothclient-sideand
server-side.
Functions
ssl.wrap_socket(sock,keyfile=None,certfile=None,server_side=False,
cert_reqs=CERT_NONE,ca_certs=None)
Takesaninstance sockof socket.socket,andreturnsaninstanceofssl.SSLSocket,a
subtypeof socket.socket,whichwrapstheunderlyingsocketinanSSLcontext.Example:
importsocket
importssl
s=socket.socket()
ss=ssl.wrap_socket(s)
ss.connect(socket.getaddrinfo('www.google.com',443)[0][-1])
Certificatesmustbeusedinordertovalidatetheothersideoftheconnection,andalsoto
authenticateourselveswiththeotherend.Suchcertificatesmustbestoredasfilesusingthe
FTPserver,andtheymustbeplacedinspecificpathswithspecificnames.
Forinstance,toconnecttotheBlynkserversusingcertificates,takethefile ca.pemlocated
inthe blynkexamplesfolderandputitin /flash/cert/.Thendo:
importsocket
importssl
s=socket.socket()
ss=ssl.wrap_socket(s,cert_reqs=ssl.CERT_REQUIRED,ca_certs='/flash/cert/ca.pem')
ss.connect(socket.getaddrinfo('cloud.blynk.cc',8441)[0][-1])
SSLsocketsinheritallmethodsandfromthestandardsockets,seethe usocketmodule.
Exceptions
ssl.SSLError
Constants
5.3.16ussl
383
ssl.CERT_NONEssl.CERT_OPTIONALssl.CERT_REQUIRED
Supportedvaluesin cert_reqs
5.3.16ussl
384
ucrypto—Cryptography
Thismoduleprovidesnativesupportforcryptographicalgorithms.It’slooselybasedon
PyCrypto.
Classes
classAES-AdvancedEncryptionStandard
Methods
crypto.getrandbits(bits)
Returnsabytesobjectfilledwithrandombitsobtainedfromthehardwarerandomnumber
generator.
AccordingtotheESP32TechnicalReferenceManual,suchbits"...canbeusedasthe
basisforcryptographicaloperations"."Thesetruerandomnumbersaregeneratedbasedon
thenoiseintheWi-Fi/BTRFsystem.WhenWi-FiandBTaredisabled,therandomnumber
generatorwillgiveoutpseudo-randomnumbers."
Theparameter bitsisroundedupwardstothenearestmultipleof32bits.
Cryptographyisnotatrivialbusiness.Doingthingsthewrongwaycouldquicklyresultin
decreasedornosecurity.Pleasedocumentyourselfinthesubjectifyouaredepending
onencryptiontosecureimportantinformation.
5.3.17ucrypto
385
ustruct–PackandUnpackPrimitiveData
Types
SeePythonstructformoreinformation.
Supportedsize/byteorderprefixes: @,<,>,!.
Supportedformatcodes: b,B,h,H,i,I,l,L,q,Q,s,P,f,d(thelatter2depending
onthefloating-pointsupport).
Functions
ustruct.calcsize(fmt)
Returnthenumberofbytesneededtostorethegiven fmt.
ustruct.pack(fmt,v1,v2,...)
Packthevalues v1,v2,...accordingtotheformatstring fmt.Thereturnvalueisa
bytesobjectencodingthevalues.
ustruct.pack_into(fmt,buffer,offset,v1,v2,...)
Packthevalues v1,v2,...accordingtotheformatstring fmtintoabufferstartingat
offset. offsetmaybenegativetocountfromtheendofbuffer.
ustruct.unpack(fmt,data)
Unpackfromthe dataaccordingtotheformatstring fmt.Thereturnvalueisatupleofthe
unpackedvalues.
ustruct.unpack_from(fmt,data,offset=0)
Unpackfromthe datastartingat offsetaccordingtotheformatstring fmt. offsetmay
benegativetocountfromtheendofbuffer.Thereturnvalueisatupleoftheunpacked
values.
5.3.18ustruct
386
thread-Low-levelThreadingAPI
Thismoduleprovideslow-levelprimitivesforworkingwithmultiplethreads(alsocalledlight-
weightprocessesortasks)—multiplethreadsofcontrolsharingtheirglobaldataspace.For
synchronisation,simplelocks(alsocalledmutexesorbinarysemaphores)areprovided.
Whenathreadspecificerroroccursa RuntimeErrorexceptionisraised.
QuickUsageExample
import_thread
importtime
defth_func(delay,id):
whileTrue:
time.sleep(delay)
print('Runningthread%d'%id)
foriinrange(2):
_thread.start_new_thread(th_func,(i+1,i))
Functions
_thread.start_new_thread(function,args[,kwargs])
Startanewthreadandreturnitsidentifier.Thethreadexecutesthefunctionwiththe
argumentlistargs(whichmustbeatuple).Theoptional kwargsargumentspecifiesa
dictionaryofkeywordarguments.Whenthefunctionreturns,thethreadsilentlyexits.When
thefunctionterminateswithanunhandledexception,astacktraceisprintedandthenthe
threadexits(butotherthreadscontinuetorun).
_thread.exit()
Raisethe SystemExitexception.Whennotcaught,thiswillcausethethreadtoexitsilently.
_thread.allocate_lock()
Returnanewlockobject.Methodsoflocksaredescribedbelow.Thelockisinitially
unlocked.
_thread.get_ident()
5.3.19_thread
387
Returnthe threadidentifierofthecurrentthread.Thisisanonzerointeger.Itsvaluehas
nodirectmeaning;itisintendedasamagiccookietobeusede.g.toindexadictionaryof
thread-specificdata.Threadidentifiersmayberecycledwhenathreadexitsandanother
threadiscreated.
_thread.stack_size([size])
Returnthethreadstacksize(inbytes)usedwhencreatingnewthreads.Theoptionalsize
argumentspecifiesthestacksizetobeusedforsubsequentlycreatedthreads,andmustbe
0(useplatformorconfigureddefault)orapositiveintegervalueofatleast 4096(4KiB).
4KiBiscurrentlytheminimumsupportedstacksizevaluetoguaranteesufficientstackspace
fortheinterpreteritself.
Objects
_thread.LockType
Thisisthetypeoflockobjects.
classLock–usedforsynchronisationbetweenthreads
Methods
Lockobjectshavethefollowingmethods:
lock.acquire(waitflag=1,timeout=-1)
Withoutanyoptionalargument,thismethodacquiresthelockunconditionally,ifnecessary
waitinguntilitisreleasedbyanotherthread(onlyonethreadatatimecanacquirealock—
that’stheirreasonforexistence).
Iftheinteger waitflagargumentispresent,theactiondependsonitsvalue:ifitiszero,the
lockisonlyacquiredifitcanbeacquiredimmediatelywithoutwaiting,whileifitisnonzero,
thelockisacquiredunconditionallyasabove.
Ifthefloating-pointtimeoutargumentispresentandpositive,itspecifiesthemaximumwait
timeinsecondsbeforereturning.Anegativetimeoutargumentspecifiesanunboundedwait.
Youcannotspecifyatimeoutif waitflagiszero.
Thereturnvalueis Trueifthelockisacquiredsuccessfully, Falseifnot.
lock.release()
Releasesthelock.Thelockmusthavebeenacquiredearlier,butnotnecessarilybythe
samethread.
5.3.19_thread
388
lock.locked()
Returnthestatusofthelock: Trueifithasbeenacquiredbysomethread, Falseifnot.
Inadditiontothesemethods,lockobjectscanalsobeusedviathewithstatement,e.g.:
import_thread
a_lock=_thread.allocate_lock()
witha_lock:
print("a_lockislockedwhilethisexecutes")
5.3.19_thread
389
5.3.20Builtin
395
ProductInfopages
Thefollowpagescontainallinformationrelatingtoeachproduct,forexamples:pinouts,
specsheets,relevantexamplesandnotes.
DevelopmentModules
WiPy2.0
WiPy3.0
SiPy
LoPy
LoPy4
GPy
FiPy
OEMmodules
W01
L01
L04
G01
L01/W01ReferenceBoard
UniversalReferenceBoard
ShieldsandExpansionboards
ExpansionBoard2.0
Pysense
Pytrack
DeepSleepShield
6.0Introduction
396
ThedatasheetoftheWiPy2isavailableasaPDFFile.
Notes
WiFi
Bydefault,uponboottheWiPy2willcreateaWiFiaccesspointwiththeSSID wipy-wlan-
XXXX,where XXXXisarandom4-digitnumber,andthepassword www.pycom.io.
Power
The VinpinontheWiPy2canbesuppliedwithavoltagerangingfrom 3.5vto 5.5v.
The 3.3vpinontheotherhandisoutputonly,andmustnotbeusedtofeedpowerintothe
WiPy2,otherwisetheon-boardregulatorwillbedamaged.
DeepSleep
DuetoacoupleissueswiththeWiPy2designthemoduledrawsmorecurrentthanitshould
whileindeepsleep.TheDC-DCswitchingregulatoralwaysstaysinhighperformancemode
whichisusedtoprovidethelowestpossibleoutputripplewhenthemodulesisinuse.Inthis
mode,itdrawsaquiescentcurrentof10mA.WhentheregulatorisputintoECOmode,the
quiescentcurrentgoesdownto10uA.Unfortunately,thepinusedtocontrolthismodeisout
oftheRTCdomain,andthereforenotusableduringdeepsleep.Thiscausestheregulatorto
alwaysstayinPWMmode,keepingitsquiescentcurrentat10mA.Alongsidethistheflash
chipdoesn'tenterpowerdownmodebecausetheCSpinisfloatingduringdeepsleep.This
causestheflashchiptoconsumearound2mAofcurrent.Toworkaroundthisissuea"deep
sleepshield"isavailablethatattachestothemoduleandallowspowertobecutofffromthe
device.Thedevicecanthenbere-enabledeitheronatimerorviapininterrupt.Withthe
deepsleepshieldthecurrentconsumptionduringdeepsleepisbetween7uAand10uA
dependingonthewakesourcesconfigured.
Tutorials
TutorialsonhowtotheWiPy2modulecanbefoundintheexamplessectionofthis
documentation.ThefollowingtutorialsmightbeofspecificinterestfortheWiPy2:
WiFiconnection
BLE
6.1.1WiPy2.0
399
6.1.1WiPy2.0
400
DifferencesfromWiPy2.0
Deepsleepcurrentdrawfixed,nowonly19.7µA
UpgradedRAMfrom512KBto4MB
UpgradedExternalFLASHfrom4MBto8MB
AntennaselectpinmovedfromGPIO16toGPIO21(P12)
Datasheet
ThedatasheetoftheWiPy3isavailableasaPDFFile.
Notes
WiFi
Bydefault,uponboottheWiPy3willcreateaWiFiaccesspointwiththeSSID wipy-wlan-
XXXX,where XXXXisarandom4-digitnumber,andthepassword www.pycom.io.
TheRFswitchthatselectsbetweentheon-boardandexternalantennaisconnectedto
P12,forthisreasonusing P12shouldbeavoidedunlessWiFiisdisabledinyour
application.
Power
The VinpinontheWiPy3canbesuppliedwithavoltagerangingfrom 3.5vto 5.5v.
The 3.3vpinontheotherhandisoutputonly,andmustnotbeusedtofeedpowerintothe
WiPy3,otherwisetheon-boardregulatorwillbedamaged.
Tutorials
TutorialsonhowtotheWiPy3modulecanbefoundintheexamplessectionofthis
documentation.ThefollowingtutorialsmightbeofspecificinterestfortheWiPy3:
WiFiconnection
BLE
6.1.2WiPy3.0
402
ThedatasheetoftheLoPyisavailableasaPDFFile.
Notes
WiFi
Bydefault,uponboottheLoPywillcreateaWiFiaccesspointwiththeSSID lopy-wlan-
XXXX,where XXXXisarandom4-digitnumber,andthepassword www.pycom.io.
Power
The VinpinontheLoPycanbesuppliedwithavoltagerangingfrom 3.5vto 5.5v.The
3.3vpinontheotherhandisoutputonly,andmustnotbeusedtofeedpowerintothe
LoPy,otherwisetheon-boardregulatorwillbedamaged.
DeepSleep
DuetoacoupleissueswiththeLoPydesignthemoduledrawsmorecurrentthanitshould
whileindeepsleep.TheDC-DCswitchingregulatoralwaysstaysinhighperformancemode
whichisusedtoprovidethelowestpossibleoutputripplewhenthemodulesisinuse.Inthis
mode,itdrawsaquiescentcurrentof10mA.WhentheregulatorisputintoECOmode,the
quiescentcurrentgoesdownto10uA.Unfortunately,thepinusedtocontrolthismodeisout
oftheRTCdomain,andthereforenotusableduringdeepsleep.Thiscausestheregulatorto
alwaysstayinPWMmode,keepingitsquiescentcurrentat10mA.Alongsidethistheflash
chipdoesn'tenterpowerdownmodebecausetheCSpinisfloatingduringdeepsleep.This
causestheflashchiptoconsumearound2mAofcurrent.Toworkaroundthisissuea"deep
sleepshield"isavailablethatattachestothemoduleandallowspowertobecutofffromthe
device.Thedevicecanthenbere-enabledeitheronatimerorviapininterrupt.Withthe
deepsleepshieldthecurrentconsumptionduringdeepsleepisbetween7uAand10uA
dependingonthewakesourcesconfigured.
Tutorials
TutorialsonhowtotheLoPymodulecanbefoundintheexamplessectionofthis
documentation.ThefollowingtutorialsmightbeofspecificinterestfortheLoPy:
WiFiconnection
LoRaWANnode
6.1.3LoPy
404
Datasheet
ThedatasheetoftheLoPy4isavailableasaPDFFile.
Notes
WiFi
Bydefault,uponboottheLoPy4willcreateaWiFiaccesspointwiththeSSID lopy4-wlan-
XXXX,where XXXXisarandom4-digitnumber,andthepassword www.pycom.io.
TheRFswitchthatselectsbetweentheon-boardandexternalantennaisconnectedto
P12,forthisreasonusing P12shouldbeavoidedunlessWiFiisdisabledinyour
application.
Power
The VinpinontheLoPy4canbesuppliedwithavoltagerangingfrom 3.5vto 5.5v.The
3.3vpinontheotherhandisoutputonly,andmustnotbeusedtofeedpowerintothe
LoPy4,otherwisetheon-boardregulatorwillbedamaged.
Tutorials
TutorialsonhowtotheLoPy4modulecanbefoundintheexamplessectionofthis
documentation.ThefollowingtutorialsmightbeofspecificinterestfortheLoPy4:
WiFiconnection
LoRaWANnode
LoRaWANnanogateway
Sigfox
BLE
6.1.4LoPy4
407
ThedatasheetoftheSiPyisavailableasaPDFFile.
Notes
WiFi
Bydefault,uponboottheSiPywillcreateaWiFiaccesspointwiththeSSID sipy-wlan-XXXX
,where XXXXisarandom4-digitnumber,andthepassword www.pycom.io.
Power
The VinpinontheSiPycanbesuppliedwithavoltagerangingfrom 3.5vto 5.5v.The
3.3vpinontheotherhandisoutputonly,andmustnotbeusedtofeedpowerintothe
SiPy,otherwisetheon-boardregulatorwillbedamaged.
DeepSleep
DuetoacoupleissueswiththeSiPydesignthemoduledrawsmorecurrentthanitshould
whileindeepsleep.TheDC-DCswitchingregulatoralwaysstaysinhighperformancemode
whichisusedtoprovidethelowestpossibleoutputripplewhenthemodulesisinuse.Inthis
mode,itdrawsaquiescentcurrentof10mA.WhentheregulatorisputintoECOmode,the
quiescentcurrentgoesdownto10uA.Unfortunately,thepinusedtocontrolthismodeisout
oftheRTCdomain,andthereforenotusableduringdeepsleep.Thiscausestheregulatorto
alwaysstayinPWMmode,keepingitsquiescentcurrentat10mA.Alongsidethistheflash
chipdoesn'tenterpowerdownmodebecausetheCSpinisfloatingduringdeepsleep.This
causestheflashchiptoconsumearound2mAofcurrent.Toworkaroundthisissuea"deep
sleepshield"isavailablethatattachestothemoduleandallowspowertobecutofffromthe
device.Thedevicecanthenbere-enabledeitheronatimerorviapininterrupt.Withthe
deepsleepshieldthecurrentconsumptionduringdeepsleepisbetween7uAand10uA
dependingonthewakesourcesconfigured.
Tutorials
TutorialsonhowtotheSiPymodulecanbefoundintheexamplessectionofthis
documentation.ThefollowingtutorialsmightbeofspecificinterestfortheSiPy:
WiFiconnection
Sigfox
6.1.5SiPy
409
ThedatasheetoftheGPyisavailableasaPDFFile.
Notes
WiFi
Bydefault,uponboottheGPywillcreateaWiFiaccesspointwiththeSSID gpy-wlan-XXXX,
where XXXXisarandom4-digitnumber,andthepassword www.pycom.io.
TheRFswitchthatselectsbetweentheon-boardandexternalantennaisconnectedto
P12,forthisreasonusing P12shouldbeavoidedunlessWiFiisdisabledinyour
application.
Power
The VinpinontheGPycanbesuppliedwithavoltagerangingfrom 3.5vto 5.5v.The
3.3vpinontheotherhandisoutputonly,andmustnotbeusedtofeedpowerintothe
GPy,otherwisetheon-boardregulatorwillbedamaged.
ATCommands
TheATcommandsfortheSequansMonarchmodemontheGPyareavailableinaPDFfile.
Tutorials
TutorialsonhowtotheGPymodulecanbefoundintheexamplessectionofthis
documentation.ThefollowingtutorialsmightbeofspecificinterestfortheGPy:
WiFiconnection
LTECAT-M1
NB-IoT
BLE
6.1.6GPy
412
ThedatasheetoftheFiPyisavailableasaPDFFile.
Notes
WiFi
Bydefault,uponboottheFiPywillcreateaWiFiaccesspointwiththeSSID fipy-wlan-XXXX
,where XXXXisarandom4-digitnumber,andthepassword www.pycom.io.
TheRFswitchthatselectsbetweentheon-boardandexternalantennaisconnectedto
P12,forthisreasonusing P12shouldbeavoidedunlessWiFiisdisabledinyour
application.
Power
The VinpinontheFiPycanbesuppliedwithavoltagerangingfrom 3.5vto 5.5v.The
3.3vpinontheotherhandisoutputonly,andmustnotbeusedtofeedpowerintothe
FiPy,otherwisetheon-boardregulatorwillbedamaged.
ATCommands
TheATcommandsfortheSequansMonarchmodemontheFiPyareavailableinaPDFfile.
Tutorials
TutorialsonhowtotheFiPymodulecanbefoundintheexamplessectionofthis
documentation.ThefollowingtutorialsmightbeofspecificinterestfortheFiPy:
WiFiconnection
LoRaWANnode
LoRaWANnanogateway
Sigfox
LTECAT-M1
NB-IoT
BLE
6.1.7FiPy
414
6.1.7FiPy
415
Drawings
ThedrawingsfortheW01isavailableasaPDFFile.
PleasenotethatthePINassignmentsforUART1(TX1/RX1),SPI(CLK,MOSI,MISO)and
I2C(SDA,SCL)aredefaultsandcanbechangedinSoftware.
Tutorials
TutorialsonhowtotheW01modulecanbefoundintheexamplessectionofthis
documentation.ThefollowingtutorialsmightbeofspecificinterestfortheW01:
WiFiconnection
BLE
6.2.1W01
418
Drawings
ThedrawingsfortheL01isavailableasaPDFFile.
PleasenotethatthePINassignmentsforUART1(TX1/RX1),SPI(CLK,MOSI,MISO)and
I2C(SDA,SCL)aredefaultsandcanbechangedinSoftware.
Tutorials
TutorialsonhowtotheL01modulecanbefoundintheexamplessectionofthis
documentation.ThefollowingtutorialsmightbeofspecificinterestfortheL01:
WiFiconnection
LoRaWANnode
LoRaWANnanogateway
BLE
6.2.2L01
420
Drawings
ThedrawingsfortheL04isavailableasaPDFFile.
PleasenotethatthePINassignmentsforUART1(TX1/RX1),SPI(CLK,MOSI,MISO)and
I2C(SDA,SCL)aredefaultsandcanbechangedinSoftware.
Tutorials
TutorialsonhowtotheL04modulecanbefoundintheexamplessectionofthis
documentation.ThefollowingtutorialsmightbeofspecificinterestfortheL04:
WiFiconnection
LoRaWANnode
LoRaWANnanogateway
Sigfox
BLE
6.2.3L04
422
Drawings
ThedrawingsfortheG01isavailableasaPDFFile.
PleasenotethatthePINassignmentsforUART1(TX1/RX1),SPI(CLK,MOSI,MISO)and
I2C(SDA,SCL)aredefaultsandcanbechangedinSoftware.
ATCommands
TheATcommandsfortheSequansMonarchmodemontheG01areavailableinaPDFfile.
Tutorials
TutorialsonhowtotheG01modulecanbefoundintheexamplessectionofthis
documentation.ThefollowingtutorialsmightbeofspecificinterestfortheG01:
WiFiconnection
LTECAT-M1
NB-IoT
BLE
6.2.4G01
424
L01referencedesign
TheL01OEMreferenceboardisareferencedesignsuitableL01aswellasW01makingit
possibletohaveasinglePCBdesignthatcanaccommodatebothOEMmodules.
IfyourequireareferenceboardfortheL04orG01,thisdesignisnotsuitableasitdoes
notfeatureaSIMslotorthedoubleantennaconnection.FortheG01orL04pleaseuse
theUniversalOEMBaseboardReference
Features
SuitsbothL01orW01OEMModules
U.FLconnectorfortheL01'sLoRaoutput.
On-board2.4GHzantennaforWiFiandBluetooth,withtheabilitytoswitchtoaexternal
antennaviaaU.FLconnector.
WS2812BRGBLED
3.5-5.5InputswitchmodeDC-DCregulatorwithlowcurrentdrawduringdeepsleep
Resetbutton
Layout
ThelayoutoftheL01baseboardreferenceisavailableasaPDFFile.
6.2.5L01OEMBaseboardReference
425
6.2.5L01OEMBaseboardReference
427
OEMBaseboardReferenceDesignFiles
TheuniversalOEMreferenceboardisareferencedesignsuitableW01,L01,L04andG01
OEMmodules,makingitpossibletohaveasinglePCBdesignthatcanaccommodateall
ourOEMmodules.
IfyourequireareferenceboardfortheG01,onlythisdesignissuitable.TheL01
referenceboarddoesnotcontainthenecessarySIMslot.
Features
SuitsallOEMmodules(L01,L04,W01,G01)
On-board2.4GHzantennaforWiFiandBluetooth,withtheabilitytoswitchtoaexternal
antennaviaaU.FLconnector.
3U.FLconnectorsforalltheoutputsavailableontheOEMmodules
WS2812BRGBLED
3.5-5.5InputswitchmodeDC-DCregulatorwithlowcurrentdrawduringdeepsleep
Resetbutton
Layout
ThelayoutoftheOEMbaseboardreferenceisavailableasaPDFFile.
6.2.6UniversalOEMBaseboardReference
428
6.2.6UniversalOEMBaseboardReference
430
TheExpansionBoardfeaturesasinglecellLi-Ion/Li-Pocharger.Whentheboardisbeing
poweredviathemicroUSBconnector,theExpansionBoardwillchargethebattery(if
connected).Whenthe CHGjumperispresentthebatterywillbechargedat 450mA.Ifthis
valueistoohighforyourapplication,removingthejumperlowersthechargecurrentto
100mA.
Specsheets
ThespecsheetoftheExpansionBoardisavailableasaPDFFile.
Differencesbetweenv2.0andv3.0
TheFTDIchipasbeenreplacedwithacustomprogrammedPIClikeonthe
Pysense/Pytrack/Pyscanboards.Thisallowsourfirmwareupdatetooltoautomatically
putthemoduleintobootloadermode.
Addeda"Safeboot"buttontoentersafebooteasier.Thisbuttonconnects P12to
3.3vandifpressedandheldwhiletheresetbuttonispressedonaPycommodule,
themodulewillentersafeboot.
6.3.1ExpansionBoard3.0
433
ThespecsheetofthePytrackisavailableasaPDFFile.
6.3.2Pytrack
435
ThespecsheetofthePysenseisavailableasaPDFFile.
6.3.3Pysense
437
Pyscan
PyscanLibraries
PyscanlibrariestousetheRFID/NFCreaderarelocatedhere:
https://github.com/pycom/pycom-libraries/tree/master/pyscanTheaccelerometerlibraryis
here:https://github.com/pycom/pycom-libraries/blob/master/pytrack/lib/LIS2HH12.py
Forthetimebeing,werecommendtouploadthe MFRC630.mpyfileviaFTPduetocurrent
limitationsofPymakrthatwillbefixedshortly.
Librariesfortherestofthecomponentswillbeaddedsoon.
Pyscancomponents:
Accelerometer:STLIS2HH12
Ambientlightsensor:Lite-onLTR-329ALS-01
RFID/NFCreader:NXPMFRC63002HN,151
Driver
TheWindows7driverforPyscanislocatedin:
https://docs.pycom.io/chapter/pytrackpysense/installation/drivers.htmlForotherOperating
Systemsthere'snodriverrequired.
Pinout
ThepinoutofthePyscanisavailableasaPDFFile.
6.3.4Pyscan
438
Begentlewhenplugging/unpluggingfromtheUSBconnector.WhilsttheUSBconnector
issolderedandisrelativelystrong,ifitbreaksoffitcanbeverydifficulttofix.
BatteryCharger
TheExpansionBoardfeaturesasinglecellLi-Ion/Li-Pocharger.Whentheboardisbeing
poweredviathemicroUSBconnector,theExpansionBoardwillchargethebattery(if
connected).Whenthe CHGjumperispresentthebatterywillbechargedat 450mA.Ifthis
valueistoohighforyourapplication,removingthejumperlowersthechargecurrentto
100mA.
Specsheets
ThespecsheetoftheExpansionBoardisavailableasaPDFFile.
6.3.5ExpansionBoard2.0
441
DeepSleepShield
TheschematicoftheDeepSleepShieldisavailableasaPDFFile.
Pinout
ThepinoutoftheDeepSleepShieldisavailableasaPDFFile.
TocorrectlyconnectaWiPy2.0,LoPyorSiPytotheDeepSleepShield,alignthewhite
triangleontheShieldwiththeLEDofthePycomDevice.OncethePycomDeviceis
seatedontotheDeepSleepShield,thiscanthenbeconnectedtotheExpansionBoard.
6.3.6DeepSleepShield
442
6.3.6DeepSleepShield
443
DeepSleepAPI
ThischapterdescribesthelibrarywhichcontrolstheDeepSleepShield.Thisincludesthe
controlsforexternalinterruptsandtimersetupofthedeepsleepfunctionality.
Tousethislibrary,pleaseuploadtheassociatedDeepSleepLibraryto /libonthetarget
Pycomdevice.
QuickExample
fromdeepsleepimportDeepSleep
importdeepsleep
ds=DeepSleep()
#getthewakereasonandthevalueofthepinsduringwakeup
wake_s=ds.get_wake_status()
print(wake_s)
ifwake_s['wake']==deepsleep.PIN_WAKE:
print("Pinwakeup")
elifwake_s['wake']==deepsleep.TIMER_WAKE:
print("Timerwakeup")
else:#deepsleep.POWER_ON_WAKE:
print("PowerONreset")
ds.enable_pullups('P17')#canalsodods.enable_pullups(['P17','P18'])
ds.enable_wake_on_fall('P17')#canalsodods.enable_wake_on_fall(['P17','P18'])
ds.go_to_sleep(60)#gotosleepfor60seconds
DeepSleep
TheDeepSleepShieldallowsforwakingupviaausertriggerandalsoviaanexternal
interrupt(i.e.Accelerometer,Button).
Constructors
classDeepSleep()
CreatesaDeepSleepobject,thatwillcontroltheboard'ssleepfeatures.Forexample;
ds=DeepSleep()
6.3.6.1DeepSleepAPI
444
Methods
deepsleep.enable_auto_poweroff()
Thismethodallowsforacriticalbatteryvoltagetobeset.Forexample,iftheexternalpower
source(e.g.LiPoCell)fallsbelow 3.3V,turnoffthePycomdevice.Thisisintendedto
protectthehardwarefromundervoltage.
deepsleep.enable_pullups(pins)
Thismethodallowsforpull-uppinstobeenabled.Forexample,ifanexternaltriggeroccurs,
wakethePycomdevicefromDeepSleep. pinsmaybepassedintothemethodasalist,
i.e. ['P17','P18'].
deepsleep.disable_pullups(pins)
Thismethodallowsforpull-uppinstobedisabled.Forexample,ifanexternaltriggeroccurs,
wakethePycomdevicefromDeepSleep. pinsmaybepassedintothemethodasalist,
i.e. ['P17','P18'].
deepsleep.enable_wake_on_raise(pins)
Thismethodallowsforpull-uppinstotriggeronarisingvoltage.Forexample,ifanexternal
risingvoltagetriggersoccurs,wakethePycomdevicefromDeepSleep. pinsmaybe
passedintothemethodasalist,i.e. ['P17','P18'].
deepsleep.disable_wake_on_raise(pins)
Thismethodallowsfordisablingpull-uppinsthattriggeronarisingvoltage. pinsmaybe
passedintothemethodasalist,i.e. ['P17','P18'].
deepsleep.enable_wake_on_fall(pins)
Thismethodallowsforpull-uppinstotriggeronafallingvoltage.Forexample,ifanexternal
fallingvoltagetriggersoccurs,wakethePycomdevicefromDeepSleep. pinsmaybe
passedintothemethodasalist,i.e. ['P17','P18'].
deepsleep.disable_wake_on_fall(pins)
Thismethodallowsfordisablingpull-uppinsthattriggeronafallingvoltage. pinsmaybe
passedintothemethodasalist,i.e. ['P17','P18'].
deepsleep.get_wake_status()
Thismethodreturnsthestatusofthepinsatwakeupfromdeepsleep.Themethodreturnsa
dictwiththestatesof wake, P10, P17, P18.
6.3.6.1DeepSleepAPI
445
deepsleep.set_min_voltage_limit(value)
Thismethodrelatestothe enable_auto_poweroffmethodandallowstheusertospecifythe
minimumpoweroffvoltageasavalue.
deepsleep.go_to_sleep(seconds)
Thismethodsendstheboardintodeepsleepforaperiodof secondsoruntilanexternal
interrupthastriggered(see set_pullups).
deepsleep.hw_reset()
ThismethodresetsthePICcontrollerandresetsittothestateprevioustothepins/min-
voltagebeingset.
Pleasenotethatmorefunctionalityisbeingaddedweeklytotheselibraries.Ifarequired
featureisnotavailable,feelfreetocontributewithapullrequestatthePycomLibraries
GitHubrepository.
6.3.6.1DeepSleepAPI
446
Notes
Poweringwithanexternalpowersource
Thedevicescanbepoweredbyabatteryorotherexternalpowersource.
Besuretoconnectthepositiveleadofthepowersupplyto VIN,andgroundto GND.
Whenpoweringvia VIN:
Theinputvoltagemustbebetween 3.4Vand 5.5V.
PleaseDONOTpowertheboardviathe 3.3Vpinasthismaydamagethedevice.
ONLYusethe VINpinforpoweringPycomdevices.
ThebatteryconnectorfortheExpansionBoardisaJSTPHR-2variant.TheExpansion
Boardexposesthemaleconnectorandanexternalbatteryshoulduseafemaleadapterin
ordertoconnectandpowertheexpansionboard.Thepolarityofthebatteryshouldbe
checkedbeforebeingpluggedintotheexpansionboard,thecablesmayrequireswapping.
The GPIOpinsofthemodulesareNOT5Vtolerant,connectingthemtovoltages
higherthan 3.3Vmightcauseirreparabledamagetothedevice.
Staticelectricitycandamagecomponentsonthedeviceandmaydestroythem.Ifthere
isalotofstaticelectricityinthearea(e.g.dryandcoldclimates),takeextracarenotto
shockthedevice.IfthedevicecameinaESDbag(Silverpackaging),thebestwayto
storeandcarrythedeviceisinsidethisbagasitwillbeprotectedagainststatic
discharges.
6.4Notes
447
WhatisPybytes?
PybytesisanIoTEcosystemthatempowersyoubygrantingfullcontrolofallyourPycom
devices.
WithPybytesyouhavecontroloveryourdevice'sdatastreamandmore:
Visualisesensorsdataaccordingtoyourinterestsusingourcustomisabledashboard;
Checkthestatusofyourentirefleet;
Keeptrackofyourassetswithourgeolocationfeature;
Distributefirmwareupdatesonascalableapproach.
Inanutshell,PybytesisanenvironmentdesignedtooptimiseyourIoTapplicationsusing
Pycomboards.
WhatPybytesoffersyou?
DataVisualisation:Pybytesdashboardiscustomisable,allowingyoutofreelysetupkey
performanceindicatorsandtimeseriesdatafromallyoursensors.
Intelligentnotifications:Keeptrackofyourdevice'sstatus,batterylevel,datastreaming
andmeasurementswithpre-definedalarms.ReceivenotificationsviaemailorSMS.
Terminal:Executecommandstogatheraccurateinformationfromyourdevicesusing
Pybytesterminalshell.
Firmwareupdatesovertheair:Upgradeordowngradefirmwareversionswithour
exclusivefirmwareupdate.
Trackyourassetsposition:GoogleMapsAPIempowersyourviewoveryourdevice's
geolocation.
Let'sgetstarted!
GettingstartedwithPybytes
ConnectyourPycommoduletoPybytes
8.1Introduction
451
CreateyourPybytesaccount
FollowthesestepstocreateaPybytesaccount:
Step1:Gototheregistrationpage
1. Gotothislink.
2. Enteryourfullname,emailaddressandapasswordtoyouraccount.
3. Confirmtheverificationmessagesenttoyouremailaddress.
4. Clickonthelinkandcompleteyourlogin.
GoInvent!
Nowit'stimetoexplorePybytes.YoucanstartbyconnectingyourPycomboardtoPybytes.
Checkhere!
8.2GettingStarted
453
3. Selectyourshield(e.g.,PySense,PyTrack,PyScanorother);
4. Selectyournetworkoption;
8.3AddadevicetoPybytes
455
SelecthowyouwouldliketoconnectyourdevicetoPybytes:
1. CONNECTYOURDEVICEQUICKLY(RECOMMENDED)
2. CONNECTYOURDEVICEBYFLASHINGPYBYTESLIBRARY
Fromfirmware1.16.xonwardsallPycomdevicescomewithPybyteslibrarybuild-in
/frozenfolder.Thatmeansthatyoucanchoosebetweenaddingyourdevicequickly
withthefirmwareupdateroryoucanflashPybyteslibrarymanually.
8.3AddadevicetoPybytes
457
ConnectingadevicetoPybytesquicklyby
usingtheFirmwareUpdater
Inthissection,weexplaintoyouhowtoconnectyourdevicetoPybytesquicklyusingthe
FirmwareUpdater.
IncaseyouwanttoextendPybyteslibraryyoucanflashPybyteslibrarymanually.Click
hereformoreinformation.
Step1:Downloadthefirmwareupdater
Atthelaststepofthe"AddDevice"process:
1. Downloadthefirmwareupdaterforyouroperatingsystem;
8.3.1ConnecttoPybytes:QuickAdd
458
2. Selectyourdeviceserialport(Makesureyourdeviceisconnectedtoyourcomputer);
3. Marktheoptions"Eraseflashfilesystem"and"ForceupdatePybytesregistration";
4. PasteyourdevicetokenfromPybytes;
8.3.1ConnecttoPybytes:QuickAdd
460
5. Thefirmwareupdaterwillupdatethedevice'sfirmware.
8.3.1ConnecttoPybytes:QuickAdd
461
ConnectingadevicetoPybytesby
flashingPybyteslibrarymanually
Inthissection,wewillexplaintoyouhowtoconnectyourdevicetoPybytesbyflashing
Pybyteslibrarymanually.
Fromfirmware1.16.xonwardsallPycomdevicescomewithPybyteslibrarybuild-in
/frozenfolder.Thatmeansthatyoucanaddyourdevicequicklywithouttheneedof
flashingPybyteslibrarymanually.Clickhereformoreinformation.
Step1:DownloadyourPybytesLibrary
Atthelaststepofthe"AddDevice"process:
1.Clickondownload*Pybyteslibrary*
8.3.2ConnecttoPybytes:FlashPybyteslibrarymanually
463
YoucanalsodownloadPybyteslibraryatthedevice'ssettingspage:
1. NavigatetoyourdeviceinPybytes;
2. Onyourdevice'spageclickonsettingstab;
3. ClickonthebuttonDownloadatPybyteslibrary;
Step2.FlashyourdevicewithPymakr
Incaseyouhaven'tinstalledPymakrplugin,followtheseinstructions.
1. ConnectyourdevicetoyourcomputerwithUSBcable.
2. ExtractdownloadPybyteslibraryandopenextractedfolderwithAtom.
3. Getyourdeviceserialport:inPymakrpluginclickonMore>getserialports
4. Pasteyourdevice'sserialportto pymakr.conffile:
8.3.2ConnecttoPybytes:FlashPybyteslibrarymanually
464
{
"address":"PASTE_YOUR_SERIAL_PORT_HERE",
"username":"micro",
"password":"python",
"sync_folder":"flash"
}
5. Checkoutyour flash/pybytes_config.jsonfile.Itwillbepre-filledwithyourinformation
fromPybytesLikedeviceTokenorWiFicredentials.Youcanchangee.g.yourWiFy
passwordhere.
6. Putyourdeviceinsafebootmode.
7. UploadcodetoyourdevicebyclickingonUploadbuttoninPymakr.AfterallPybytes
libraryfilesareuploadedtodevice,devicewillrestartandwillconnecttoPybytes.
Pybyteslibraryiswrittento /flashfolderandwilltakeprecedenceoverbuildin
firmwarelibrariesin /frozenfolder.
Nextstep:Setupyourdevice's
dashboard!
Nowit'stimetodisplaydatafromyourdeviceintoPybytesdashboard.Youcancheckmore
aboutithere!
8.3.2ConnecttoPybytes:FlashPybyteslibrarymanually
465
Visualisedatafromyourdevice.
Inthissection,wewillexplaintoyouhowtocreatewidgetsfordatavisualisationandsetup
yourdevice'sdashboardonPybytes.
WeassumethatyoualreadyhaveyourdeviceconnectedtoPybytes.Incaseyou
haven't,checkhowtoaddyourdevicehere.Afteryourdonewiththat,youcanproceed
tothenextexample.
Step1:Setupyourapplication(main.py)
Thefirststepistohaveanapplicationrunningonyourdevice.Theapplicationinthis
examplesendsdatafromavectorevery10secondstoPybytes.
1. Openthe main.pyfileonPymakr;
2. Insertthefollowingcodeonyour main.py;
8.4Visualisedatafromyourdevice
466
##Importwhatisnecessarytocreateathread
import_thread
fromtimeimportsleep
##Incrementindexusedtoscaneachpointfromvectorsensors_data
definc(index,vector):
ifindex<len(vector)-1:
returnindex+1
else:
return0
##Defineyourthread'sbehaviour,hereit'saloopsendingsensorsdataevery10sec
onds
defsend_env_data():
idx=0
sensors_data=[0,-0.2,-0.5,-0.7,-0.8,-0.9,-0.9,-0.9,-0.8,-0.6,-0.4,-0.2
,0,0.3,0.5,0.7,0.8,0.9,0.9,0.9,0.8,0.6,0.4,0.1]
while(pybytes):
pybytes.send_virtual_pin_value(False,1,sensors_data[idx])
idx=inc(idx,sensors_data)
sleep(10)
##Startyourthread
_thread.start_new_thread(send_env_data,())
1. Uploadthecodeintoyourdevice.NowyourdeviceissendingdatatoPybytes.
Inthiscode,we'recallingthefunction pybytes.send_virtual_pin_value(persistent,
pin,value))tocommunicatewithPybytes.ThisfunctionispartofthePybytes
library,andithasthreearguments: persistent, pinand value.
persistentdenotesinformationthatisinfrequentlyaccessedandnotlikelyto
bemodified;
pinrepresentswhichvirtualpinisreceivingdata;
valueisthevaluebeingattributedtothatparticularpin.
Step2:Addasignalfromyourdevice
GotoPybytes.
1. On Devicespageselectadevice;
8.4Visualisedatafromyourdevice
467
2. Onyourdevice'spageclickon Datatab.
3. Clickonthe DefineNewSignalbutton.
8.4Visualisedatafromyourdevice
468
4. Definethenewsignalbyenteringanumber,aname,adatatypeandaunit.Finally,
clickonthebutton Define.
5. Yoursignalwasadded!
8.4Visualisedatafromyourdevice
469
ThenameandunitarelabelsusedtoidentifyyoursignalinsidePybytes(Inthis
examplewedefined Sinwaveasthenameofthesignaland Radastheunit).
Thesignalnumberhastomatchthepinnumberthatyoudefinedon
pybytes.send_virtual_pin_valuefunctioncall,insideyour main.pycode(Inthis
examplewedefined pin=1);
Thedatatypealsohastomatchthevariableusedasargumenton
pybytes.send_virtual_pin_valuefunctioncall,insideyour main.pycode(Inthis
exampleourvariableisafloatingnumber;thereforewedefinedasa Float32).
Step3:Addawidgetforthesignal
1. Clickonthesignalcard.
8.4Visualisedatafromyourdevice
470
2. Clickonthebutton Createanewdisplay.
3. Selectthetypeofvisualisation(e.g.BarchartorLinechart).
8.4Visualisedatafromyourdevice
471
4. Youcanadjusttheparametersofyourwidgetat Settings.After,clickonthebutton
Create.
5. Yourwidgetwascreated.Now,addyourwidgettoyourdevice'sdashboard.Clickonthe
button Editonyourwidget.
8.4Visualisedatafromyourdevice
472
6. Markthecheckbox DisplayonDashboardat Settings.Finally,clickonthebutton
Save.
7. Clickonthetab Dashboard.Yourwidgetwassuccessfullyaddedthere!
8.4Visualisedatafromyourdevice
473
Step4:Organiseyourdashboard
1. Clickonthebutton Organise.Nowthedashboard'sgridwillentertheeditmodeand
allowyoutoresizeandrepositionitswidgets.
2. Resizeawidgetbyclickingonthetriangleiconatthebottomrightcornerofthewidget
anddragthecursoroverthegrid.After,clickonthebutton Savetosavethisaction.
8.4Visualisedatafromyourdevice
474
3. Changethewidget'spositionbydrag-and-droppingitoverthegrid.After,clickonthe
button Savetosavethisaction.
Done!
Nowyou'velearnedhowtosetupyourdevice'sdashboardtodisplaydata.Also,youcan
addmorewidgetstootherpinsofyourdevice.
8.4Visualisedatafromyourdevice
475
8.4Visualisedatafromyourdevice
476
DocumentationNotes
ThePycomdocumentationaimstobestraightforwardandtoadheretotypicalPython
documentationtoallowforeaseofunderstanding.However,theremaybesomeunusual
featuresforthosenotusedtoPythondocumentationorthatarenewtotheMicroPython
Language.Thissectionofthedocumentationaimstoprovideclarityforanyofthedesign
specificsthatmightbeconfusingforthosenewtoPythonandthisstyleofdocumentation.
9.1Introduction
477
DocumentationSyntax
ThePycomdocumentationfollowsstandardPythonLibraryformatusingthepopularSphinx
Docstool.Therearesomenotablepointsregardingthesyntaxofclasses,methodsand
constants.Pleaseseethenotesbelowandfamiliariseyourselfwiththespecificdetails
beforereviewingthedocumentation.
KeywordArguments
KeywordArgumentsrefertotheargumentsthatarepassedintoaconstructor(upon
referencingaclassobject).WhenpassingvaluesintoaMicroPythonconstructoritisnot
alwaysrequiredtospecifythenameoftheargumentandinsteadrelyontheorderofthe
argumentspassedastodescribewhattheyreferto.Intheexamplebelow,itcanbeseen
thattheargument modeispassedintothe i2c.init()methodwithoutspecifyinganame.
Thevaluesofthearguments(asseenintheexamples/docs)refertothedefaultvaluesthat
arepassedintotheconstructorifnothingisprovided.
i2c.init(mode,*,baudrate=100000,pins=(SDA,SCL))
Anexampleofhowthismethodmightbecalled:
i2c.init(I2C.MASTER,pins=('P12','P11'))
Itcanbeseenthatavaluefor baudratewasnotpassedintothemethodandthus
MicroPythonwillassumeadefaultvalueof 100000.Alsothefirstargument modewasnot
specifiedbyname,astheconstructordoesnotrequireit,denotedbythelackofan =
symbolintheconstructordocumentation.
PassingArgumentsintoaMethod
Itisimportanttonotethattherearecertainclassmethodsthatcanonlyaccepta keyword
forcertainargumentsaswellassomethatonlyaccepta value.Thisisintentionalby
designbutisnotalwaysapparenttotheusercallingspecificmethods.Thedifferences
betweenthetwoareoutlinedbelow,withexamplesreferencingwheredifferencesmight
applyandwhattobeawareof.
Keyword
9.2Syntax
478
Anastrik *inamethoddescription(inthedocs),denotesthatthefollowingarguments
requireakeyword,i.e. pin='P16'intheexamplebelow.
adc.channel(*,pin,attn=ADC.ATTN_0DB)
frommachineimportADC
adc=ADC()#createanADCobject
apin=adc.channel(pin='P16')#createananalogpinonP16
pinisarequiredargumentandthemethod channelwillnotexecuteunlessitispassed
aswithakeyword.
Anotherexampleshowshowthe PWMclass, pwm.channel()requiresakeywordargument
for pinbutdoesnotfor id.
frommachineimportPWM
pwm=PWM(0,frequency=5000)
pwm_c=pwm.channel(0,pin='P12')#nokeywordargumentrequiresforid(0)butisreq
uiredforpin(pin='P12')
Value
Thedocumentationmayrefertoamethodthattakesanargumentlistedbynamebutdoes
allowforakeywordtobepassed.Forexample,the pycomclasscontainsamethod
rgbled.Thisliststhatthemethodacceptsavaluefor color,howeverthismaynotbe
specifiedby keyword,only value.Thisisintentionalasthe valuebeingpassedisthe
onlyargumentvalidforthismethod
pycom.rgbled(color)
Iftheargumentispassedintothemethodwithakeyword,itwillreturnanerrorstating
TypeError:functiondoesnottakekeywordarguments.
importpycom
pycom.rgbled(color=0xFF0000)#Incorrect
pycom.rgbled(0xFF0000)#Correct
Anotherexampleofamethodthatonlyacceptsvalueinput.Inthiscase,the RTC.init()
methodrequireavalue( tuple)inputforthe datetime.Itwillnotacceptakeyword.
rtc.init(datetime)
9.2Syntax
479
frommachineimportRTC
rtc=RTC()
rtc.init(datetime=(2014,5,1,4,13,0,0,0))#Incorrect
rtc.init((2014,5,1,4,13,0,0,0))#Correct
Constants
The constantssectionofalibrarywithinthedocsreferstospecificvaluesfromthatlibrary’s
class.Thesemightbeusedwhenconstructinganobjectfromthatclassorwhenutilisinga
methodfromwithinthatclass.Thesearegenerallylistedbythelibrarynamefollowedbythe
specificvalue.Seetheexamplebelow:
I2C.MASTER()
Beawarethatyoucanonlyreferencetheseconstantsuponimportingandconstructing
aobjectfromalibrary.
9.2Syntax
480
REPLvsScripts
Usersofthisdocumentationshouldbeawarethatexamplesgiveninthedocsareunderthe
expectationthattheyarebeingexecutedusingtheMicroPythonREPL.Thismeansthat
whencertainfunctionsarecalled,theiroutputmaynotnecessarilybeprintedtotheconsole
iftheyarerunfromascript.WhenusingtheREPLmanyclasses/functionsautomatically
produceaprintedoutputdisplayingthereturnvalueofthefunctiontotheconsole.Thecode
snippetbelowdemonstratessomeexamplesofclasses/functionsthatmightdisplaythis
behaviour.
BasicArithmetic
1+1#REPLwillprintout'2'toconsole
1+1#Scriptwillnotreturnanythingtheconsole
print(1+1)#BoththeREPLandascriptwillreturn'2'totheconsole
CallingMethods
importubinascii
ubinascii.hexlify(b'12345')#REPLwillprintout"b'3132333435'"totheconsole
ubinascii.hexlify(b'12345')#Scriptwillnotreturnanytheconsole
Inordertousethesefunctionsthatdonotprintoutanyvalues,youwillneedtoeitherwrap
themina print()statementorassignthemtovariablesandcallthemlaterwhenyouwish
tousethem.
Forexample:
#immediatelyprinttoconsolewhenusingascript
print(1+1)
#orsavevariabletoforlater
value=1+1
#dosomethinghere...
print(value)
9.3REPLvsScripts
481
FirmwareDowngrade
Thefirmwareupgradetoolusuallyupdatesyourdevicetothelatestavailablefirmware
version.Ifyourequiretodowngradeyourdevicetoapreviousfirmwaretherearetwo
methodstoachievethis.
IfyouareusinganExpansionBoard1.0or2.0,youwillneedtohaveajumper
connectedbetween G23and GNDtouseeitherprocedurebelow.Youwillalsoneedto
presstheresetbuttonbeforebeginning.
Youcanobtainpreviousfirmwareversionshere:
WiPy
LoPy
SiPy
GPy
FiPy
LoPy4
Note:Priortoversion 1.16.0.b1thefirmwareformoduleswithLoRafunctionalitywas
frequencyspecific.From 1.16.0.b1andonward,thefirmwareisregionagnosticandthis
caneitherbesetprogramaticallyorviatheconfigblock(seehere).
GUI
Asofversion 1.12.0.b0ofthefirmwareupdatetool,youcannowprovidea .taror
.tar.gzarchiveofthefirmwareyouwishtouploadtotheboard.
Whenyoustarttheupdatetoolyouwillseethefollowingscreen:
10.1FirmwareDowngrade
482
Whenyoutickthe Flashfromlocalfileoption,anaddressbarwillappear.Clickthe ...
buttonandlocatethe .tar(.gz)filewiththefirmwareyouwishtoflashtoyourdevice.
Fromthispointtheupdaterwillbehavejustlikearegularupdatebutusingthelocalfile
insteadofdownloadingthelatest.
Commandline
YoucanalsousetheCLIversionoftheupdatetooltodowngradeyourdevice.Willneedto
geta .taror .tar.gzarchiveofthefirmwareyouwishtouploadtotheboard.Thenrun
thefollowingcommands:
$pycom-fwtool-cli-v-pPORTflash-t/path/to/firmware/archive.tar.gz
10.1FirmwareDowngrade
483
CommandLineUpdateUtility
Windows
AfterinstallingtheWindowsversionoftheupdatertool,theCLItool pycom-fwtool-cli.exe
canbefoundhere:
32-BitWindows: C:\ProgramFiles\Pycom\PycomFirmwareUpdate\
64-BitWindows: C:\ProgramFiles(x86)\Pycom\PycomFirmwareUpdate\
macOS
InordertogetaccesstotheCLItoolonmacOS,youwillneedtorightclickontheMac
versionoftheupdatertoolandclick ShowPackageContents,thennavigateto
Contents/Resources,hereyouwillfindthe pycom-fwtool-cli.
Linux
IntheUbuntu14.04LTS(andnewer)versionoftheupdatertool, pycom-fwtool-cliis
installedin /usr/local/bin.IntheGenericLinuxpackage,thetoolisextractedintofolder
./pyupgrade
Usage
10.2CLIUpdater
484
usage:pycom-fwtool-cli[-h][-v][-d][-q][-pPORT][-sSPEED][-c][-x]
[--ftdi][--pic][-r]
{list,chip_id,wmac,smac,sigfox,exit,flash,copy,write,write_rem
ote,wifi,pybytes,cb,nvs,ota,lpwan,erase_fs,erase_all}
...
UpdateyourPycomdevicewiththespecifiedfirmwareimagefileFormore
detailspleaseseehttps://docs.pycom.io/chapter/advance/cli.html
positionalarguments:
{list,chip_id,wmac,smac,sigfox,exit,flash,copy,write,write_remote,wifi,pybytes,cb,nv
s,ota,lpwan,erase_fs,erase_all}
listGetlistofavailableCOMports
chip_idShowESP32chip_id
wmacShowWiFiMAC
smacShowLPWANMAC
sigfoxShowsigfoxdetails
exitExitfirmwareupdatemode
flashWritefirmwareimagetoflash
copyRead/Writeflashmemorypartition
writeWritetoflashmemory
wifiGet/SetdefaultWIFIparameters
pybytesRead/Writepybytesconfiguration
cbRead/Writeconfigblock
nvsRead/Writenonvolatilestorage
otaRead/Writeotablock
lpwanGet/SetLPWANparameters[EU868US915AS923AU915]
erase_fsEraseflashfilesystemarea
erase_allEraseentireflash!
optionalarguments:
-h,--helpshowthishelpmessageandexit
-v,--verboseshowverboseoutputfromesptool
-d,--debugshowdebugginoutputfromfwtool
-q,--quietsuppresssuccessmessages
-pPORT,--portPORTtheserialporttouse
-sSPEED,--speedSPEED
baudrate
-c,--continuationcontinuepreviousconnection
-x,--noexitdonotexitfirmwareupdatemode
--ftdiforcerunninginftdimode
--picforcerunninginpicmode
-r,--resetuseEspressifresetmode
HowtousetheParameters
TheCLItoolusesacombinationofglobalandcommandspecificparameters.Theorder
ofparametersisimportanttoavoidambiguity.
10.2CLIUpdater
485
pycom-fwtool-cli[globalparameters][command][commandparameters]
While pycom-fwtool-cli-hshowshelpforglobalparametersandalistofavailable
commands,commandspecificparameterscanbeviewedusing pycom-fwtool-cli
[command]-h
Theparameter -r,--resethasbeenaddedasacourtesyforusersof3rdparty
ESP32products.ThisfunctionalityisnotsupportedbytheExpansionBoard2.0and
maycausethistooltocrashorhangincertaincircumstances.
GlobalParameters
`-h/--help`:showsabovehelp(youcanalsogetdetailedhelpforeachsub-comma
nd
`-v/--verbose`:showverboseoutputfromesptool.
`-d/--debug`:showdebugoutputfromfwtool.
`-q/--quiet`:suppressmostoutput,usedforscripting
`-p/--port`:specifiestheserialporttobeused.Canalsobesetvia**environ
mentvariableESPPORT**
`-s/--speed`:specifiestheserialspeedtobeused.Canalsobesetvia**enviro
nmentvariableESPBAUD**
`-c/--continuation`:continuepreviousconnectioninFTDImode.Thisallowsrunning
multiplecommandssequentiallywithouthavingtoresetthemodule.Thisoptionisign
oredinPICmodeasthemodulecanberesetviatheserialconnection.
`-x/--noexit`:ThiswillpreventthePICfromleavingfirmwareupdatemode.
`--ftdi`:ThiswillforcetheCLIupdatertoruninFTDImode.
`--pic`:ThiswillforcetheCLIupdatertoruninPICmode.
`-r,--reset`:ThiswillforcetheCLIupdatertouseEspressif'sworkaroundtosw
itchintoFirmwareupdatemode.Thisresetmethodisintendedfor3rdpartyhardwareo
nlyandisnotsupportedbytheExpansionBoard2.0
Commands
list
Getlistofavailableserialportsports.
usage:pycom-fwtool-clilist[-h]
optionalarguments:
-h,--helpshowthishelpmessageandexit
Example:OnmacOS:
10.2CLIUpdater
486
$pycom-fwtool-clilist
/dev/cu.usbmodemPy343431[Pytrack][USBVID:PID=04D8:F013SER=Py343434LOCATION=20-2]
/dev/cu.Bluetooth-Incoming-Port[n/a][n/a]
OnWindows:
COM6[Pytrack][USBVID:PID=04D8:F013SER=Py343434LOCATION=20-2]
Thisistheonlycommandthatdoesnotrequireanyadditionalparameters.
Allothercommandsrequirethattheserialportisspecifiedeitherthroughthe -p/
--portoptionorthroughenvironmentvariable ESPPORTYoucanoptionallyspecify
thespeedeitherthrough -s/ --speedorviaenvironmentvariable ESPBAUD.The
defaultspeedis 921600.ThemaximumspeedforreadoperationsonPICbased
expansionboards&shieldsis 230400.Thespeedwillbereducedautomaticallyif
necessary.
SpecialnoteforExpansionBoard2.0
Youwillneedtohaveajumperwireconnectedbetween G23and GNDtouseanyof
thecommandsbelow.Youwillalsoneedtopresstheresetbuttoneitherbefore
runningeachcommandoratleastbeforerunningthefirstcommand.Toavoidhavingto
presstheresetbuttonagainaftereachcommand,youcanusethe -c/ --
continuationoption.ThefirstcommandconnectingtothedeviceMUSTNOTusethe -
c/ --continuationoption.Thisistomakesureaprogramcalled _stub_isuploaded
ontothedevice.This _stub_cannotbeuploadedmorethanonce,soyouneedtotell
theclitoolthatthe _stub_isalreadyrunning,whichisdonethroughusingthe -c/ --
continuationoption.
chip_id
ShowstheuniqueIDoftheESP32ontheconnectedmodule.
usage:pycom-fwtool-cli-pPORTexit[-h]
optionalarguments:
-h,--helpshowthishelpmessageandexit
wmac
10.2CLIUpdater
487
ShowstheWiFiMACoftheconnectedmodule.
usage:pycom-fwtool-cli-pPORTwmac[-h]
optionalarguments:
-h,--helpshowthishelpmessageandexit
smac
ShowstheLPWANMACoftheconnectedmodule.
usage:pycom-fwtool-cli-pPORTsmac[-h]
optionalarguments:
-h,--helpshowthishelpmessageandexit
sigfox
Showsigfoxdetails
usage:pycom-fwtool-cli-pPORTsigfox[-h]
optionalarguments:
-h,--helpshowthishelpmessageandexit
exit
IfaPysense/Pytrack/Expansion3haspreviouslybeenleftinfirmwareupdatemodebyusing
the -xoption,thiscommandcanbeusedtoexitthefirmwareupdatemode.
usage:pycom-fwtool-cli-pPORTexit[-h]
optionalarguments:
-h,--helpshowthishelpmessageandexit
flash
Writesfirmwareimagetoflash,mustbeasa .tar(.gz)fileasprovidedbyPycom.These
filescanbefoundonGitHub.
10.2CLIUpdater
488
usage:pycom-fwtool-cli-pPORTflash[-h][-tTAR]
optionalarguments:
-h,--helpshowthishelpmessageandexit
-tTAR,--tarTARperformtheupgradefromatar[.gz]file
copy
Read/Writeflashmemorypartitionfrom/tolocalfile
usage:pycom-fwtool-cli-pPORT[-h][-pPARTITION][-fFILE][-r][-b]
optionalarguments:
-h,--helpshowthishelpmessageandexit
-pPARTITION,--partitionPARTITION
Thepartitiontoread/write(all,fs,nvs,factory,
secureboot,bootloader,partitions,otadata,fs1,
ota_0,config)
-fFILE,--fileFILEnameofthebinaryfile(default:<wmac>-<part>.bin)
-r,--restorerestorepartitionfrombinaryfile
-b,--backupbackuppartitiontobinaryfile(default)
write
Writetoaspecificlocationinflashmemory.
usage:pycom-fwtool-cli-pPORTwrite[-h][-aADDRESS][--contentsCONTENTS]
optionalarguments:
-h,--helpshowthishelpmessageandexit
-aADDRESS,--addressADDRESS
addresstowriteto
--contentsCONTENTScontentsofthememorytowrite(base64)
wifi
Get/SetdefaultWiFiparameters.
usage:pycom-fwtool-cliwifi[-h][--ssidSSID][--pwdPWD][--wob[WOB]]
optionalarguments:
-h,--helpshowthishelpmessageandexit
--ssidSSIDSetWifiSSID
--pwdPWDSetWifiPWD
--wob[WOB]SetWifionboot
10.2CLIUpdater
489
pybytes
Read/Writepybytesconfiguration.
usage:pycom-fwtool-clipybytes[-h][--tokenTOKEN][--mqttMQTT][--uidUID]
[--nwprefsNWPREFS][--extraprefsEXTRAPREFS]
optionalarguments:
-h,--helpshowthishelpmessageandexit
--tokenTOKENSetDeviceToken
--mqttMQTTSetmqttServiceAddress
--uidUIDSetuserId
--nwprefsNWPREFSSetnetworkpreferences
--extraprefsEXTRAPREFS
Setextrapreferences
Note:Thelocal pybytes_config.jsonfileisoverwrittenwhenmakinganymodifications
usingthiscommand(requiresPybytesfirmware 1.17.5.b6orhigherandFirmware
updater 1.14.3).
cb
Read/Writeconfigblock(LPMAC,SigfoxPAC&ID,etc.).Youcanfindthestructureofthis
blockhere.
usage:pycom-fwtool-cli-pPORTcb[-h][-fFILE][-b][-r]
optionalarguments:
-h,--helpshowthishelpmessageandexit
-fFILE,--fileFILEnameofthebackupfile
-b,--backupbackupcbpartitiontofile
-r,--restorerestorecbpartitionfromfile
Ifneither -bor -risprovided,thecommandwilldefaulttobackup.Ifnofilenameis
provided, <WMAC>.cbisused.
Tobackupyourconfigblock: $pycom-fwtool-cli-pPORTcb
Torestoreyourconfigblock: $pycom-fwtool-cli-pPORTcb-r-fbackup.cb
nvs
Read/Writenon-volatilestorage.
10.2CLIUpdater
490
usage:pycom-fwtool-cli-pPORTnvs[-h][-fFILE][-b][-r]
optionalarguments:
-h,--helpshowthishelpmessageandexit
-fFILE,--fileFILEnameofthebackupfile
-b,--backupbackupcbpartitiontofile
-r,--restorerestorecbpartitionfromfile
Ifneither -bor -risprovided,thecommandwilldefaulttobackup.Ifnofilenameis
provided, <WMAC>.nvsisused.
TobackupyourNVS: $pycom-fwtool-cli-pPORTnvs
TorestoreyourNVS: $pycom-fwtool-cli-pPORTnvs-r-fbackup.nvs
ota
Read/Writeotablock,thiscontainsdatarelatingtoOTAupdatessuchasthehashofthe
OTAfirmware.
usage:pycom-fwtool-cliota[-h][-fFILE][-b][-r]
optionalarguments:
-h,--helpshowthishelpmessageandexit
-fFILE,--fileFILEnameofthebackupfile
-b,--backupbackupcbpartitiontofile
-r,--restorerestorecbpartitionfromfile
Ifneither -bnor -risprovided,thecommandwilldefaulttobackup.Ifnofilenameis
provided, <WMAC>.otaisused.
TobackupyourOTAblock: $pycom-fwtool-cli-pPORTota
TorestoreyourOTAblock: $pycom-fwtool-cli-pPORTota-r-fbackup.ota
lpwan
Get/SetLPWANparameterssavedtonon-volatilestorage.Pleaseseehereformoredetails.
10.2CLIUpdater
491
usage:pycom-fwtool-cli-pPORTlpwan[-h][--regionREGION]
optionalarguments:
-h,--helpshowthishelpmessageandexit
--regionREGIONSetdefaultLORAregion
--erase_regionErasedefaultLORAregion
--lora_regionOutputonlyLORAregion
erase_fs
Eraseflashfilesystemarea.Thisisusefulifsomecoderunningonthedeviceispreventing
accesstotheREPL.
usage:pycom-fwtool-cli-pPORTerase_fs[-h]
optionalarguments:
-h,--helpshowthishelpmessageandexit
erase_all
Eraseentireflash,onlyusethisifyouaresureyouknowwhatyouaredoing.Thiswill
removeyourdeviceslpwanmacaddressesetc.
usage:pycom-fwtool-clierase_all[-h]
optionalarguments:
-h,--helpshowthishelpmessageandexit
10.2CLIUpdater
492
StepsforusingSecureBootandFlash
Encryption
Summary
Inordertoencryptyourfirmware,youwillneedtobuilditfromsource.Ourfirmwaresource
codecanbefoundhere,alongwithinstructionsonhowtobuildit.Belowyouwillfind
specificinstructionsonhowgeneratekeys,buildandflashencryptedfirmware.
1. Obtainkeys(forSecureBootandFlashEncryption)
2. Flashkeysandparametersin efuses
3. Compilebootloaderandapplicationwith makeSECURE=on
4. Flash:bootloader-digestataddress 0x0andencrypted;alltheothers(partitionsand
application)encrypted,too.
Prerequisites
Firstlyyouwillneedtosetupthetoolchainanddownloadthesourcecode.detailed
instructionsonhowtoachievethiscanbefoundhere.Onceyouhavecompletethis,youwill
needtoopenaterminalinthe esp32folderofthefirmwaresourcecoderepo.
NextyouwillneedkeysforFlashEncryptionandSecureBoot;theycanbegenerated
randomlywiththefollowingcommands:
python$IDF_PATH/components/esptool_py/esptool/espsecure.pygenerate_flash_encrypt
ion_keyflash_encryption_key.bin
python$IDF_PATH/components/esptool_py/esptool/espsecure.pygenerate_signing_keys
ecure_boot_signing_key.pem
TheSecureBootkey secure_boot_signing_key.pemhastobetransformedinto secure-
bootloader-key.bin,tobeburntintoefuses.Thiscanbedonein2ways:
python$IDF_PATH/components/esptool_py/esptool/espsecure.pyextract_public_key--k
eyfilesecure_boot_signing_key.pemsignature_verification_key.bin
or,asanartifactofthemakebuildprocess,onthesamedirectorylevelasMakefile
makeBOARD=GPYSECURE=onTARGET=boot
10.3SecureBootandEncryption
493
Toflashthekeys( flash_encryption_key.binand secure-bootloader-key.bin)intothe
efuses(writeandreadprotected)runthefollowingcommands(ignoringthelinesthatstart
with #):
Note:Irreversibleoperations
#BurningEncryptionKey
python$IDF_PATH/components/esptool_py/esptool/espefuse.py--port/dev/ttyUSB0bur
n_keyflash_encryptionflash_encryption_key.bin
#BurningSecureBootKey
python$IDF_PATH/components/esptool_py/esptool/espefuse.py--port/dev/ttyUSB0bur
n_keysecure_bootsecure-bootloader-key.bin
#EnablingFlashEncryptionmechanism
python$IDF_PATH/components/esptool_py/esptool/espefuse.py--port/dev/ttyUSB0bur
n_efuseFLASH_CRYPT_CNT
#ConfiguringFlashEncryptiontousealladdressbitstogetherwithEncryptionke
y(maxvalue0x0F)
python$IDF_PATH/components/esptool_py/esptool/espefuse.py--port/dev/ttyUSB0bur
n_efuseFLASH_CRYPT_CONFIG0x0F
#EnablingSecureBootmechanism
python$IDF_PATH/components/esptool_py/esptool/espefuse.py--port/dev/ttyUSB0bur
n_efuseABS_DONE_0
Ifthekeysarenotwritteninefuse,beforeflashingthebootloader,thenrandomkeys
willbegeneratedbytheESP32,theycanneverbereadnorre-written,sobootloader
canneverbeupdated.Evenmore,theapplicationcanbere-flashed(byUSB)just3
moretimes.
Makefileoptions:
makeBOARD=GPYSECURE=onSECURE_KEY=secure_boot_signing_key.pemENCRYPT_KEY=flash_
encryption_key.binTARGET=[boot|app]
SECURE=onisthemainflag;it'snotoptional
if SECURE=onthefollowingdefaultsareset:
encryptionisenable
secure_boot_signing_key.pemisthesecurebootkey,locatedrelativelytoMakefile
flash_encryption_key.binistheflashencryptionkey,locatedrelativelytoMakefile
Forflashingthebootloaderdigestandtheencryptedversionsofallbinaries:
makeBOARD=GPYSECURE=onflash
Flashing
10.3SecureBootandEncryption
494
Forflashingthe bootloader-reflash-digest.binhastobewrittenataddress0x0,insteadof
the bootloader.bin(ataddress 0x1000).
Buildisdoneusing SECURE=onoption;additionally,allthebinariesarepre-encrypted.
makeBOARD=GPYclean
makeBOARD=GPYSECURE=onTARGET=boot
makeBOARD=GPYSECURE=onTARGET=app
makeBOARD=GPYSECURE=onflash
Manualflashcommand:
python$IDF_PATH/components/esptool_py/esptool/esptool.py--chipesp32--port/dev
/ttyUSB0--baud921600--beforeno_reset--afterno_resetwrite_flash-z--flash_mode
dio--flash_freq80m--flash_sizedetect0x0build/GPY/release/bootloader/bootloader-r
eflash-digest.bin_enc0x8000build/GPY/release/lib/partitions.bin_enc0x10000build/GP
Y/release/gpy.bin_enc_0x10000
OTAupdate
TheOTAshouldbedoneusingthepre-encryptedapplicationimage.
Becausetheencryptionisdonebasedonthephysicalflashaddress,thereare2application
binariesgenerated:
gpy.bin_enc_0x10000whichhastobewrittenatdefaultfactoryaddress: 0x10000
gpy.bin_enc_0x1A0000whichhastobewrittenatthe ota_0partitionaddress
(0x1A0000)
Hint:onMicroPythoninterface,themethod pycom.ota_slot()respondswiththe
addressofthenextOTApartitionavailable(either 0x10000or 0x1A0000).
10.3SecureBootandEncryption
495
MicroPythonLicenseInformation
TheMITLicense(MIT)
Copyright(c)2013-2015DamienP.George,andothers
Permissionisherebygranted,freeofcharge,toanypersonobtainingacopyofthissoftware
andassociateddocumentationfiles(the“Software”),todealintheSoftwarewithout
restriction,includingwithoutlimitationtherightstouse,copy,modify,merge,publish,
distribute,sublicense,and/orsellcopiesoftheSoftware,andtopermitpersonstowhomthe
Softwareisfurnishedtodoso,subjecttothefollowingconditions:
Theabovecopyrightnoticeandthispermissionnoticeshallbeincludedinallcopiesor
substantialportionsoftheSoftware.
THESOFTWAREISPROVIDED“ASIS”,WITHOUTWARRANTYOFANYKIND,
EXPRESSORIMPLIED,INCLUDINGBUTNOTLIMITEDTOTHEWARRANTIESOF
MERCHANTABILITY,FITNESSFORAPARTICULARPURPOSEAND
NONINFRINGEMENT.INNOEVENTSHALLTHEAUTHORSORCOPYRIGHTHOLDERS
BELIABLEFORANYCLAIM,DAMAGESOROTHERLIABILITY,WHETHERINAN
ACTIONOFCONTRACT,TORTOROTHERWISE,ARISINGFROM,OUTOFORIN
CONNECTIONWITHTHESOFTWAREORTHEUSEOROTHERDEALINGSINTHE
SOFTWARE.
Copyright(c)2017,PycomLimited.
ThissoftwareislicensedundertheGNUGPLversion3oranylaterversion,withpermitted
additionalterms.FormoreinformationseethePycomLicencev1.0documentsuppliedwith
thisfile,oravailableathttps://www.pycom.io/opensource/licensing
11.1License
496