TheThingsNetwork / arduino-device-lib

Arduino Library for TTN Devices
MIT License
206 stars 96 forks source link

Added support for SAMR34-based boards #286

Open danalvarez opened 1 year ago

danalvarez commented 1 year ago

Based on my TTN forum post

I have recently been tinkering with a WLR089 Xplained Pro board, which is based on the SAMR34. This new LoRa modem is intented to be used as a standalone microcontroller + radio solution from Microchip, but I found Microchip also released a firmware for the modem in which the standard ASCII commands used for the RN2xx3 chips can be used to control it. It’s called the RN parser.

Since the RN parser firmware largely emulates the behaviour of the RN2xx3 modules, this PR adds support for the SAMR34 to this library.

Changes

The main changes to this library to add SAMR34 support are listed below. These have also been updated in the documentation in docs/TheThingsNetwork.md.

  1. Added the TTN_HEX_CHAR_DETECT_CASE macro, because downlinks in the SAMR34 firmware are sent with lower-case ASCII, while the RN2xx3 uses upper case.
  2. Added SAMR34 to compare_table, to be used when checking a valid module is connected
  3. Added sys_sleep_standby to sys_table, because SAMR34 is sent to sleep by issuing sys sleep stansby <ms>, instead of just sys sleep <ms> as in RN2xx3.
  4. Added the macReset command, which was not implemented before and is necessary with SAMR34 because a mac reset must be issued to start the LoRaWAN stack on power on.
    1. Added all possible frequency plans to mac_reset_table
  5. Modified showStatus() to not show the battery voltage and APPEUI when working with a SAMR34, because these commands are not implemented in the RN parser firmware
    1. A complete list of the implemented commands is available in the Command User Guide for the RN parser firmware
  6. Added a check for the SAMR34 in checkValidModuleConnected()
  7. Modified sleep() to send sys sleep standby <ms> for SAMR34 boards, still backwards compatible with RN2xx3
  8. Modified wake() to take a pin as argument when working with SAMR34, because this module is not woken up via autoBaud() but rather via an external pin interrupt (more info here). Still backwards compatible with RN2xx3.

Tested commands

Here is a list of the commands I have personally tested with the WLR089 module:

mac reset <band>
mac set adr <state>
mac set devaddr <address>
mac set nwkskey <nwksesskey>
mac set appskey <appsesskey>
mac set ch status <channelID> <status>
mac set ch drrange <channelID> <minRange> <maxRange>
mac set dr <dataRate>
mac set pwridx <pwrIndex>
mac set retx <reTxNb>
mac join abp
mac tx uncnf <port> <data>
mac get deveui
mac get dr
mac get rxdelay1
mac get rxdelay2
sys sleep standby <length>
sys get hweui

Some Final Notes

  1. I ensured backwards compatibility with RN2xx3 in the functions that were modified, so this should continue to be compatible with RN2xx3 without any changes to user code.
  2. For the WLR089, I am using the MLS 1_0_P_6 (Parser_ECC608) firmware contained here, since several bugs that made the firmware unusable where fixed for this release. And I manually modified the baud rate for the firmware in the conf_sio2host.h file and set it to 9600, since no autobaud functionallity exists in the RN Parser firmware. I am using AltSoftSerial to communicate with the modem in an Arduino Pro Mini.
CLAassistant commented 1 year ago

CLA assistant check
All committers have signed the CLA.

jpmeijers commented 1 year ago

This sounds great. @johanstokking what do you think about this? Do we want to include support in our library?

I should have an SAMR34 devkit somewhere on which I can test this to confirm before merging.

jpmeijers commented 1 year ago

Default baud rate of RN2xx3 (and this library): 57600 Default baud rate of RN parser: 115200 Baud rate for Software Serial to work correctly: 9600

I can't get this to work yet. The SAMR34 keeps on replying with busy and invalid param and keys not set.

Test setup:

SendOTAA output:

6:18:53.955 -> -- STATUS
16:18:53.955 -> EUI: 000425191801d600
16:18:53.955 -> Battery: invalid_param
16:18:53.970 -> AppEUI: invalid_param
16:18:53.970 -> DevEUI: 0000000000000000
16:18:53.970 -> Data Rate: 0
16:18:53.970 -> RX Delay 1: 0
16:18:53.970 -> RX Delay 2: 0
16:18:53.970 -> -- JOIN
16:18:55.424 -> Model: SAMR34
16:18:55.424 -> Version: Xpro
16:18:55.424 -> Sending: mac set deveui 000425191801d600
16:18:55.424 -> Response is not OK: busy
16:18:55.424 -> Sending: mac set adr off
16:18:55.424 -> Response is not OK: busy
16:18:55.424 -> Sending: mac set deveui 000425191801d600
16:18:55.424 -> Response is not OK: busy
16:18:55.424 -> Sending: mac set appeui 000425191801D600
16:18:55.424 -> Response is not OK: invalid_param
16:18:55.424 -> Sending: mac set appkey 3E57A97C821ECA81AF393801B58DE31F
16:18:55.424 -> Response is not OK: busy
16:18:55.424 -> Sending: mac save 
16:18:55.424 -> Sending: mac set rx2 3 869525000
16:18:55.424 -> Response is not OK: busy
16:18:55.424 -> Sending: mac set ch drrange 1 0 6
16:18:55.457 -> Response is not OK: busy
16:18:55.457 -> Sending: mac set ch dcycle 0 299
16:18:55.457 -> Response is not OK: invalid_param
16:18:55.457 -> Sending: mac set ch dcycle 1 299
16:18:55.457 -> Response is not OK: invalid_param
16:18:55.457 -> Sending: mac set ch dcycle 2 299
16:18:55.457 -> Response is not OK: invalid_param
16:18:55.457 -> Sending: mac set ch freq 3 867100000
16:18:55.457 -> Response is not OK: busy
16:18:55.457 -> Sending: mac set ch drrange 3 0 5
16:18:55.457 -> Response is not OK: busy
16:18:55.457 -> Sending: mac set ch dcycle 3 499
16:18:55.457 -> Response is not OK: invalid_param
16:18:55.457 -> Sending: mac set ch status 3 on
16:18:55.457 -> Response is not OK: busy
16:18:55.457 -> Sending: mac set ch freq 4 867300000
16:18:55.457 -> Response is not OK: busy
16:18:55.457 -> Sending: mac set ch drrange 4 0 5
16:18:55.457 -> Response is not OK: busy
16:18:55.457 -> Sending: mac set ch dcycle 4 499
16:18:55.490 -> Response is not OK: invalid_param
16:18:55.490 -> Sending: mac set ch status 4 on
16:18:55.490 -> Response is not OK: busy
16:18:55.490 -> Sending: mac set ch freq 5 867500000
16:18:55.490 -> Response is not OK: busy
16:18:55.490 -> Sending: mac set ch drrange 5 0 5
16:18:55.490 -> Response is not OK: busy
16:18:55.490 -> Sending: mac set ch dcycle 5 499
16:18:55.490 -> Response is not OK: invalid_param
16:18:55.490 -> Sending: mac set ch status 5 on
16:18:55.490 -> Response is not OK: busy
16:18:55.490 -> Sending: mac set ch freq 6 867700000
16:18:55.490 -> Response is not OK: busy
16:18:55.490 -> Sending: mac set ch drrange 6 0 5
16:18:55.490 -> Response is not OK: busy
16:18:55.490 -> Sending: mac set ch dcycle 6 499
16:18:55.490 -> Response is not OK: invalid_param
16:18:55.490 -> Sending: mac set ch status 6 on
16:18:55.490 -> Response is not OK: busy
16:18:55.490 -> Sending: mac set ch freq 7 867900000
16:18:55.629 -> Response is not OK: busy
16:18:55.629 -> Sending: mac set ch drrange 7 0 5
16:18:55.629 -> Response is not OK: busy
16:18:55.629 -> Sending: mac set ch dcycle 7 499
16:18:55.629 -> Response is not OK: invalid_param
16:18:55.629 -> Sending: mac set ch status 7 on
16:18:55.629 -> Response is not OK: busy
16:18:55.629 -> Sending: mac set pwridx 1
16:18:55.629 -> Response is not OK: busy
16:18:55.629 -> Sending: mac set retx 7
16:18:55.629 -> Response is not OK: busy
16:18:55.629 -> Sending: mac set dr 5
16:18:55.629 -> Response is not OK: busy
16:18:55.629 -> Sending: mac join otaa 
16:18:55.629 -> Response is not OK: keys_not_init
16:18:55.629 -> Send join command failed
16:19:05.519 -> Sending: mac join otaa 
16:19:05.519 -> Response is not OK: keys_not_init
16:19:05.519 -> Send join command failed
16:19:15.541 -> Sending: mac join otaa 
16:19:15.541 -> Response is not OK: keys_not_init
16:19:15.541 -> Send join command failed
16:19:25.532 -> Sending: mac join otaa 
16:19:25.532 -> Response is not OK: keys_not_init
16:19:25.532 -> Send join command failed
jpmeijers commented 1 year ago

The problems I'm seeing is related to the required mac reset after startup of the SAMR34. I've added ttn.macReset() calls in my test sketches, but those print Response is not OK: invalid_param in the serial console.

@danalvarez I would recommend that you add an example sketch to this library that shows how to initialise and use the SAMR34 running RN parser. It seems that this module is just enough different from the RN2xx3 that the existing example sketches won't work out of the box.

danalvarez commented 1 year ago

@jpmeijers Thank you for testing this. Indeed, the library's default modemType is TTN_MODEM_TYPE_RN. This will make several of the function calls fail if you are using SAMR34. You must first call checkValidModuleConnected() so that the correct modemType is set, and then all other functions behave correctly. You must also call macReset() if you are using SAMR34, to init the LoRaWAN stack.

It is also important not to soft reset the module when performing a call personalize() or provision() in SAMR34, as this would require you to call macReset() again. personalize() and provision() do this by default, so I have added checks for this.

I also noted that some commands (namely: mac set class <class> and mac set appeui <appeui>) are implemented differently in the RN parser firmware: as mac set edclass <class> and mac set joineui <appeui>, respectively. I've added checks for this in setClass(), getAppEui(), showStatus() and provision().

I have added steps in the setup() of DeviceInfo.ino to show how to initialise the SAMR34 (this is backwards compatible with RN2xx3). I have also updated SendABP.ino, SendOTAA.ino, and Receive.ino to work with both SAMR34 and RN2xx3.

I have also updated the documentation to reflect these changes.

Let me know if you have any questions or suggestions.

PS

Note that you can chage the default baud rate of the RN parser firmware by editing the conf_sio2host.h file. This way, you can use software serial to communicate with the SAMR34 in an Uno (I have tested using AltSoftSerial @ 9600 baud, but I assume SoftwareSerial should work as well.).

danalvarez commented 1 year ago

Hello @jpmeijers , do you think you might have a chance to test this? I've addressed your change requests. :)

danalvarez commented 1 year ago

Bump

jpmeijers commented 1 year ago

Yes, will hopefully get to this in the coming week(end). Was in Europe for 3 weeks for the conference.

jpmeijers commented 1 year ago

I'm still facing some issues. At startup the DeviceInfo sketch hangs for 30 seconds trying to read the EUI from the SAMR34.

Another thing that I do not like is all the extra custom code that is added to the examples. The API needs to be simple to use, but with all these changes it is becoming quite complicated and unclear what is needed. The only way to solve this is to move all init code into a single init function that can play the role of single entry point, which is called in setup(). Depending on which module is detected the init function can run the required reset/init code.

To be honest I'm starting to think adding SAMR34 support to this repo is not worth it. Maybe we should rather keep this support in a separate repo, like under @danalvarez's account.

DeviceInfo.ino output

14:48:46.205 -> Model: SAMR34
14:48:46.205 -> Valid module connected.
14:48:46.205 -> Device Information
14:48:46.205 -> 
14:49:16.214 -> No response from RN module.
14:49:16.214 -> EUI: ok
14:49:16.214 -> AppEUI: invalid_param
14:49:16.214 -> DevEUI: 000425191801d600
14:49:16.214 -> Data Rate: 3
14:49:16.214 -> RX Delay 1: 1000
14:49:16.248 -> RX Delay 2: 2000
14:49:16.248 -> 
14:49:16.248 -> Use the EUI to register the device for OTAA
14:49:16.248 -> -------------------------------------------
14:49:16.248 -> 
14:49:26.240 -> Device Information
14:49:26.240 -> 
14:49:26.240 -> EUI: 000425191801d600
14:49:26.240 -> AppEUI: 0000000000000000
14:49:26.240 -> DevEUI: 000425191801d600
14:49:26.240 -> Data Rate: 3
14:49:26.240 -> RX Delay 1: 1000
14:49:26.240 -> RX Delay 2: 2000
14:49:26.240 -> 
14:49:26.240 -> Use the EUI to register the device for OTAA
14:49:26.240 -> -------------------------------------------
14:49:26.240 -> 

Sniffing SAMR34 output:

[14:48:46:084] invalid_param␍␊
[14:48:46:086] SAMR34 Xpro MLS_SDK_1_0_P_6 Sep  4 2022 15:28:58␍␊
[14:48:46:187] SAMR34 Xpro MLS_SDK_1_0_P_6 Sep  4 2022 15:28:58␍␊
[14:48:46:202] ok␍␊
[14:49:16:206] invalid_param␍␊
[14:49:16:209] 000425191801d600␍␊
[14:49:16:212] 3␍␊
[14:49:16:214] 1000␍␊
[14:49:16:217] 2000␍␊
[14:49:26:219] 000425191801d600␍␊
[14:49:26:223] 0000000000000000␍␊
[14:49:26:227] 000425191801d600␍␊
[14:49:26:229] 3␍␊
[14:49:26:231] 1000␍␊
[14:49:26:233] 2000␍␊