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.
- 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)
- 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
-
You have now compiled an empty project. Find the main.c program which is probably in the firmware folder.
-
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)
-
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.)
-
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
-
Now repeat the last step to as many Argons as you want. (Best to just try 2 to start with)
-
Connect 3V3 to D0 and see if all Argons flash. (Sort of proof that the Mesh is active)
-
Connect 3V3 to D6 to shut of wifi with any of the Argons, the Mesh publish should still work.
-
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
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.