Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: Code that works for testing 2x Lora Vision Shields #87

Closed
hpssjellis opened this issue Mar 1, 2021 · 29 comments
Closed

Comments

@hpssjellis
Copy link

@akash73

I am having troubles getting my 3 Lora Vision Shields working in North America.
Any code or suggestions would be appreciated but I think my biggest issue is my gateways are not stable. (I will probably drive the 40 km and do some testing where there are more gateways).

The other issue seems to be just less North American testing.

It would be really good if we could do some point-to-point testing with the Vision Shields. The https://github.com/sandeepmistry/arduino-LoRa library looks promising but I can't even get the MRKWAN DumbModemLoraSender program working. (Looks like it is directly from the sandeemistry library.)

Any suggestions for connecting the Semtech module up correctly? I might eventually be able to access all 160 pins on the PortentaH7 so direct connections might be a possibility in the near future. I just need to know more information about what needs to be connected.

I have posted a similar issue with the sandeepmistry LoRa Library

@facchinm
Copy link
Contributor

facchinm commented Mar 9, 2021

Hi Jeremy,
the "dumb" mode only works for SAMD boards (MKRWAN13x0) since they share SPI and UART pins. One way to bypass the issue is by using this core https://github.com/GrumpyOldPizza/ArduinoCore-stm32l0 and this patch GrumpyOldPizza/ArduinoCore-stm32l0#57 to directly write the Murata module firmware. When doing so the SAMD (or STM32 in the Portenta) can communicate with the module using the standard serial port and you can avoid the LoraWAN stack and talk directly with the radio.

In the meantime, I'm setting up a new API to allow manually changing the channel mask, overriding the default configuration (arduino/mkrwan1300-fw@9479bb9). This would allow sending messages via single channel "gateways" (like ESP32 with LoRa radio)

Hope it helps!

@hpssjellis
Copy link
Author

Thank you so much @facchinm for looking into this. I have got my LoRanWan Vision Shield connecting in North America on the https://explorer.helium.com/coverage network. I contacted their devs who have purchased the board with a portenta and will try to add Helium support in their arduino LongFi library.

For point-to-point LoRa I am not really sure how to use https://github.com/GrumpyOldPizza/ArduinoCore-stm32l0 with the patch but the LoRa ping/pong example looks exactly what I want. Not really sure what board would work. See Image below.

I will probably wait for you to have something from Arduino that I can test.

image

@giulcioffi
Copy link
Contributor

Hi @hpssjellis, PR #90 adds new APIs to enable/disable channels. Could you please try them and give us some feedback? Thanks!

@hpssjellis
Copy link
Author

hpssjellis commented Mar 17, 2021

@giulcioffi . I would really like to help test these. Controlling the channel mask should be helpful. Do you have any links to example programs I can try? I really appreciate you working on this.

.

I made a quick attempt to print information but had no luck. Does the channel information need a live connection, I don't think so? Notice I had no printout from getChannelMask.

image

@giulcioffi
Copy link
Contributor

giulcioffi commented Mar 18, 2021

Sorry, the firmware binary was not updated...I just pushed a new commit in PR #90 with the updated firmware. Please upload the example MKRWANFWUpdater_standalone with the new binary to update the firmware.
Then, to test the new APIs, an example sketch could be the following. Remember to call modem.begin() with your region, before everything else.

#include <MKRWAN.h>

LoRaModem modem;

void setup() {
  Serial.begin(115200);
  while (!Serial);
  
  if (!modem.begin(EU868)) {
    Serial.println("Failed to start module");
    while (1) {}
  };

  Serial.println("getChannelMask: " + String(modem.getChannelMask()));

  Serial.println("isChannelEnabled(0): " + String(modem.isChannelEnabled(0)));
  Serial.println("isChannelEnabled(1): " + String(modem.isChannelEnabled(1)));
  Serial.println("isChannelEnabled(2): " + String(modem.isChannelEnabled(2)));
  Serial.println("isChannelEnabled(3): " + String(modem.isChannelEnabled(3)));
  Serial.println("isChannelEnabled(4): " + String(modem.isChannelEnabled(4)));

  modem.disableChannel(1);
  modem.enableChannel(4);

  Serial.println("get new ChannelMask: " + String(modem.getChannelMask()));
}

void loop() {

}

@hpssjellis
Copy link
Author

@giulcioffi that worked better. Using this code

#include <MKRWAN.h>

LoRaModem modem;

void myPrintMask(){
 
  Serial.println("Your module version is: " + String(modem.version()) );
  Serial.println("getDataRate: " + String(modem.getDataRate()) );
  Serial.println("getADR: " + String(modem.getADR()) );
  Serial.println("getRX2Freq: " + String(modem.getRX2Freq()) );
  Serial.println("getRX2DR(): " + String(modem.getRX2DR()) );
   
  Serial.println("getDevAddr: " + String(modem.getDevAddr()) );
  Serial.println("getNwkSKey: " + String(modem.getNwkSKey()) );
  Serial.println("getAppSKey: " + String(modem.getAppSKey()) );
  Serial.println("getFCU: " + String(modem.getFCU()) );
  Serial.println("getFCD: " + String(modem.getFCD()) );
  Serial.println("getChannelMask: " + String(modem.getChannelMask()));
  
  Serial.println("isChannelEnabled(0): " + String(modem.isChannelEnabled(0)));
  Serial.println("isChannelEnabled(1): " + String(modem.isChannelEnabled(1)));
  Serial.println("isChannelEnabled(2): " + String(modem.isChannelEnabled(2)));
  Serial.println("isChannelEnabled(3): " + String(modem.isChannelEnabled(3)));
  Serial.println("isChannelEnabled(4): " + String(modem.isChannelEnabled(4)));
  Serial.println("isChannelEnabled(5): " + String(modem.isChannelEnabled(5)));
  Serial.println("isChannelEnabled(6): " + String(modem.isChannelEnabled(6)));
  Serial.println("-------------------------------");
}

void setup() {
  Serial.begin(115200);
  while (!Serial);
  
  if (!modem.begin(US915)) {
    Serial.println("Failed to start module");
    while (1) {}
  };

  Serial.println("For modem.begin(US915)");

  Serial.println("Now Showing default Channels ");
  myPrintMask();

  Serial.println("Now Disabling all channels and enable channel 2 ");
  modem.disableChannel(0);
  modem.disableChannel(1);
  modem.enableChannel(2);
  modem.disableChannel(3);
  modem.disableChannel(4);
  modem.disableChannel(5);
  modem.disableChannel(6);
  myPrintMask(); 

  
  Serial.println("Now enable all channels except 2");
  modem.enableChannel(0); 
  modem.enableChannel(1); 
  modem.disableChannel(2); 
  modem.enableChannel(3); 
  modem.enableChannel(4); 
  modem.enableChannel(5); 
  modem.enableChannel(6); 
  myPrintMask(); 

}

void loop() {

}

I got these results

For modem.begin(US915)
Now Showing default Channels 
Your module version is: ARD-078 1.2.3
getDataRate: 0
getADR: 1
getRX2Freq: 923300000
getRX2DR(): 8
getDevAddr: 00000000
getNwkSKey: 00000000000000000000000000000000
getAppSKey: 00000000000000000000000000000000
getFCU: 0
getFCD: 0
getChannelMask: ffffffffffffffff00ff0000
isChannelEnabled(0): 1
isChannelEnabled(1): 1
isChannelEnabled(2): 1
isChannelEnabled(3): 1
isChannelEnabled(4): 1
isChannelEnabled(5): 1
isChannelEnabled(6): 1
-------------------------------
Now Disabling all channels and enable channel 2 
Your module version is: ARD-078 1.2.3
getDataRate: 0
getADR: 1
getRX2Freq: 923300000
getRX2DR(): 8
getDevAddr: 00000000
getNwkSKey: 00000000000000000000000000000000
getAppSKey: 00000000000000000000000000000000
getFCU: 0
getFCD: 0
getChannelMask: ff84ffffffffffff00ff0000
isChannelEnabled(0): 0
isChannelEnabled(1): 0
isChannelEnabled(2): 1
isChannelEnabled(3): 0
isChannelEnabled(4): 0
isChannelEnabled(5): 0
isChannelEnabled(6): 0
-------------------------------
Now enable all channels except 2
Your module version is: ARD-078 1.2.3 ARD-078
getDataRate: 1
getADR: 0
getRX2Freq: 1
getRX2DR(): 923300000
getDevAddr: 8
getNwkSKey: 00000000
getAppSKey: 00000000000000000000000000000000
getFCU: 0
getFCD: 0
getChannelMask: 0
isChannelEnabled(0): 1
isChannelEnabled(1): 1
isChannelEnabled(2): 0
isChannelEnabled(3): 1
isChannelEnabled(4): 1
isChannelEnabled(5): 1
isChannelEnabled(6): 1
-------------------------------


Possibly the default channelmask should be saved as it looks like it gets lost if you disable all the channels.

P.S. How would code look to use only one channel to allow 2 Portenta's with the Lora Vision Shield to communicate?

@giulcioffi
Copy link
Contributor

Hi @hpssjellis, thank you for pointing out this failure on Portenta. getChannelMask() was sometimes failing during the series of channel enabling/disabling operations...I now pushed a commit that should fix this issue.
About the communication between 2 Portenta with the Lora Vision Shield, this will need some additional development since you will need to move from LoraWAN to Lora protocol. You can do this by using a single-channel gateway and the provided APIs.

@hpssjellis
Copy link
Author

@giulcioffi That is great. I thought it didn't work but then I ran the updater and my code worked great. Here is the new output.

For modem.begin(US915)
Now Showing default Channels 
Your module version is: ARD-078 1.2.3
getDataRate: 0
getADR: 1
getRX2Freq: 923300000
getRX2DR(): 8
getDevAddr: 00000000
getNwkSKey: 00000000000000000000000000000000
getAppSKey: 00000000000000000000000000000000
getFCU: 0
getFCD: 0
getChannelMask: ffffffffffffffff00ff0000
isChannelEnabled(0): 1
isChannelEnabled(1): 1
isChannelEnabled(2): 1
isChannelEnabled(3): 1
isChannelEnabled(4): 1
isChannelEnabled(5): 1
isChannelEnabled(6): 1
-------------------------------
Now Disabling all channels and enable channel 2 
Your module version is: ARD-078 1.2.3
getDataRate: 0
getADR: 1
getRX2Freq: 923300000
getRX2DR(): 8
getDevAddr: 00000000
getNwkSKey: 00000000000000000000000000000000
getAppSKey: 00000000000000000000000000000000
getFCU: 0
getFCD: 0
getChannelMask: ff84ffffffffffff00ff0000
isChannelEnabled(0): 0
isChannelEnabled(1): 0
isChannelEnabled(2): 1
isChannelEnabled(3): 0
isChannelEnabled(4): 0
isChannelEnabled(5): 0
isChannelEnabled(6): 0
-------------------------------
Now enable all channels except 2
Your module version is: ARD-078 1.2.3
getDataRate: 0
getADR: 1
getRX2Freq: 923300000
getRX2DR(): 8
getDevAddr: 00000000
getNwkSKey: 00000000000000000000000000000000
getAppSKey: 00000000000000000000000000000000
getFCU: 0
getFCD: 0
getChannelMask: fffbffffffffffff00ff0000
isChannelEnabled(0): 1
isChannelEnabled(1): 1
isChannelEnabled(2): 0
isChannelEnabled(3): 1
isChannelEnabled(4): 1
isChannelEnabled(5): 1
isChannelEnabled(6): 1
-------------------------------


If you can think of some code to test point to point that would be really useful. I will be testing my own ideas based on sandeepmistrys lora, but using your channel masks

@facchinm
Copy link
Contributor

@hpssjellis unfortunately the mask is not enough for point to point communication; you can use it to talk with a low cost, single channel gateway (eg. an ESP32 with Semtech radio) that will transparenly forward the data to the cloud.
LoraWAN encryption schemes are compulsory, so the "gateway" board will just receive garbage.
Moreover, the gateway must be able to communicate directly to the radio chip, so we are back to square one (no way to do it using Portenta HW).
The only way to exploit P2P is by writing a very custom firmware for the Murata module, taking this as a starting point.

@hpssjellis
Copy link
Author

Just checking, @facchinm and @giulcioffi . The Portenta vision shield LoRa hardware limitations, are they simplified with the Breakout board, which does give access to some of the lora chip pins?

Also if I am stuck with Murata chip programming, I would give it a try, I just need a few examples to get started.

@facchinm
Copy link
Contributor

So, I just tested a possible procedure and I think it could work for you 🙂

  1. download this core https://github.com/facchinm/ArduinoCore-stm32l0/tree/vision_shield (vision_shield branch) in your sketchbook/hardware folder (eg. with cd $sketchbook/hardware/mycores && git clone https://github.com/facchinm/ArduinoCore-stm32l0 -b vision_shield)
  2. Upload the attached sketch to your Portenta PortentaLoRaBridge-210323a.zip
  3. Select "Arduino Portenta Vision Shield" from "Tlera Corp STM32L0 Boards" board entry
  4. Upload any sketch after selecting the Portenta serial (this won't overwrite the sketch running on Portenta)
  5. I used LoRa_Callbacks example from inside the core and it works great, ping-ponging data between two boards.

Let me know if you need any help!

@hpssjellis
Copy link
Author

@facchinm Martino, I really like where this is going.

I have an error running on windows. (I installed the Tlera board then replaced the board code with your repository. Not sure if that is the best method. )

image

@facchinm
Copy link
Contributor

Almost there 😄 The PortentaLoRaBridge sketch should be flashed on the Portenta, so you should select Portenta H7 M7 as target. All the other sketches than will run on the Murata if compiled for Vision Shield 😉

@hpssjellis
Copy link
Author

That makes sense but @facchinm I am getting same error using either the M7 or M4 core. Are you running a newer than 1.3.2 mbed board? Where would I find the Class Uart to check?

@facchinm
Copy link
Contributor

Ah yes, I'm using an unreleased version of mbed core... You can either use the git version or just wait a bit until we release (hint, will happen soon 😉 )

@hpssjellis
Copy link
Author

@facchinm Sounds good. I will wait. Thank you so much for looking into this. Your my new Tech Hero.

@facchinm
Copy link
Contributor

facchinm commented Apr 8, 2021

@hpssjellis core 2.0.0 is live and released, so now the sketch should compile just fine 🙂
The release notes are here https://github.com/arduino/ArduinoCore-mbed/releases/tag/2.0.0 if you want to take a look!

@hpssjellis
Copy link
Author

@facchinm That is big news. Yes I will be testing everything and making more Portenta Videos.

P.S. I am making a Portenta Arduino IDE Library with a bugs folder as I find any. I will also post issues as appropriate.

https://github.com/hpssjellis/portenta-pro-community-solutions/tree/main/examples/z-portenta-bugs

@hpssjellis
Copy link
Author

@facchinm are you on a Mac on Linux machine? I am having a few serial port issues that look linux based

/dev/ttyS0

I will test from my ubuntu machine tonight. Couple of questions:

  1. Do I need an up-to-date MKRWAN library to run MKRWANFWUpdate_standalone? (I don't think so)

  2. After running PortentaLoRaBridge using Portenta M7 it looks like you don't double hit the board button to put into bootloader mode. Just keep flashing Tlera code to the board. (I think that is Correct)

  3. Everything seems to be fine, just have to get Serial Print running. For now I will try to just use LED's to test.

@hpssjellis
Copy link
Author

hpssjellis commented Apr 9, 2021

@facchinm Works great on Ubuntu. Ping pong switching master etc. Very impressive.
image

What is the plan if you can get this working on windows? Can this be made as part of the MBED core or would you push a PR to https://github.com/GrumpyOldPizza/ArduinoCore-stm32l0 ?

@hpssjellis
Copy link
Author

@facchinm from a memory allocation point of view does this make any sense to you? I have my 2 Portenta LoRa shields Ping and Ponging each other, I then put a normal Machine Learning program on one of the Portenta boards using the normal arduino method. On bootup the boards still ping and pong, even though the machine learning program also runs! If I then clean both the M7 and M4 cores of the that board, it still Ping and Pongs with the original when powered. If I shut down the cleaned board, the Ping Pong stops. Weird.

Basically really resilient. I can't stop it from being able to ping/pong. Any idea how to clean it? I even fired up OpneMV and it still ping/pongs but only when powered.

If I load your Tlera core, I can flash a blank program which stops the 2nd board from ping/pong. Has your Tlera Core created a permanent thread like a virtual 3rd core?

@facchinm
Copy link
Contributor

Super happy you made it working 🎉 !
Basically, the Tlera Core flashes directly the STM32L0 in the murata module, so unless you keep the module under reset, the sketch flashed on that core will keep running 🙂
The "right" way to do this would be adding an RPC like interface to both the L0 and the H7 (using a library like https://github.com/openmv/openmv-arduino-rpc with SerialLora as transport) and trigger the LoRa functionality on demand.
Let me know if you need any help in doing this 😉

@hpssjellis
Copy link
Author

I will look into the RPC library as I need to get information from the M7 core to the murata module, thank you @facchinm.

One quick question: On the MKRWAN library the DevEui was generated by the library. In the GrumpyOldPizza library there does not seem to be that ability. Do I just let TTN determine the DevEui?

@facchinm
Copy link
Contributor

Sure, DevEUI is a sorf of mac address, so you shouldn't join the same network with two boards sharing it. TTN takes care there's no duplicate when they assign it so it's all fine 😉

@hpssjellis
Copy link
Author

@facchinm just an update here. I seem to be able to communicate with the murata module from the Portenta using UART3. That seems to be connected to the murata module regular Serial. Still testing if I can send data using UART3 to the murata module.

#include "mbed.h"

UART mySerial3(PJ_8,  PJ_9,  NC, NC);


// in the main loop from the portenta

  if (mySerial3.available()) {    
     Serial.write(mySerial3.read());  
  }

@hpssjellis
Copy link
Author

@facchinm I had this bright idea to fork your version of the grumpyOldPizza library at https://github.com/facchinm/ArduinoCore-stm32l0 add several Portenta Specific examples here and then submit a PR back to grumpyOldPizza to include in his library.

Unfortunately I have just clued in that your fork is very raw and not at all ready for a PR back to the master. It is probably a fair bit of work to make it ready and that is a waste of your time. I thrive on wasting time.

You have basically just changed:

boards.txt

and the

B-L072Z-LRWAN1 variant.cpp file for each of the Arduino boards.

Is there anything else you changed or is that it? Is this something you would eventually submit as a PR or somehow include with the Arduino MBED boards or is this something I might be able to submit as a PR to grumpOldPizza? It looks like I just have to make a B-L072Z-LRWAN1 folder for each of the Arduino boards and then use your board.txt file and link everything to the new folders.

@hpssjellis
Copy link
Author

@giulcioffi , @facchinm your version of the grumpyOldPizza library is very cool, any chance it will ever bit a bit more mainstream and give support for all the arduino mbed devices?

I am having a lot of success with both Portenta P2P and LoRaWan, my plan is to make a P2P system which switches to the LoRaWan system when needed. My proof of concept is running. Unfortunately the Murarta module memory seems to die at 0x08010000 is there any way to give it a bit more space?

@hpssjellis
Copy link
Author

hpssjellis commented Dec 17, 2021

I would like to distribute to friends my .bin or .dfu files made using @facchinm version of the GrumpyOldPizza Tlera board. Does anyone know how to upload these files to the Portenta from the command line on windows. The problem is going to be getting them to load to the correct memory location and if I can just use a regular arduino uploader?

Here is the load command that my linux computer generated


/root/Arduino/hardware/mycores/ArduinoCore-stm32l0-vision_shield/tools/linux/stm32flash /dev/ttyACM0 -e 512 -b 2400 -w /tmp/arduino_build_519314/mySketchName.ino.dfu
stm32flash 0.5

Developing with LoRaWan is incredibly frustrating as you always have to rely on other peoples gateways. What @facchinm has got working with LoRa is very exciting.

It is much too hard to teach others how to work with the GrumpOldPizza method, which as far as I can tell needs a linux computer but giving people my code would work fine.

Seems to be some information here in the installation folder for windows

@echo off
set count=1
:wait
    "%~dp0\dfu-util.exe" -l -d 0483:df11 | findstr "Found" >NUL 2>&1
    if %errorlevel% == 0 ( 
	"%~dp0\dfu-util.exe" -d %1:%2,0x0483:0xdf11 -a 0 -s 0x08000000:leave -D %3
    ) else (
        if %count% gtr 10 goto break 
        echo %count%
        set /A count+=1
        ping -n 1 127.0.0.1 >NUL
        goto :wait
    )
)

:break


Whereas on my window machine the code looks something like

C:\Users\myUser.name\AppData\Local\Arduino15\packages\arduino\tools\dfu-util\0.10.0-arduino1/dfu-util --device 0x2341:0x035b -D C:\Users\myUser~ful.name\AppData\Local\Temp\arduino_build_538244/sketch_dec17a.ino.bin -a0 --dfuse-address=0x08040000:leave 
dfu-util 0.10-dev

Can someone take the above windows command and adapt it to upload the GrumpOldPizza binary.dfu file ?

P.S. I assume dfu-util can take both .bin and .dfu files.

.

So I tried this command on the windows dos prompt after moving the linux .dfu file into my downloads folder


C:\Users\myUser.name\AppData\Local\Arduino15\packages\arduino\tools\dfu-util\0.10.0-arduino1/dfu-util  -d 512:2400,0x0483:0xdf11    -D C:\Users\myUser.name\Downloads\arduino_build_519314\arduino_build_519314/v0.4.0-send-ok-E.ino.dfu -a 0 -s 0x08000000:leave

Not really sure if the Portenta should be in boot mode or regular mode as on the linux computer we install a bridge file to the portenta and then run grumpyOldPizza. I will try to test out if my command line is working.

Also downloaded onto windows stm32flash and tried

stm32flash COM5 -e 512 -b 2400 -w "C:\Users\myUser.name\Downloads\arduino_build_519314\arduino_build_519314/v0.4.0-send-ok-E.ino.dfu"

@hpssjellis
Copy link
Author

@facchinm I think you might be proud of me.

Looks like if I install xxd and run

echo -n "const " > fw.h && xxd -i myGrumpyCompiledFile.dfu >> fw.h

and replace the following file:

https://github.com/arduino-libraries/MKRWAN/blob/master/examples/MKRWANFWUpdate_standalone/fw.h

I can convert my GrumpyOldPizza .dfu files made on a linux computer to a header file then change the 2 variables to the following:

const unsigned char mlm32l07x01_bin[] 
unsigned int mlm32l07x01_bin_len 

and using a windows computer and the program MKRWANFWUpdate_standalone with the new fw.h file looks like it loads onto the Portenta Boards from a windows computer. In my case I can publish the fw.h files to my students who don't have linux computers. (95% of them don't have linux computers)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants