Using Particle Mesh Devices with the OpenThread Border Router


#63

@bsatrom

That sounds so great. Don’t stop with Zigbee, lets connect the Particle Mesh hardware to as many platforms as possible. It is a win-win for everyone. Keep me in the loop, especially if you have any problems. Also nice if some of the Developer brainiacs like @peekay123 , @ScruffR, @nrobinson2000 and others could get involved.

That may have been a bit too enthusiastic. :smiley:

Good luck.


Raspberry Pi as gateway
#64

Been a while, @peekay123 did you ever get anything interesting going with your nrf52840 USB dongle (s) ?

I have an interesting argon.bin file I would like to send you. What’s the best way for me to do that?


#65

@rocksetta, I never got a chance to do anything with the dongle. I’ve been very busy on other projects. :disappointed_relieved:


#66

@rocksetta great work so far! I just found this thread, read through it, but want to make sure I understand the state of the world.

It sounds like you are still working on getting Particle Mesh devices to talk with other, 3rd party Thread devices?


#67

I am kind of like a dog with a bone when I get an idea, I purchased a class set of Argons and Xenons to teach OpenThread using the very easy to use Particle IDE. I was a bit surprised that things were more complex than I thought they would be.

If you use twitter say hi to @rocksetta we can DM, easier for me than using my laptop. As you saw at myblog/144 I have some connections going on, but it is far from useful yet.


#68

WARNING, WHAT WORKED LAST WEEK IS NOW BRICKING EVERY ARGON I TRY IT ON. WARNING!

It seems that the Argon version 1.4.2 bootloader will crash this program. Easy solution.

Downlaod version 1.4.1 bootloader from the releases page https://github.com/particle-iot/device-os/releases
or the direct link here
https://github.com/particle-iot/device-os/releases/download/v1.4.1/argon-bootloader@1.4.1.bin

From that folder open a terminal and run

particle usb dfu
particle update
particle usb start-listening
particle flash --serial argon-bootloader@1.4.1.bin 
particle usb reset

Then flash my code again from the correct folder. Very sad that Particle has made a bootloader that will not work with an opensource solution to a Argon connectivity issue.
Another solution would just be to stay at version 1.4.1 or install version 1.4.1 from scratch.

As per your message request @bsatrom here are the steps to load Openthread compatible software onto an Argon or Xenon. I have a Boron but have not done any testing with it yet. The following code simply sets up a HA network using multiple combinations of Argons and Xenons. These work without an OpenThread Border Router. Border Router connection is for another post.

  1. I do not know how to do a modular build using particle-cli or the webIDE (A good time for someone from Particle to make a tutorial about doing that.) so you have to load po-util at www.po-util.com. Installation of po-util on Linux is just
bash <(curl -sL get.po-util.com)
  1. Then run these commands on a Mac or Linux machine, takes a while for the last step to complete.
po init argon myArgonProject
cd myArgonProject
po config mesh-develop 
po setup-mesh
MODULAR=n po argon build

  1. You have now compiled an empty project. Find the main.c program which is probably in the firmware folder.

  2. Replace main.c with the following code. (If compiling for the Xenon it is the exact same code just the po command uses the word xenon instead of argon)

  3. Plug in your Argon (that has wifi pre-setup) and put in DFU mode. Hold down BOTH buttons. Release only the RESET button, while holding down the SETUP button. Wait for the LED to start flashing yellow (it will flash magenta first). (Don’t hold too long as it eventually does a factory reset which causes other issues.)

  4. Then do these steps (I manually delete the myArgonProject-argon.bin file generated in the above step in the main folder, clean does not delete it )

po argon clean
MODULAR=n po argon build
particle flash --usb myArgonProject-argon.bin

  1. Now repeat the last step to as many Argons as you want. (Best to just try 2 to start with)

  2. Connect 3V3 to D0 and see if all Argons flash. (Sort of proof that the Mesh is active)

  3. Connect 3V3 to D6 to shut of wifi with any of the Argons, the Mesh publish should still work.

  4. Following is the main.c code to load.

.

(There is a strong chance that I messed up a bit of my code when I tried to make it look all pretty so I have pasted working un-pretty code here)

// Particle Mesh Devices Connection Information Testing
// By Jeremy Ellis
// MIT Licence


// Install po-util with the following
// sudo apt install curl
// bash <(curl -sL get.po-util.com)
// Might want to pre install git, node, npm and particle-cli
// To check po-util version type
// po

// Start a po-util project
// po init argon myArgonProject
// cd myArgonProject

// po config mesh-develop 
// po setup-mesh

// MODULAR=n po argon build

// particle login
// particle list
// particle flash --usb myArgonProject-argon.bin


#include "Particle.h"

// uncomment the next line to improve stability
SYSTEM_THREAD(ENABLED);  // causes a small delay for Mesh.publish()

SYSTEM_MODE(SEMI_AUTOMATIC);  // so wifi not needed

//Next line allows you to use the Particle Featherwing plug and play
//STARTUP(System.enableFeature(FEATURE_ETHERNET_DETECTION)); 









#define OT_MASTER_KEY_SIZE 16

#include <assert.h>
#include "ot_api.h"
#include "openthread/dataset.h"

//#include "spark_wiring_udp.h"

//#include <openthread/thread_ftd.h>


#include <string.h>


extern "C" {

int8_t    otLinkGetChannel(otInstance *aInstance);
uint16_t  otLinkGetPanId(otInstance *aInstance);         // type otPanId
otMasterKey *otThreadGetMasterKey(otInstance *aInstance);
char     *otThreadGetNetworkName(otInstance *aInstance);


        otOperationalDataset aDataset;


void myHandler(const char *event, const char *data); 

};




/////////////////////////// important globals here ///////////////////////////////

int  myCode =5;  // number of flashes
bool myXenonAntennaAttached = false;  
bool myArgonBothAntennaAttached = false;  
bool myPublishToConsole = true;        // set true for Argon or debugging


int myCount = 0;
bool myButtonReady = true;



/////////////////////////////// end globals ////////////////////////////







void setup() {


   pinMode(D0, INPUT_PULLDOWN);
     pinMode(D6, INPUT_PULLDOWN);  // set pin D6 as an input at zero
    pinMode(D7, OUTPUT);          // our trusty D7 LED
    
    if (digitalRead(D6) == 0){
        Particle.connect();
    }

   Mesh.subscribe("mySendToAll", myHandler);

   if (myXenonAntennaAttached){
       #if (PLATFORM_ID == PLATFORM_XENON) 
	   digitalWrite(ANTSW1, 0);
	   digitalWrite(ANTSW2, 1);
       #endif  
   }
   if (myArgonBothAntennaAttached){
       #if (PLATFORM_ID == PLATFORM_ARGON) 
	   digitalWrite(ANTSW1, 1);
	   digitalWrite(ANTSW2, 0);
       #endif  
   }



        memset(&aDataset, 0, sizeof(otOperationalDataset));



        /* Set Network Name to OTCodelab */
        static char          aNetworkName[] = "OTCodelab";
        size_t length = strlen(aNetworkName);
        assert(length <= OT_NETWORK_NAME_MAX_SIZE);
        memcpy(aDataset.mNetworkName.m8, aNetworkName, length);
        aDataset.mComponents.mIsNetworkNamePresent = true;




    /*
     * Fields that can be configured in otOperationDataset to override defaults:
     *     Network Name, Mesh Local Prefix, Extended PAN ID, PAN ID, Delay Timer,
     *     Channel, Channel Mask Page 0, Network Master Key, PSKc, Security Policy
     */
    aDataset.mActiveTimestamp                      = 1;
    aDataset.mComponents.mIsActiveTimestampPresent = true;

    /* Set Channel to 15 */
    aDataset.mChannel                      = 15;
    aDataset.mComponents.mIsChannelPresent = true;

    /* Set Pan ID to 2222 */
    aDataset.mPanId                      = (otPanId)0x2222;
    aDataset.mComponents.mIsPanIdPresent = true;

    /* Set Extended Pan ID to C0DE1AB5C0DE1AB5 */
    uint8_t extPanId[OT_EXT_PAN_ID_SIZE] = {0xC0, 0xDE, 0x1A, 0xB5, 0xC0, 0xDE, 0x1A, 0xB5};
    memcpy(aDataset.mExtendedPanId.m8, extPanId, sizeof(aDataset.mExtendedPanId));
    aDataset.mComponents.mIsExtendedPanIdPresent = true;

    /* Set master key to 1234C0DE1AB51234C0DE1AB51234C0DE */
    uint8_t key[OT_MASTER_KEY_SIZE] = {0x12, 0x34, 0xC0, 0xDE, 0x1A, 0xB5, 0x12, 0x34, 0xC0, 0xDE, 0x1A, 0xB5};
    memcpy(aDataset.mMasterKey.m8, key, sizeof(aDataset.mMasterKey));
    aDataset.mComponents.mIsMasterKeyPresent = true;


        otInstance*  ot = ot_get_instance();

        otDatasetSetActive(ot, &aDataset);

        char *myNetworkName = otThreadGetNetworkName(ot);
        char myNetworkNameBuff[255];
        snprintf(myNetworkNameBuff, sizeof(myNetworkNameBuff), "%s", myNetworkName); // network name as a string

        Particle.publish("----------------","-------------", 60, PRIVATE); // just to show a space between samples
        delay(4000);
        Particle.publish("My Network Name: ", String(myNetworkNameBuff), 60, PRIVATE); //shows printing an integer variable
        delay(1000);

        // Mesh.localIP().toString().c_str());

        Particle.publish("My local ip: ", String(Mesh.localIP()), 60, PRIVATE); //shows printing an integer variable
        delay(1000);

}


void loop() {


 myCount +=1;
    
    if (digitalRead(D6) == 0){   
        Particle.connect();      // Cool I am a Photon
    } else {
        Particle.disconnect();  // Now I am an Arduino
    }



    if (myButtonReady && digitalRead(D0) == 1){
        myCount = 0;
        digitalWrite(D7, 1);
        myButtonReady = false;
      
        Particle.publish("Sending Broadcast", "...", 60, PRIVATE); 
        Mesh.publish("mySendToAll", String(myCode));  
        delay(1000);
        digitalWrite(D7, 0);
    }
    
    if (myCount >= 1000){
        if (! myButtonReady){
           Particle.publish("Device Reset", "...", 60, PRIVATE); 
        }
        myButtonReady = true; 

    }
    delay(5);  // becomes about 5 seconds



}






// Event listener for "mySendToAll" event from Xenons
void myHandler(const char *event, const char *data) {

    String parse = data;  //Cast char*data to String class
    int myNumber = parse.toInt();
    if (myPublishToConsole){  // mainly for Argon gateway unless debugging
        Particle.publish("Flashing D7 this many times:", parse, 60, PRIVATE); 
       // Particle.publish("udp ort number:", String(_remotePort), 60, PRIVATE); // did not compile
    }
    for (int myLoop = 0; myLoop < myNumber; myLoop++){
       digitalWrite(D7, HIGH);
       delay(200);   // very quick flash
       digitalWrite(D7, LOW);
       delay(200);   
    }
    delay(500); // to tell if 2 devices signal at similar times
}















Reminder to refresh your devices so they can work with particle again use a fresh .bin from particle. or just run particle update

https://github.com/particle-iot/device-os/releases/download/v1.4.1-rc.1/particle_device-os@1.4.1-rc.1.zip

New Video here

WARNING, WHAT WORKED LAST WEEK IS NOW BRICKING EVERY ARGON I TRY IT ON. WARNING!

It seems that the Argon version 1.4.2 bootloader will crash this program. Easy solution.

Downlaod version 1.4.1 bootloader from the releases page https://github.com/particle-iot/device-os/releases
or the direct link here
https://github.com/particle-iot/device-os/releases/download/v1.4.1/argon-bootloader@1.4.1.bin

From that folder open a terminal and run

particle usb dfu
particle update
particle usb start-listening
particle flash --serial argon-bootloader@1.4.1.bin 
particle usb reset

Then flash my code again from the correct folder. Very sad that Particle has made a bootloader that will not work with an opensource solution to a Argon connectivity issue.
Another solution would just be to stay at version 1.4.1 or install version 1.4.1 from scratch.


Particle MESH - Node Quantity Limit?
High School Robotics Course using the Particle.io Mesh Devices Blog
2 Argon boards on same mesh network?
How to unbrick Xenon (return to factory default firmware)
#69

I have 9 x nrf52840 usb dongles, 3 fanstel, 3 nordic and 3 makerdiary. (Which is kind of useless for Mesh owners, would be much better to make Particle devices talk to openthread.) My dongles all work with the Openthread border router and can ping or scan for the Mesh devices. I can’t communicate with the mesh devices since the Mesh.publish() command is much more complex behind the scenes than openthread commands. Example below of a basic udp message using openthread.

udp send ff02::1 1234 Hello Mesh

The Particle Mesh devices should be able to connect to OTBR using a serial USB connection. Pre-made software needs to be installed to run the commands, but that is for a later date. Presently I just want to get the mesh devices talking to the linux screen (or putty) program. I found this code from:

Not sure if that will get the Mesh devices talking to putty or screen but I will give it a try, my backup plan is just to use my normal putty communication program

// Use putty serial mode 
// gete putty here   https://www.putty.org/
// To find which COM port use the device manager
// If no access to the device manager type on a windows command line   CMD or powershell
// mode





int incomingByte = 0; // for incoming serial data

void setup() {
    Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
    Serial.print("Press any key, then try the letter A");
}

void loop() {
  // send data only when you receive data:
    if (Serial.available() > 0) {
    // read the incoming byte:
        incomingByte = Serial.read();

        Serial.print("I received: ");
        Serial.println(incomingByte, DEC);
        
        if ((char)incomingByte == 'A'){   // #65
            Serial.println("Cool, you entered an 'A' ");
 
        }        
        if ((char)incomingByte == 'a'){   // #97
            Serial.println("Sweet, you entered an 'a' ");
 
        }
        
    }
  
}

The hard part is going to be getting the opehthread-cli working on mesh devices. If anyone wants to mess around with openthread I have a github/gitpod ready to go

or run this pre-made gitpod: (fairly advanced stuff and takes about 5 min to load.)

Open in Gitpod

Commands like the following should run (the commands below generate the .hex files to load on my usb dongles so you can send OTBR commands using “screen”).

              make -f examples/Makefile-nrf52840 USB=1 BOOTLOADER=1 BORDER_AGENT=1 BORDER_ROUTER=1 COMMISSIONER=1 JOINER=1 UDP_PROXY=1 CFLAGS+=-UCONFIG_GPIO_AS_PINRESET 

              arm-none-eabi-objcopy output/nrf52840/bin/ot-ncp-ftd -O ihex output/nrf52840/bin/ncp_app.hex       
             
              arm-none-eabi-objcopy output/nrf52840/bin/ot-cli-ftd -O ihex output/nrf52840/bin/ot-cli-ftd.hex                 

#70

Can’t believe I just got po-util.com working on gitpod.

Cloud po-util now even windows users can build Particle Mesh devices.

Open in Gitpod

Obviously you can’t do, from the browser

particle flash --usb myArgonProject-argon.bin

But particle-cli does install on windows so just download the .bin file and use your windows machine to install it.

To refix

Thanks @ScruffR This is very useful for fixing the Argons

(put in DFU mode)
particle flash --usb tinker

(put in DFU mode)
particle update

(put in DFU mode)
particle flash --usb tinker

(Should be in listening mode flashing blue)
particle serial wifi
(setup your wifi)


#71

It’s possible to put devices into dfu mode without pressing the buttons by using the following particle-cli command. Just leaving this here for future reference.

particle usb dfu

#72

Thanks. Any idea if particle update, updates the bootloader? I have a couple of really dead Argons.


#73

So this was successful in getting one Argon back to life:

  1. Download from https://github.com/particle-iot/device-os/releases/ look for heading System Binaries (All Devices) about 2 pages down. (In this case v1.4.2)

  2. Argon listening mode flashing blue

particle serial flash argon-bootloader@1.4.2.bin

  1. DFU mode just to flashing yellow

particle flash --usb argon-system-part1@1.4.2.bin

  1. ( I flashed the tinker as well but don’t think that was needed, and connected wifi for wifi put in listening mode)

particle serial wifi

  1. Put device in listening mode and use the android app to re-setup everything
    (very fast since the firmware is uptodate.)

I will try with my other dead Argons to see if this also works.


#74

IIRC with 1.4.0 (or 1.4.1 ??) the bootloader has been made DFU flashable. So from then on particle update -v (I prefer the verbose version to see what’s going on) should also take care of that.


#75

Thanks @ScruffR I got all 4 of my very dead Argons working again.

For 3 of them I did

particle update

Then used the Android App since the firmware is already installed and the app doesn’t need to go through the OS update, (which in a school with busy wifi is a horrible experience).

For one of the Argons I had to do the OS update, but before that I did a full factory reset past DFU until the white LED. Then installed the bootloader and the firmware, then did particle update and used the android app. Now it works but strangely the device name is not updating and looks kind of like the Device ID. Oh well at least it is working and I can go back to breaking Argons (What I do best!)