-
1Introduction
In this tutorial, I'm going to show you how to transfer the sensor readings between two ESP32 Boards via Bluetooth protocol.
Things that you need:
- M5Stick C
- M5Stamp Pico
- LM35 Temperature Sensor
-
2Get PCBs for Your Projects Manufactured
You must check out PCBWAY for ordering PCBs online for cheap!You get 10 good-quality PCBs manufactured and shipped to your doorstep for cheap. You will also get a discount on shipping on your first order. Upload your Gerber files onto PCBWAY to get them manufactured with good quality and quick turnaround time. PCBWay now could provide a complete product solution, from design to enclosure production. Check out their online Gerber viewer function. With reward points, you can get free stuff from their gift shop.
-
3M5Stick C (Source from M5Stack)
M5StickC is a mini M5Stack, powered by ESP32. It is a portable, easy-to-use, open source, IoT development board. What it can do? This tiny block is able to realize your idea, enlighten your creativity, and help with your IoT prototyping in a very short time. It will take away a lot of pains from the development process.M5stickC is one of the core devices in M5Stack product series.
It is built in a continually growing hardware and software ecosystem. It has a lot of compatible modules and units, as well as the open source code & engineering communities that will help you maximize your benefits in every step of the developing process.
-------------------------------------------->Buy Link<----------------------------------------------------
Power switch operation:
Power on :Press power button for 2 seconds
- Power on :Press power button for 2 seconds
Power off :Press power button for 6 seconds
- Power off :Press power button for 6 seconds
Notice:
- Baud rate supported by M5StickC: 1200 ~115200, 250K, 500K, 750K, 1500K
Product Features
- ESP32-based
- Built-in 6-Axis IMU
- Red LED
- IR transmitter
- Microphone
- Buttons, LCD(0.96 inch)
- Built-in Lipo Battery
- Extendable Socket
- Wearable & Wall mounted
Compatible with multi-platform development:
-
4M5Stamp Pico (Source from M5Stack)
STAMP-PICO features an ultra-compact design with two low-power Xtensa® 32-bit LX6 microprocessors at 240MHz on a PCB as tiny and delicate as a postage stamp. low power consumption. It is ideal for any space-constrained or battery-powered devices such as wearables, medical devices, sensors, and other IoT devices.
1, MULTIFORM: 5 options of installation, means endless possibilities! (SMT, DIP, flywire, grove interface), with a high-temperature resistant plastic shell, 3D antenna and components can be better protected.
- 1, MULTIFORM: 5 options of installation, means endless possibilities! (SMT, DIP, flywire, grove interface), with a high-temperature resistant plastic shell, 3D antenna and components can be better protected.
2, LOW-CODE DEVELOPMENT: STAMP-PICO supports UIFlow graphical programming platform, scripting-free, cloud push; and fully compatible with Arduino, MicroPython, ESP32-IDF, and other mainstream development platforms to quickly build various applications.
- 2, LOW-CODE DEVELOPMENT: STAMP-PICO supports UIFlow graphical programming platform, scripting-free, cloud push; and fully compatible with Arduino, MicroPython, ESP32-IDF, and other mainstream development platforms to quickly build various applications.
3, HIGH INTEGRATION: STAMP-PICO contains 5V->3.3V DC/DC port, GPIOx12, programmable RGB light x1, button x1, finely tuned RF circuit, providing stable and reliable wireless communication.
- 3, HIGH INTEGRATION: STAMP-PICO contains 5V->3.3V DC/DC port, GPIOx12, programmable RGB light x1, button x1, finely tuned RF circuit, providing stable and reliable wireless communication.
4, STRONG EXPANDABILITY: Easy access to M5Stack's hardware and software ecology system: a wealth of sensors, actuators, functional modules, and accessories to choose from, Extremely fast adaptation.
- 4, STRONG EXPANDABILITY: Easy access to M5Stack's hardware and software ecology system: a wealth of sensors, actuators, functional modules, and accessories to choose from, Extremely fast adaptation.
-------------------------------------------->Buy Link<--------------------------------------------
Product Features
- Chip-set:ESP32-PICO-D4 (2.4GHz Wi-Fi dual mode)
- Support UIFlow graphical programming
- Multi-IO pinout, support multiple application forms (SMT, DIP, fly-by-wire)
- Integrated programmable RGB LEDs and buttons
- Miniature module
-
5LM35 Temperature Sensor
The LM35 is an integrated analog temperature sensor whose output is proportional to degrees centigrade. Sensors such as the LM35 do not require external calibration or trimming to provide typical accuracy. LM35's low output impedance, linear output, and accurate inherent calibration make it especially easy to interface with readouts and control circuits.
-
6Hardware Connections
Connect the LM35's output pin to M5Stamp's 36th pin and LM35's power to 5 V and GND to GND of the PICO.
- VOUT - > G36
- GND - > GND
- VCC - > 5V
That's all we need to this tutorial.
-
7Transmitter Programming
In this tutorial, M5Stamp pico will act as a transmitter, and it will send a temperature reading to the transmitter once it connected the transmitter.
#include <BLEDevice.h> #include <BLEServer.h> #include <BLEUtils.h> #include <BLE2902.h> #include <FastLED.h> // LED Count #define NUM_LEDS 1 #define DATA_PIN 27 // Define the array of leds CRGB leds[NUM_LEDS]; #define Button 39 //BLE server name #define bleServerName "M5" //LM35 #define ADC_VREF_mV 3300.0 // in millivolt #define ADC_RESOLUTION 4096.0 #define PIN_LM35 36 // ESP32 pin GIOP36 (ADC0) connected to LM35 float temp; float tempF; float hum; // Timer variables unsigned long lastTime = 0; unsigned long timerDelay = 30000; bool deviceConnected = false; #define SERVICE_UUID "91bad492-b950-4226-aa2b-4ede9fa42f59" // Temperature Characteristic and Descriptor BLECharacteristic bmeTemperatureCelsiusCharacteristics("cba1d466-344c-4be3-ab3f-189f80dd7518", BLECharacteristic::PROPERTY_NOTIFY); BLEDescriptor bmeTemperatureCelsiusDescriptor(BLEUUID((uint16_t)0x2902)); //Setup callbacks onConnect and onDisconnect class MyServerCallbacks: public BLEServerCallbacks { void onConnect(BLEServer* pServer) { deviceConnected = true; }; void onDisconnect(BLEServer* pServer) { deviceConnected = false; } }; void setup() { // Start serial communication Serial.begin(115200); FastLED.addLeds<SK6812, DATA_PIN, RGB>(leds, NUM_LEDS); pinMode(Button, INPUT); // Create the BLE Device BLEDevice::init(bleServerName); // Create the BLE Server BLEServer *pServer = BLEDevice::createServer(); pServer->setCallbacks(new MyServerCallbacks()); // Create the BLE Service BLEService *bmeService = pServer->createService(SERVICE_UUID); // Create BLE Characteristics and Create a BLE Descriptor bmeService->addCharacteristic(&bmeTemperatureCelsiusCharacteristics); bmeTemperatureCelsiusDescriptor.setValue("BME temperature Celsius"); bmeTemperatureCelsiusCharacteristics.addDescriptor(&bmeTemperatureCelsiusDescriptor); // Start the service bmeService->start(); // Start advertising BLEAdvertising *pAdvertising = BLEDevice::getAdvertising(); pAdvertising->addServiceUUID(SERVICE_UUID); pServer->getAdvertising()->start(); Serial.println("Waiting a client connection to notify..."); } void loop() { static bool State; State = digitalRead(Button); if (State == 0) { ESP.restart(); } if (deviceConnected) { if ((millis() - lastTime) > timerDelay) { // Turn the LED on, then pause leds[0] = 0xf00000; FastLED.show(); delay(2000); // read the ADC value from the temperature sensor int adcVal = analogRead(PIN_LM35); // convert the ADC value to voltage in millivolt float milliVolt = adcVal * (ADC_VREF_mV / ADC_RESOLUTION); // convert the voltage to the temperature in °C temp = milliVolt / 10; static char temperatureCTemp[6]; dtostrf(temp, 6, 2, temperatureCTemp); //Set temperature Characteristic value and notify connected client bmeTemperatureCelsiusCharacteristics.setValue(temperatureCTemp); bmeTemperatureCelsiusCharacteristics.notify(); // Now turn the LED off, then pause leds[0] = 0x00f000; FastLED.show(); Serial.print("Temperature Celsius: "); Serial.print(temp); Serial.println(" ºC"); lastTime = millis(); } } }
In this code if you need to change your BLE Server name then change this line as per your needs:
And this lines of code contains the basic LM35's calibration readings, don't change these.
This is the BLE Service ID to the transmitter:
Here is the service ID for the temperature data.
M5Stamp Pico doesn't have any reset button, but it has a user defined button, here I used that one to reset the board.
Finally, upload the code to the M5Stamp Pico, make sure you have selected a correct board settings:
-
8Receiver
In this tutorial, M5Stick C will act as a transmitter, and it will receive the temperature reading from the transmitter.
#include <M5StickC.h> #include "BLEDevice.h" //BLE Server name #define bleServerName "M5" /* UUID's of the service, characteristic that we want to read*/ // BLE Service static BLEUUID bmeServiceUUID("91bad492-b950-4226-aa2b-4ede9fa42f59"); //Temperature Celsius Characteristic static BLEUUID temperatureCharacteristicUUID("cba1d466-344c-4be3-ab3f-189f80dd7518"); //Flags stating if should begin connecting and if the connection is up static boolean doConnect = false; static boolean connected = false; //Address of the peripheral device. Address will be found during scanning... static BLEAddress *pServerAddress; //Characteristicd that we want to read static BLERemoteCharacteristic* temperatureCharacteristic; //Activate notify const uint8_t notificationOn[] = {0x1, 0x0}; const uint8_t notificationOff[] = {0x0, 0x0}; //Variables to store temperature and humidity char* temperatureChar; //Flags to check whether new temperature and humidity readings are available boolean newTemperature = false; //Connect to the BLE Server that has the name, Service, and Characteristics bool connectToServer(BLEAddress pAddress) { BLEClient* pClient = BLEDevice::createClient(); // Connect to the remove BLE Server. pClient->connect(pAddress); Serial.println(" - Connected to server"); // Obtain a reference to the service we are after in the remote BLE server. BLERemoteService* pRemoteService = pClient->getService(bmeServiceUUID); if (pRemoteService == nullptr) { Serial.print("Failed to find our service UUID: "); Serial.println(bmeServiceUUID.toString().c_str()); return (false); } // Obtain a reference to the characteristics in the service of the remote BLE server. temperatureCharacteristic = pRemoteService->getCharacteristic(temperatureCharacteristicUUID); if (temperatureCharacteristic == nullptr) { Serial.print("Failed to find our characteristic UUID"); return false; } Serial.println(" - Found our characteristics"); //Assign callback functions for the Characteristics temperatureCharacteristic->registerForNotify(temperatureNotifyCallback); return true; } //Callback function that gets called, when another device's advertisement has been received class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { void onResult(BLEAdvertisedDevice advertisedDevice) { if (advertisedDevice.getName() == bleServerName) { //Check if the name of the advertiser matches advertisedDevice.getScan()->stop(); //Scan can be stopped, we found what we are looking for pServerAddress = new BLEAddress(advertisedDevice.getAddress()); //Address of advertiser is the one we need doConnect = true; //Set indicator, stating that we are ready to connect Serial.println("Device found. Connecting!"); } } }; //When the BLE Server sends a new temperature reading with the notify property static void temperatureNotifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify) { //store temperature value temperatureChar = (char*)pData; newTemperature = true; } //function that prints the latest sensor readings in the OLED display void printReadings() { M5.update(); //Erase the previous contents in the display M5.Lcd.fillScreen(BLACK); M5.Lcd.setTextColor(RED); M5.Lcd.setCursor(20, 18); M5.Lcd.setTextSize(1.8); M5.Lcd.print("[ "); M5.Lcd.setTextColor(GREEN); M5.Lcd.print("BLE Smart Flask"); M5.Lcd.setTextColor(RED); M5.Lcd.print(" ]"); M5.Lcd.setCursor(18, 40); M5.Lcd.setTextColor(GREEN); Serial.print("Temperature:"); M5.Lcd.print("Temperature: "); Serial.println(temperatureChar); M5.Lcd.print(temperatureChar); M5.Lcd.print(" C"); M5.Lcd.setCursor(15, 55); M5.Lcd.setTextColor(RED); M5.Lcd.print("---------------------"); float x = atof(temperatureChar); if (x >= 35.0) { Serial.println("It may be a over heat"); M5.Lcd.setCursor(15, 65); M5.Lcd.setTextColor(RED); M5.Lcd.print("It's may be over heat"); } else { Serial.println("It's ok to drink"); M5.Lcd.setCursor(30, 65); M5.Lcd.setTextColor(GREEN); M5.Lcd.print("It's ok to drink"); } M5.Lcd.setCursor(15, 75); M5.Lcd.setTextColor(RED); M5.Lcd.print("---------------------"); } void setup() { M5.begin(); M5.Lcd.setRotation(3); M5.Axp.ScreenBreath(10); M5.Lcd.setTextColor(RED); M5.Lcd.setCursor(10, 35); M5.Lcd.setTextSize(1.8); //Start serial communication Serial.begin(115200); Serial.println("Starting Arduino BLE Client application..."); //Init BLE device BLEDevice::init(""); BLEScan* pBLEScan = BLEDevice::getScan(); pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); pBLEScan->setActiveScan(true); pBLEScan->start(30); } void loop() { if (doConnect == true) { if (connectToServer(*pServerAddress)) { Serial.println("We are now connected to the BLE Server."); M5.Lcd.print("Connected to BLE Server"); //Activate the Notify property of each Characteristic temperatureCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationOn, 2, true); connected = true; } else { Serial.println("We have failed to connect to the server; Restart your device to scan for nearby BLE server again."); M5.Lcd.print("Not Connected"); } doConnect = false; } //if new temperature readings are available, print in the OLED if (newTemperature) { newTemperature = false; printReadings(); } }
In this code, rename the transmitter name same as yours, and make sure the device service ID and Temperature Data ID are match with the transmitter.
I have added some lines of code to show the Temperature reading to the TFT Display.
Once done, the needed changes, upload the code to the M5Stick C.
After uploaded the code once, press the rest button on the transmitter and the receiver and monitor the serial outputs.
The sensor readings will be uploaded each 10 seconds
I added this with my coffee flask.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.