Menu
Microbots
0
  • Learn
    • Getting Started
    • Maker Builds
    • Education
  • Shop
    • ProtoBot
    • Modules & Parts
    • Tools & Gears
    • Coming Soon
  • About
    • Our Story
    • Reach Out
    • FAQs
  • Sign in
  • English
  • Your Cart is Empty
Microbots
  • Learn
    • Getting Started
    • Maker Builds
    • Education
  • Shop
    • ProtoBot
    • Modules & Parts
    • Tools & Gears
    • Coming Soon
  • About
    • Our Story
    • Reach Out
    • FAQs
  • Language

  • 0 0

CodeCell: Connecting with BLE

Bluetooth Low Energy (BLE) is a popular way to communicate wirelessly between electronic devices. It is an energy-efficient version of Bluetooth that allows devices to exchange small amounts of data with low power consumption. Here are it's key concepts:

  • BLE Server → CodeCell acts as a server, advertising itself to other devices.
  • BLE Client → A phone, tablet, or another microcontroller that connects to CodeCell.
  • BLE Service → A collection of characteristics that define the data being sent.
  • BLE Characteristic → A specific data point (e.g., button presses, sensor readings).

Viewing BLE Data on a Smartphone

Before we start testing, your need to download an app to send BLE data on your  smartphone. So start by downloading a BLE scanner app:

  • Android → nRF Connect or "BLE Scanner"
  • iOS → nRF Connect

Setting Up BLE on CodeCell

To make CodeCell advertise itself as a BLE device, we need to initialize BLE, create a service and characteristic, and start advertising.

This code creates a BLE server, advertises a service, and sets up a characteristic that can be read and written by a connected device. The CodeCell will receive the button characteristic and control its onboard RGB LED:

  • If the button value is 1, the LED turns red.
  • If the button value is 0, the LED turns green.
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>

#include <CodeCell.h>
CodeCell myCodeCell;

BLECharacteristic *pButtonCharacteristic = NULL;
#define BUTTON_UUID "abcd1234-abcd-1234-abcd-123456789012"

class MyServerCallbacks : public BLEServerCallbacks {
  void onConnect(BLEServer *pServer) override {
    Serial.println("BLE Connected");
    delay(1000);
  }

  void onDisconnect(BLEServer *pServer) override {
    Serial.println("BLE Disconnected");
    delay(500);
    BLEDevice::startAdvertising(); // Restart advertising
  }
};

// Callback class for handling button writes
class ButtonCallback : public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic *pCharacteristic) override {
   String value = pCharacteristic->getValue();
    
    if (value.length() > 0) {
      int buttonState = value[0]; 

      Serial.print("Button State: ");
      Serial.println(buttonState);

      if (buttonState == 1) {
        myCodeCell.LED(255, 0, 0); // Red LED when button is 1
      } else {
        myCodeCell.LED(0, 255, 0); // Green LED when button is not 1
      }
    }
  }
};

void setup() {
    Serial.begin(115200);
    myCodeCell.Init(LIGHT); // Initializes the light sensor

    BLEDevice::init("CodeCell_BLE"); // Set BLE device name
    BLEServer *bleServer = BLEDevice::createServer();
    bleServer->setCallbacks(new MyServerCallbacks());

    BLEService *bleService = bleServer->createService(BLEUUID("12345678-1234-5678-1234-56789abcdef0"));

    // Create BLE characteristic for button state
    pButtonCharacteristic = bleService->createCharacteristic(
        BUTTON_UUID,
        BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE
    );
    pButtonCharacteristic->addDescriptor(new BLE2902());
    pButtonCharacteristic->setCallbacks(new ButtonCallback());

    bleService->start();

    BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
    pAdvertising->addServiceUUID("12345678-1234-5678-1234-56789abcdef0");
    BLEDevice::startAdvertising();
}

void loop() {
    // No need to continuously check, LED updates only on BLE write
}

How This Code Works

  • BLE Initialization → CodeCell advertises itself as a BLE device called "CodeCell_BLE".
  • BLE Service & Characteristic → A service with a button characteristic is created.
  • BLE Callbacks → The server prints "BLE Connected" when a client connects and "BLE Disconnected" when it disconnects.
  • Advertising Restart → When disconnected, BLE automatically starts advertising again so new devices can connect.

Testing the LED Control  

  • Connect to "CodeCell_BLE" in the BLE Scanner app.
  • Select the service you created - typically displayed as Unknown Service
  • Find the button characteristic (BUTTON_UUID) and send the value:
    • Write 1 → LED turns red 🔴
    • Write 0 → LED turns green 🟢

Sending Sensor Data

Next we'll define a new BLE characteristic that allows CodeCell to send sensor values to a connected device.

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>

#include <CodeCell.h>
CodeCell myCodeCell;

BLECharacteristic *pSensorCharacteristic = NULL;
#define SENSOR_UUID "abcd5678-abcd-5678-abcd-56789abcdef0"

class MyServerCallbacks : public BLEServerCallbacks {
  void onConnect(BLEServer *pServer) override {
    Serial.println("BLE Connected");
    delay(1000);
  }

  void onDisconnect(BLEServer *pServer) override {
    Serial.println("BLE Disconnected");
    delay(500);
    BLEDevice::startAdvertising(); // Restart advertising
  }
};

void setup() {
    Serial.begin(115200);
    myCodeCell.Init(LIGHT); // Initialize light and proximity sensor

    BLEDevice::init("CodeCell_BLE"); // Name the BLE device
    BLEServer *bleServer = BLEDevice::createServer();
    bleServer->setCallbacks(new MyServerCallbacks());

    BLEService *bleService = bleServer->createService(BLEUUID("12345678-1234-5678-1234-56789abcdef0"));

    // Create BLE characteristic for sensor data
    pSensorCharacteristic = bleService->createCharacteristic(
        SENSOR_UUID,
        BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY
    );
    pSensorCharacteristic->addDescriptor(new BLE2902());

    bleService->start();

    BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
    pAdvertising->addServiceUUID("12345678-1234-5678-1234-56789abcdef0");
    BLEDevice::startAdvertising();
}

void loop() {
    if (myCodeCell.Run(10)) { // Read every 100ms (10Hz)
        uint16_t proximity = myCodeCell.Light_ProximityRead();
        Serial.print("Proximity: ");
        Serial.println(proximity);

        // Convert proximity value to string and send over BLE
        String proximityStr = String(proximity);
        pSensorCharacteristic->setValue(proximityStr.c_str());
        pSensorCharacteristic->notify(); // Notify connected device
    }
}

How it works?

  • This code sets up a new characteristic (SENSOR_UUID) that clients can read and get real-time updates:
    • PROPERTY_READ → Allows the client to read the value manually.
    • PROPERTY_NOTIFY → Automatically sends updates when new data is available.
  • The Light_ProximityRead() function gets a value from the onboard light sensor that detects nearby objects. We convert the number to a string and send it to the BLE client.

Try it out

Now that CodeCell is sending proximity sensor data over BLE, you can view it on a phone.

  • Open a BLE app like nRF Connect (Android/iOS)
  • Scan for "CodeCell_BLE" and connect
  • Find the sensor characteristic (SENSOR_UUID)
  • Enable notifications and watch the proximity data update in real-time!
  • Your Serial Monitor data should match the data sent to your phone

Move an object near the sensor and see how values change!


 

  • Share:

Follow

Github

  • About
  • Software
  • Education
  • Contact
  • FAQs
  • Terms
  • Refund Policy
  • Privacy Policy

Join our Community ~ Be the first to know about new products and get exciting deals!

© 2026 Microbots.

★ Reviews

Let customers speak for us

68 reviews
Write a review
84%
(57)
6%
(4)
3%
(2)
3%
(2)
4%
(3)
63
21
C
CodeCell C3
Cloke74

Great piece of kit, had just what i needed to complete the project i had in mind. Shame shipping to the UK is so expensive, but appreciate this isn’t necessarily in the hands of MicroBots

A
CodeCell C6
Anonymous

I had an issue, got a red light, I used too much flux. Support said clean it, then the one sensor worked fine. I got the help and answer same day I provided a foto.

A
CodeCell C6 Drive
Anonymous

I think this is the best of the ESP offered, most versatile.

User picture
P
CodeCell C6
Prudhvi tej Chinimilli

Been testing the Microbots CodeCell C6 and honestly impressed with how much functionality they packed into such a tiny module. Great form factor for rapid prototyping wearable/embedded sensing applications. ESP32-C6 + IMU integration makes development much easier compared to building everything from scratch.

Still exploring battery optimization and compact LiPo options for our use case, but overall the platform is promising for low-cost real-time sensing systems. Excited to keep building with it.

F
CodeCell C6
Francisco Estivallet

Amazing hardware, my go to for compact projects.

User picture
123