Read from Wire-I2C LED on/off on 1st(Central) MKR WiFi 1010 and send to 2nd(Peripheral) MKR WiFi via BLE

Hello,
I have a project where I am sending an LED on/off command from a Teensy 4.1 to an MKR Wifi 1010 via I2C using Wire.h and then need to send that same LED on/off via BLE to a second MKR Wifi 1010 that will have an actual light attached to it. I have setup the first MKR as the Central and the second MKR as the Peripheral with an LED Service and a Characteristic that I can write to and all of that is good. I can read the on/off via the I2C bus and light up the local LED on the Teensy as well as the Builtin LED on the first MKR fine. As a BLE test, I can also send an LED on/off loop to the second MKR via the Characteristic.writeValue and that also works fine. The part I'm stuck on is how to take the Wire.read LED on/off and send that via LED Characteristic.writeValue?
Here is my code and the heart of the read/write are towards the bottom. Thanks for any help on this.

#include <ArduinoBLE.h>
#include <Wire.h>


int LED = 3;
int x = 0;

void setup() {
  Serial.begin(9600);

  //WiFiDrv::pinMode(27, OUTPUT); //define blue pin
  pinMode ( LED, OUTPUT);

  // initialize the Bluetooth® Low Energy hardware
  BLE.begin();

  Serial.println("Bluetooth® Low Energy Central - LED control");

  // start scanning for peripherals
  BLE.scanForUuid("79055cb9-70d2-4739-a687-c6065d41fb83");

  Wire.begin(1); 
  Wire.onReceive(receiveEvent);
}

void loop() {
  // check if a peripheral has been discovered
  BLEDevice peripheral = BLE.available();

  if (peripheral) {
    // discovered a peripheral, print out address, local name, and advertised service
    Serial.print("Found ");
    Serial.print(peripheral.address());
    Serial.print(" '");
    Serial.print(peripheral.localName());
    Serial.print("' ");
    Serial.print(peripheral.advertisedServiceUuid());
    Serial.println();

    if (peripheral.localName() != "LED") {
      return;
    }

    // stop scanning
    BLE.stopScan();

    controlLed(peripheral);

    // peripheral disconnected, start scanning again
    BLE.scanForUuid("79055cb9-70d2-4739-a687-c6065d41fb83");
  }
}

void controlLed(BLEDevice peripheral) {
  // connect to the peripheral
  Serial.println("Connecting ...");

  if (peripheral.connect()) {
    Serial.println("Connected");
  } else {
    Serial.println("Failed to connect!");
    return;
  }

  // discover peripheral attributes
  Serial.println("Discovering attributes ...");
  if (peripheral.discoverAttributes()) {
    Serial.println("Attributes discovered");
  } else {
    Serial.println("Attribute discovery failed!");
    peripheral.disconnect();
    return;
  }

  // retrieve the LED characteristic
  BLECharacteristic ledCharacteristic = peripheral.characteristic("74b3ab05-e45b-4706-8504-89113a04c570");

  if (!ledCharacteristic) {
    Serial.println("Peripheral does not have LED characteristic!");
    peripheral.disconnect();
    return;
  } else if (!ledCharacteristic.canWrite()) {
    Serial.println("Peripheral does not have a writable LED characteristic!");
    peripheral.disconnect();
    return;
  }
//------------------------------------------------------------------------------------------------------------------
// This part is just a test to write the LED on/off via BLE to the second MKR WiFi-This works as it should
//------------------------------------------------------------------------------------------------------------------

  while (peripheral.connected()) {
    // while the peripheral is connected


        ledCharacteristic.writeValue((byte)0x01);
        delay(1000);

        
        ledCharacteristic.writeValue((byte)0x00);
        delay(1000);
      }
    
    Serial.println("Peripheral disconnected");
}

//------------------------------------------------------------------------------------------------------------------
// This is reading the I2C value and does write to the builtin LED as it should.  
//. ***. This is the value I want to write to the second MKR via BLE***
//------------------------------------------------------------------------------------------------------------------
void receiveEvent(int howMany) {
  
  x = Wire.read();    // read one character from the I2C

    if (x == 1) {
      digitalWrite(LED, HIGH);
    }
    else{
      digitalWrite(LED, LOW);
      }
}

Can You draw a logic block diagram showing the builld?
You talk about "Characteristic.writeValue"..... It's not clear how/where/why it's used.

Yep... heading home and I'll do it ASAP. Thanks

Hello @Railroader! What I mean by "Characteristic.writeValue".. At the end of my code there is this code that shows how I can write the LED Characteristic to MKR #2 via BLE. Whats in the code right now is just a simple LED Blink being written via BLE to the second MKR-and this works fine. Right below that is the "void receiveEvent" code that is being received by the Wire iC2 READ and it assigns a variable X(or 1 or a 0) and turns on/off the local LED on MKR 1- This works fine. So now that I have proved I'm receiving the blink message from the PC>to the Teensy>to the MKR #1 via iC2 - and I have a good BLE link from MKR 1 to MKR 2 now I'm trying to understand how I get my Wire read via the iC2 bus to blink on my MKR 2 via BLE. Everything I have tried gives me the "not declared in this scope" error. Like trying to write to the ledCharacteristic.writeValue right from the x= Wire.read code.

//------------------------------------------------------------------------------------------------------------------
// This part is just a test to write the LED on/off via BLE to the second MKR WiFi-This works as it should
//------------------------------------------------------------------------------------------------------------------

  while (peripheral.connected()) {
    // while the peripheral is connected


        ledCharacteristic.writeValue((byte)0x01);
        delay(1000);

        
        ledCharacteristic.writeValue((byte)0x00);
        delay(1000);
      }
    
    Serial.println("Peripheral disconnected");
}

//------------------------------------------------------------------------------------------------------------------
// This is reading the I2C value and does write to the builtin LED as it should.  
//. ***. This is the value I want to write to the second MKR via BLE***
//------------------------------------------------------------------------------------------------------------------
void receiveEvent(int howMany) {
  
  x = Wire.read();    // read one character from the I2C

    if (x == 1) {
      digitalWrite(LED, HIGH);
    }
    else{
      digitalWrite(LED, LOW);
      }

That is a compiler error and no code is downloaded.
Please post the entire error code.

Here's the whole sketch with trying to print to the ledCharacteristic.writeValue at the bottom.

#include <ArduinoBLE.h>
#include <Wire.h>


int LED = 3;
int x = 0;

void setup() {
  Serial.begin(9600);

  //WiFiDrv::pinMode(27, OUTPUT); //define blue pin
  pinMode ( LED, OUTPUT);

  // initialize the Bluetooth® Low Energy hardware
  BLE.begin();

  Serial.println("Bluetooth® Low Energy Central - LED control");

  // start scanning for peripherals
  BLE.scanForUuid("79055cb9-70d2-4739-a687-c6065d41fb83");

  Wire.begin(1); 
  Wire.onReceive(receiveEvent);
}

void loop() {
  // check if a peripheral has been discovered
  BLEDevice peripheral = BLE.available();

  if (peripheral) {
    // discovered a peripheral, print out address, local name, and advertised service
    Serial.print("Found ");
    Serial.print(peripheral.address());
    Serial.print(" '");
    Serial.print(peripheral.localName());
    Serial.print("' ");
    Serial.print(peripheral.advertisedServiceUuid());
    Serial.println();

    if (peripheral.localName() != "LED") {
      return;
    }

    // stop scanning
    BLE.stopScan();

    controlLed(peripheral);

    // peripheral disconnected, start scanning again
    BLE.scanForUuid("79055cb9-70d2-4739-a687-c6065d41fb83");
  }
}

void controlLed(BLEDevice peripheral) {
  // connect to the peripheral
  Serial.println("Connecting ...");

  if (peripheral.connect()) {
    Serial.println("Connected");
  } else {
    Serial.println("Failed to connect!");
    return;
  }

  // discover peripheral attributes
  Serial.println("Discovering attributes ...");
  if (peripheral.discoverAttributes()) {
    Serial.println("Attributes discovered");
  } else {
    Serial.println("Attribute discovery failed!");
    peripheral.disconnect();
    return;
  }

  // retrieve the LED characteristic
  BLECharacteristic ledCharacteristic = peripheral.characteristic("74b3ab05-e45b-4706-8504-89113a04c570");

  if (!ledCharacteristic) {
    Serial.println("Peripheral does not have LED characteristic!");
    peripheral.disconnect();
    return;
  } else if (!ledCharacteristic.canWrite()) {
    Serial.println("Peripheral does not have a writable LED characteristic!");
    peripheral.disconnect();
    return;
  }
//------------------------------------------------------------------------------------------------------------------
// This part is just a test to write the LED on/off via BLE to the second MKR WiFi-This works as it should
//------------------------------------------------------------------------------------------------------------------

  while (peripheral.connected()) {
    // while the peripheral is connected


        ledCharacteristic.writeValue((byte)0x01);
        delay(1000);

        
        ledCharacteristic.writeValue((byte)0x00);
        delay(1000);
      }
    
    Serial.println("Peripheral disconnected");
}

//------------------------------------------------------------------------------------------------------------------
// This is reading the I2C value and does write to the builtin LED as it should.  
//. ***. This is the value I want to write to the second MKR via BLE***
//------------------------------------------------------------------------------------------------------------------
void receiveEvent(int howMany) {
  
  x = Wire.read();    // read one character from the I2C

    if (x == 1) {
      ledCharacteristic.writeValue((byte)0x01);
    }
    else{
      ledCharacteristic.writeValue((byte)0x00);
      }
}

Returns this error:
/private/var/folders/8x/700kp8mj6vd5w_x8stw53z_r0000gn/T/.arduinoIDE-unsaved2024922-8753-1v4pa5a.q0wr/sketch_oct22a/sketch_oct22a.ino: In function 'void receiveEvent(int)':
/private/var/folders/8x/700kp8mj6vd5w_x8stw53z_r0000gn/T/.arduinoIDE-unsaved2024922-8753-1v4pa5a.q0wr/sketch_oct22a/sketch_oct22a.ino:115:7: error: 'ledCharacteristic' was not declared in this scope
ledCharacteristic.writeValue((byte)0x01);
^~~~~~~~~~~~~~~~~
/private/var/folders/8x/700kp8mj6vd5w_x8stw53z_r0000gn/T/.arduinoIDE-unsaved2024922-8753-1v4pa5a.q0wr/sketch_oct22a/sketch_oct22a.ino:115:7: note: suggested alternative: 'BLECharacteristic'
ledCharacteristic.writeValue((byte)0x01);
^~~~~~~~~~~~~~~~~
BLECharacteristic
/private/var/folders/8x/700kp8mj6vd5w_x8stw53z_r0000gn/T/.arduinoIDE-unsaved2024922-8753-1v4pa5a.q0wr/sketch_oct22a/sketch_oct22a.ino:118:7: error: 'ledCharacteristic' was not declared in this scope
ledCharacteristic.writeValue((byte)0x00);
^~~~~~~~~~~~~~~~~
/private/var/folders/8x/700kp8mj6vd5w_x8stw53z_r0000gn/T/.arduinoIDE-unsaved2024922-8753-1v4pa5a.q0wr/sketch_oct22a/sketch_oct22a.ino:118:7: note: suggested alternative: 'BLECharacteristic'
ledCharacteristic.writeValue((byte)0x00);
^~~~~~~~~~~~~~~~~
BLECharacteristic

exit status 1

Compilation error: 'ledCharacteristic' was not declared in this scope

This variable is change within an interrupt routine, and should be declared volatile. It should also be a byte, as you are reading a single byte in the receive event.

//int x = 0;
volatile byte x = 0;

Then, I would use this variable as follows.

void receiveEvent(int howMany) {
    x = Wire.read();    // read one character from the I2C
}

Then in while (peripheral.connected())

while (peripheral.connected()) {
    // while the peripheral is connected
    static unsigned long lastWriteTime = 0;
    if (millis() - lastWriteTime >= 1000)
    {
      lastWriteTime = millis();
      ledCharacteristic.writeValue(x);
      //delay(1000);
      //ledCharacteristic.writeValue((byte)0x00);
      //delay(1000);
    }
  }
  Serial.println("Peripheral disconnected");
}

Thanks.

Where would this function come from? From which library?

As You write " BLEDevice peripheral = BLE.available();" there must be a declaration like "xxlibrary ledCharacteristic = ???"

Thanks @cattledog. That does compile so I will give that a try tomorrow.

This comes from the <ArduinoBLE.h> library. Then in:

void controlLed(BLEDevice peripheral) {
  // connect to the peripheral
  Serial.println("Connecting ...");

  if (peripheral.connect()) {
    Serial.println("Connected");
  } else {
    Serial.println("Failed to connect!");
    return;
  }

I use:

// retrieve the LED characteristic
  BLECharacteristic ledCharacteristic = peripheral.characteristic("74b3ab05-e45b-4706-8504-89113a04c570");

  if (!ledCharacteristic) {
    Serial.println("Peripheral does not have LED characteristic!");
    peripheral.disconnect();
    return;
  } else if (!ledCharacteristic.canWrite()) {
    Serial.println("Peripheral does not have a writable LED characteristic!");
    peripheral.disconnect();
    return;
  }

@cattledog had detailed knowledge and pulled the plug, more then I could do. Well become @kwburhans

Thank You @cattledog, that works and now I understand. :grinning:

Thanks foe taking a look @Railroader!

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.