Looking for example ble multilink for argon to 4 xenons


My setup consist of 2 ble beacons, 1 Argon and 4 Xenons.
if someone can point me in the right direction for a multilink example.

  1. I need to transmit the battery voltages to the argon.
  2. I need to send short commands to the Xenons, turn on a relay.

I don’t need the Xenons connected to the cloud, I can relay their message through the Argon if possible.

thanks in advance

The maximum number of concurrently connected peers is 3.
However, if you can do with a round-robin approach that wouldn’t be too different from a 1-to-1 connection merely cycling through the peer addresses.

The Xenons can permanently advertise their battery states while the Argon would only establish a connection when a command is to be sent.

Alternatively you could go without a central device entirely if your commands would be simple on/off states. Then the Argon could also just advertise the desired state of all relays in a single byte and each individual Xenon would just pick out the respective bit pertaining to its relay.

1 Like

Thanks Scruff. I followed your suggestion. I can indeed advertise my on/off command to all Xenon’s one time. I would like to “marry” the MAC address of the Xenon with their battery voltage and send to Argon.
I know how to extract the MAC address from a BLE payload on the receiver side, how would I get the MAC address from the Xenon to add to the payload to send to Argon

I don’t quite understand the reason for that request.
You are looking for a way to send the MAC address twice in the same data packet? Why?
The advertising data is already limited in length so why add redundancy?

However, you can use BLE.address() to request the MAC of the local device and then adding that to the advertising data is straight forward.

1 Like

Thanks Scruff. I followed your suggestion. Im using both Argon and Xenon in “beacon modes” 2 functions for BLE advertising and scanning on Argon and four Xenons. Advertise packets between them are little maybe 1-10 packets a day.

The Argon Scans for the BLE i-beacons and works very well. Im also able to send “trigger relay command” from the Argon to the 4 Xenons if I get message from the i beacon. But sending the batt voltage from Xenons to the Argon is not so reliable.

  1. I cant listen and transmit at the same time on my Xenons.
  2. I dont think the “beaconing” setup on my Argon and Xenon is the best method for two way communication. it becomes a timing and timeout problem.
  3. Would it be better to let the argon connect to each xenon and exchange information (receive battery info and send relay status) in one go? is it possible?

For completeness: my beaconing code below
functions on the Argon to scan both BLE i-beacons and scan for the voltage advertisement from the Xenons

void scanBleBeacons(){
  BLE.setScanTimeout(100); // 
  int count = BLE.scan(scanResults, SCAN_RESULT_MAX);
  for (int ii = 0; ii < count; ii++) {
    size_t len = scanResults[ii].advertisingData.get(buf, BLE_MAX_ADV_DATA_LEN);//used to get an entire block of 31 bytes
    String Beacon_name = results[ii].advertisingData.deviceName();//check if the results have an name
    memcpy(buf_copy, buf, sizeof(buf));//make a copy
    //build  a string out of the MAC char array so we can compare incoming to what is saved in the EEPROM
    sprintf (emMacCharToString, "em_MAC_%02x:%02x:%02x:%02x:%02x:%02x",
//make sure its a eddystone TLM beacon so we can extract batt voltages from the beacons
    if((buf_copy[11] == 0x20)&&(buf_copy[12] == 0x00)&&(buf_copy[15] == 0x80)&&(buf_copy[16] == 0x00)){
     saveVoltage = (buf_copy[13]<<8)|(buf_copy[14]) ;//It is a TLM beacon so ectract the voltage
     ExtractBattVoltage();// do something with the voltage that was extracted i.e post to ubidots
    //We also need to check for Xenon battery voltages.
    //check if its a xenon and copy the voltage
    if ((buf_copy[5] == 0x19)&&(buf_copy[6] == 0x74)&&(buf_copy[7] == 0x03)&&(buf_copy[8] == 0x29)){
      //copy and build the MAC with voltage to post to ubidots
     sprintf (xenonMacOne, "xenon_MAC_%02x:%02x:%02x:%02x:%02x:%02x\0",scanResults[ii].address[5], scanResults[ii].address[4], scanResults[ii].address[3],
                                                                      scanResults[ii].address[2], scanResults[ii].address[1], scanResults[ii].address[0]);
    float xenonVoltage;
    memcpy(&xenonVoltage, &buf[9], 4);//copy the  voltage values out of the buffer
    ubidots.add(xenonMacOne, xenonVoltage);//build context for ubidots
  }//end of for 

}// end of scanBleBeacons

Code that transmit the relay on to all the xenons (beacon mode)

//sends the relay message to turn relay on on all Xenons listening
void updateAdvertisingData(bool updateOnly)
   uint8_t buf[BLE_MAX_ADV_DATA_LEN];
   size_t offset = 0;
   memcpy(&buf[offset], &gatewayDetonationCommand, 
   offset += strlen(gatewayDetonationCommand);
   BleAdvertisingData advData;
   advData.appendCustomData(buf, offset);
   // Continuously advertise untill time out occurs, specified in setup

On my Xenons I have similar two functions one for receiving the relay command and one for sending the battery voltage however I cant run both these function at the same time (cant listen and speak) need to turn one off.

void scanBleGateway(){
  BLE.setScanTimeout(100); // 
  int count = BLE.scan(scanResults, SCAN_RESULT_MAX);
  for (int ii = 0; ii < count; ii++) {
   size_t len = scanResults[ii].advertisingData.get(buf, BLE_MAX_ADV_DATA_LEN);//used to get an entire block of 31 bytes
   memcpy(gatewayMessage,(void*)&buf[5], 20);//copy only the message sent from the gateway
   //convert to string the incoming message from Argon
   sprintf (gatewayMessageCharToString, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
            gatewayMessage[0], gatewayMessage[1],  gatewayMessage[2], gatewayMessage[3], gatewayMessage[4], gatewayMessage[5], gatewayMessage[6], gatewayMessage[7], gatewayMessage[8], gatewayMessage[9], gatewayMessage[10], 
            gatewayMessage[11], gatewayMessage[12], gatewayMessage[13],gatewayMessage[14], gatewayMessage[15], gatewayMessage[16], gatewayMessage[17], gatewayMessage[18], gatewayMessage[19], gatewayMessage[20]);

/*compare incoming string to const char string in setup, if the same the trigger relay*/
   if (!strcmp (BeaconVibrationDetected,gatewayMessageCharToString)){
     triggerRelay(); /*triggerRelay*/
//transmit the Xenon battery voltage 2 or 3 times a day to Argon for upload to ubidots
void timerTransmitBattVoltage(void){
   battVoltage = analogRead(BATT) * 0.0011224 / 3.7 * 100; /// in percentage
   uint8_t buf[BLE_MAX_ADV_DATA_LEN];

    size_t offset = 0;
    //Copy the battery voltage as well as Custom identifier (19740329) into the buffer for Argon to extract
    buf[offset++] = 0x19;
    buf[offset++] = 0x74;
    buf[offset++] = 0x03;
    buf[offset++] = 0x29;
    memcpy(&buf[offset], &battVoltage, 5);
    offset += 5;
    BleAdvertisingData advData;
    advData.appendCustomData(buf, offset);
    // Continuously advertise till time out occurs as setup in setup function

Im not to familiar with the BLE connectable protocall using characteristics and services but would this be a better solution?

thanks again

The suggestion to use advertising instead of connecting to the relay controler was merely an alternative when timing is non-critical and/or as a backup plan between actively toggling the relay states.

For active pushing of data to the Xenons individually the round-robin connecting approach would be the safer bet.

pushing data to the Xenon is not sp much of a problem its get the batt voltage from the the xenons. Would I be able to do both in one connection? thought it worked only one way.

You can go both ways although it’s usually (with the exception of a notification characterisitic) the central that initiates the transfer it either writes to the device or reads from the device - providing the device exposes a read and write characteristic (or a combined read/write).