Fab Academy 2024 Website

  • Home
  • About
  • WEEK1 Project Management / Principles and Practices
  • WEEK2 Computer Aided Design
  • WEEK3 Computer-controlled cutting
  • WEEK4 Electronics production
  • WEEK5 3D scanning and printing
  • WEEK6 Embedded programming
  • WEEK7 Computer-controlled machining
  • WEEK8 Electronics design
  • WEEK9 Output devices
  • WEEK10 Mechanical design, Machine design
  • WEEK11 Input devices
  • WEEK12 Molding and casting
  • WEEK13 Networking and communications
  • WEEK14 Interface and application programming
  • WEEK15 Wildcard week
  • WEEK16 System integration
  • WEEK17 Applications and implications, project development
  • WEEK18 Invention, intellectual property, and income
  • Final
目次
  • WEEK13 Networking and communications
    • Group Assignment
    • Individual Assignment
      • Use the board created in Assignment 8
      • Change the MCU from XIAO PR2040 to XIAO ESP32C3
      • Combine the codes
        • Arudino UART Sample code
        • Execution Result
        • Combined code
          • ChatGPT Prompt
        • Execution Result

WEEK13 Networking and communications

  1. Fab Academy 2024 Website
  2. WEEK13 Networking and communications
hito |


WEEK13 Networking and communications

Group Assignment

send a message between two projects

Networking and communications

Individual Assignment

design, build, and connect wired or wireless node(s) with network or bus addresses and local input &/or output device(s)

For this assignment, we will continue to work on the content related to the Final Project. The flow is as follows:

・Use the board created in Assignment 8
・Change the MCU from XIAO PR2040 to XIAO ESP32C3 (The reason for the change is that the ESP32C3 has Bluetooth functionality)
・Combine the code to obtain acceleration & gyro data used in Assignment 11 and the Arduino IDE UART sample code (File->Examples->BLE->UART)
・Transmit the acceleration and gyro data obtained from the MPU-6050 accelerometer sensor to a Bluetooth-connected smartphone in real-time

Use the board created in Assignment 8

alt text alt text

Change the MCU from XIAO PR2040 to XIAO ESP32C3

ESP32C3 Datasheet alt text
The ESP32C3 is a microcontroller developed by Espressif Systems as part of their ESP32 series. It is characterized by its low cost and low power consumption. Key features and specifications include:

Processor: The ESP32C3 is equipped with a 32-bit RISC-V single-core processor, which can operate at up to 160 MHz.
Memory: It supports built-in 384KB SRAM and up to 4MB of external flash memory.
Wireless Capabilities: It offers support for both Wi-Fi (802.11 b/g/n) and Bluetooth Low Energy (BLE) 5.0, making it well-suited for wireless communication applications.
GPIO Pins: It includes numerous General-Purpose Input/Output pins that allow for connectivity with a variety of sensors and actuators.
Security: The device incorporates security features such as AES, SHA, and RSA to enhance device security.
The ESP32C3 is commonly used in applications such as smart home devices, wearables, and IoT nodes, especially in projects requiring Bluetooth connectivity and energy efficiency.

Combine the codes

Combine the code to obtain acceleration & gyro data used in Assignment 11 and the Arduino IDE UART sample code (File->Examples->BLE->UART)

Arudino UART Sample code

/*
    Video: https://www.youtube.com/watch?v=oCMOYS71NIU
    Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
    Ported to Arduino ESP32 by Evandro Copercini

   Create a BLE server that, once we receive a connection, will send periodic notifications.
   The service advertises itself as: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E
   Has a characteristic of: 6E400002-B5A3-F393-E0A9-E50E24DCCA9E - used for receiving data with "WRITE" 
   Has a characteristic of: 6E400003-B5A3-F393-E0A9-E50E24DCCA9E - used to send data with  "NOTIFY"

   The design of creating the BLE server is:
   1. Create a BLE Server
   2. Create a BLE Service
   3. Create a BLE Characteristic on the Service
   4. Create a BLE Descriptor on the characteristic
   5. Start the service.
   6. Start advertising.

   In this example rxValue is the data received (only accessible inside that function).
   And txValue is the data to be sent, in this example just a byte incremented every second. 
*/
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

BLEServer *pServer = NULL;
BLECharacteristic * pTxCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;
uint8_t txValue = 0;

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"


class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
    }
};

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      String rxValue = pCharacteristic->getValue();

      if (rxValue.length() > 0) {
        Serial.println("*********");
        Serial.print("Received Value: ");
        for (int i = 0; i < rxValue.length(); i++)
          Serial.print(rxValue[i]);

        Serial.println();
        Serial.println("*********");
      }
    }
};


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

  // Create the BLE Device
  BLEDevice::init("UART Service");

  // Create the BLE Server
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Create the BLE Service
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // Create a BLE Characteristic
  pTxCharacteristic = pService->createCharacteristic(
                    CHARACTERISTIC_UUID_TX,
                    BLECharacteristic::PROPERTY_NOTIFY
                  );

  pTxCharacteristic->addDescriptor(new BLE2902());

  BLECharacteristic * pRxCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID_RX,
                      BLECharacteristic::PROPERTY_WRITE
                    );

  pRxCharacteristic->setCallbacks(new MyCallbacks());

  // Start the service
  pService->start();

  // Start advertising
  pServer->getAdvertising()->start();
  Serial.println("Waiting a client connection to notify...");
}

void loop() {

  if (deviceConnected) {
    pTxCharacteristic->setValue(&txValue, 1);
    pTxCharacteristic->notify();
    txValue++;
    delay(10); // bluetooth stack will go into congestion, if too many packets are sent
  }

  // disconnecting
  if (!deviceConnected && oldDeviceConnected) {
    delay(500); // give the bluetooth stack the chance to get things ready
    pServer->startAdvertising(); // restart advertising
    Serial.println("start advertising");
    oldDeviceConnected = deviceConnected;
  }
  // connecting
  if (deviceConnected && !oldDeviceConnected) {
    // do stuff here on connecting
    oldDeviceConnected = deviceConnected;
  }
}

Execution Result

This is the execution result of the above code, checked from the eDebugger app connected to the smartphone after running the above code. It can be confirmed that data is being sent from the ESP32C3.
alt text

Next, let's send the text "test" from the smartphone side.The received result is displayed in the Serial Monitor.
alt text alt text

Combined code

ChatGPT Prompt

Please write a code that sends data generated from the source code to a device connected via UART. Refer to the sample code for UART connections.

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

// UUIDs
#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

// MPU-6050 Settings
const int MPU_addr = 0x68;
int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;

BLEServer *pServer = NULL;
BLECharacteristic *pTxCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;

class MyServerCallbacks: public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
    deviceConnected = true;
  }

  void onDisconnect(BLEServer* pServer) {
    deviceConnected = false;
  }
};

void setup() {
  Serial.begin(9600);
  Wire.begin();
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);

  // Create the BLE Device
  BLEDevice::init("MPU-6050 UART Service");

  // Create the BLE Server
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Create the BLE Service
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // Create a BLE Characteristic for transmitting sensor data
  pTxCharacteristic = pService->createCharacteristic(
                        CHARACTERISTIC_UUID_TX,
                        BLECharacteristic::PROPERTY_NOTIFY
                      );
  pTxCharacteristic->addDescriptor(new BLE2902());

  // Start the service
  pService->start();

  // Start advertising
  pServer->getAdvertising()->start();
  Serial.println("Waiting for client connection to notify...");
}

void loop() {
  if (deviceConnected) {
    // Read sensor data
    Wire.beginTransmission(MPU_addr);
    Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
    Wire.endTransmission(false);
    Wire.requestFrom(MPU_addr, 14, true);  // request a total of 14 registers
    AcX = Wire.read() << 8 | Wire.read();    
    AcY = Wire.read() << 8 | Wire.read();
    AcZ = Wire.read() << 8 | Wire.read();
    Tmp = Wire.read() << 8 | Wire.read();
    GyX = Wire.read() << 8 | Wire.read();
    GyY = Wire.read() << 8 | Wire.read();
    GyZ = Wire.read() << 8 | Wire.read();

    // Format the data for accelerometer
    char bufferAcc[64];
    snprintf(bufferAcc, sizeof(bufferAcc), "%d, %d, %d, %d", AcX, AcY, AcZ, Tmp);
    pTxCharacteristic->setValue((uint8_t*)bufferAcc, strlen(bufferAcc));
    pTxCharacteristic->notify();

    // Delay to avoid congestion
    delay(100);

    // Format data for gyroscope
    char bufferGyro[64];
    snprintf(bufferGyro, sizeof(bufferGyro), "%d, %d,   %d", GyX, GyY, GyZ);
    pTxCharacteristic->setValue((uint8_t*)bufferGyro, strlen(bufferGyro));
    pTxCharacteristic->notify();

    delay(333);  // Total delay
  }

  // Handling disconnection
  if (!deviceConnected && oldDeviceConnected) {
    delay(500);
    pServer->startAdvertising();
    Serial.println("Restarting advertising");
    oldDeviceConnected = deviceConnected;
  }

  // handling new connection
  if (deviceConnected && !oldDeviceConnected) {
    oldDeviceConnected = deviceConnected;
  }
}

Execution Result

alt text alt text alt text

Some adjustments were required to get these results.

Selecting the app on the smartphone side: It was difficult to find a smartphone app that could establish a connection, perhaps because there were few apps compatible with BLE. As a result, we settled on eDebugger.

20 bytes limitation: With the BLE standard, there is a limit to the amount of data that can be stored in one packet (usually around 20 bytes), but the sensor data I was sending exceeded this size, causing the data to be truncated midway. I resolved this issue by splitting the data and sending it over two transmissions.

Copyright 2024 Hajime Ito - Creative Commons Attribution Non Commercial

検索
キーワードを入力して検索を始めましょう