The ESP32 is a powerful, low-cost microcontroller that includes built-in Bluetooth capabilities. This makes it well-suited for use in projects that involve wireless communication, such as a project that connects to a smartphone over Bluetooth.
To create a project that connects to a smartphone over Bluetooth using the ESP32, you will need to do the following:
There are several libraries available for the ESP32 that make it easy to configure and control its Bluetooth capabilities, such as Espressif’s ESP32 BLE Python library. These libraries provide APIs for configuring the ESP32 as a Bluetooth peripheral, advertising itself, and managing connections with nearby devices.
In this tutorial we will see how to send a message from the ESP32 card to the smarthpone via bluetooth using the matrix keypad. This is why we will create two programs: a mobile application with App Inventor for the smartphone and a program for the ESP32 card.
ESP32 Card
An ESP32 card is a development board or module that is based on the ESP32 microcontroller developed by Espressif. It typically includes the ESP32 chip, as well as a number of peripheral components, such as RAM, flash memory, power management, and input/output (I/O) pins. ESP32 cards can come in a variety of form factors, including the ESP32-DevKitC, ESP32-WROVER, ESP32-PICO-D4 and more.
ESP32 card can be programmed using various programming languages such as C, C++, Python and MicroPython. The ESP32 has a built-in support for the Arduino IDE which makes it easy to program and debug.
4×4 keypad
A 4×4 keypad is a type of input device that consists of a grid of 4 rows and 4 columns of buttons. It is often used as a simple, low-cost way to add numerical input to a project, such as an access control system or calculator.
The buttons on the keypad are typically labeled with the digits 0-9, as well as a few additional characters such as * and #. Each button is connected to a pin on the keypad’s circuit board, and the pins are connected to a microcontroller or other electronic device.
connecting wires
Wires are used to transmit electrical signals and power to various components such as motors, sensors, and microcontrollers. It’s important to properly route and secure the wires to prevent tangles and damage. There are several methods for doing this, including using cable ties, clamps, and wire looms. It’s also a good idea to use different colors or labeling to identify the different wires and their functions. When connecting wires in a robot, it’s important to follow proper safety procedures, such as using the correct wire stripper and connectors, and wearing protective equipment such as gloves and safety glasses.
test plate
A test plate is a type of device used in robotics to test the functionality and performance of various components or systems. It is typically a physical platform or structure that is designed to hold and support various test items or devices, such as sensors, actuators, motors, or other types of mechanical or electrical components. Test plates can be used to simulate different environments or conditions, such as temperature, humidity, vibration, or other factors, in order to evaluate the performance of the components or systems being tested. They can also be used to perform a variety of diagnostic or diagnostic tests, such as stress testing, endurance testing, or other types of evaluations.
We connect the 8 outputs of the keyboard to the 8 pins of the ESP32 card following this order: D2, D4, D5, D18, D19, D16, D15 and D23.
Here are the programs that connect the ESP32 board to the smartphone and send a message by bluetooth using the 4×4 matrix keypad.
boot.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
from machine import Pin from esp_ble_uart import * from time import sleep import utime import machine import time nom = 'ESP32-ble-uart-gcworks' UUID_UART = '6E400001-B5A3-F393-E0A9-E50E24DCCA9E' UUID_TX = '6E400003-B5A3-F393-E0A9-E50E24DCCA9E' UUID_RX = '6E400002-B5A3-F393-E0A9-E50E24DCCA9E' val_rx = "12" uart = Bleuart(nom, UUID_UART, UUID_TX, UUID_RX) uart.close() WIDTH = 128 HEIGHT = 64 # CONSTANTS KEY_UP = const(0) KEY_DOWN = const(1) keys = [['1', '2', '3', 'A'], ['4', '5', '6', 'B'], ['7', '8', '9', 'C'], ['*', '0', '#', 'D']] # Pin names for Pico cols = [19,16,15,23] rows = [2,4,5,18] # set pins for rows as outputs row_pins = [Pin(pin_name, mode=Pin.OUT) for pin_name in rows] # set pins for cols as inputs col_pins = [Pin(pin_name, mode=Pin.IN, pull=Pin.PULL_DOWN) for pin_name in cols] def init(): for row in range(0,4): for col in range(0,4): row_pins[row].value(0) def scan(row, col): """ scan the keypad """ # set the current column to high row_pins[row].value(1) key = None # check for keypressed events if col_pins[col].value() == KEY_DOWN: key = KEY_DOWN if col_pins[col].value() == KEY_UP: key = KEY_UP row_pins[row].value(0) # return the key state return key print("starting") def rcp_rx(): global val_rx if uart.any(): while uart.any(): val_rx = uart.read().decode().strip() print('sur rx: ', val_rx) # Interruption : affichage donn闁肩厧宕榮 re闁煎墽鎯甧s def env_tx(val_tx): uart.write(str(val_tx) + '\n') print("tx", val_tx) # set all the columns to low init() message="" while True: uart.irq(handler=rcp_rx) for row in range(4): for col in range(4): key = scan(row, col) if key == KEY_DOWN: print("Key Pressed", keys[row][col]) message=message+keys[row][col] env_tx(message) # sending the character associated with the press key to smartphone last_key_press = keys[row][col] time.sleep_ms(1000) |
esp_ble_uart.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
from micropython import const import struct import bluetooth # Advertising payloads are repeated packets of the following form: # 1 byte data length (N + 1) # 1 byte type (see constants below) # N bytes type-specific data _ADV_TYPE_FLAGS = const(0x01) _ADV_TYPE_NAME = const(0x09) _ADV_TYPE_UUID16_COMPLETE = const(0x3) _ADV_TYPE_UUID32_COMPLETE = const(0x5) _ADV_TYPE_UUID128_COMPLETE = const(0x7) _ADV_TYPE_UUID16_MORE = const(0x2) _ADV_TYPE_UUID32_MORE = const(0x4) _ADV_TYPE_UUID128_MORE = const(0x6) _ADV_TYPE_APPEARANCE = const(0x19) _IRQ_CENTRAL_CONNECT = const(1 << 0) _IRQ_CENTRAL_DISCONNECT = const(1 << 1) _IRQ_GATTS_WRITE = const(1 << 2) # org.bluetooth.characteristic.gap.appearance.xml _ADV_APPEARANCE_GENERIC_COMPUTER = const(128) # Generate a payload to be passed to gap_advertise(adv_data=...). def advertising_payload(limited_disc=False, br_edr=False, name=None, services=None, appearance=0): payload = bytearray() def _append(adv_type, value): nonlocal payload payload += struct.pack('BB', len(value) + 1, adv_type) + value _append(_ADV_TYPE_FLAGS, struct.pack('B', (0x01 if limited_disc else 0x02) + (0x00 if br_edr else 0x04))) if name: _append(_ADV_TYPE_NAME, name) if services: for uuid in services: b = bytes(uuid) if len(b) == 2: _append(_ADV_TYPE_UUID16_COMPLETE, b) elif len(b) == 4: _append(_ADV_TYPE_UUID32_COMPLETE, b) elif len(b) == 16: _append(_ADV_TYPE_UUID128_COMPLETE, b) # See org.bluetooth.characteristic.gap.appearance.xml _append(_ADV_TYPE_APPEARANCE, struct.pack('<h', appearance)) return payload def decode_field(payload, adv_type): i = 0 result = [] while i + 1 < len(payload): if payload[i + 1] == adv_type: result.append(payload[i + 2:i + payload[i] + 1]) i += 1 + payload[i] return result def decode_name(payload): n = decode_field(payload, _ADV_TYPE_NAME) return str(n[0], 'utf-8') if n else '' def decode_services(payload): services = [] for u in decode_field(payload, _ADV_TYPE_UUID16_COMPLETE): services.append(bluetooth.UUID(struct.unpack('<h', u)[0])) for u in decode_field(payload, _ADV_TYPE_UUID32_COMPLETE): services.append(bluetooth.UUID(struct.unpack('<d', u)[0])) for u in decode_field(payload, _ADV_TYPE_UUID128_COMPLETE): services.append(bluetooth.UUID(u)) return services class Bleuart: def __init__(self, name, UUID_UART, UUID_TX, UUID_RX, rxbuf=100): _UART_UUID = bluetooth.UUID(UUID_UART,) _UART_TX = (bluetooth.UUID(UUID_TX), bluetooth.FLAG_NOTIFY,) _UART_RX = (bluetooth.UUID(UUID_RX), bluetooth.FLAG_WRITE,) _UART_SERVICE = (_UART_UUID, (_UART_TX, _UART_RX,),) self._ble = bluetooth.BLE() self._ble.active(True) self._ble.irq(handler=self._irq) ((self._tx_handle, self._rx_handle,),) = self._ble.gatts_register_services((_UART_SERVICE,)) # Increase the size of the rx buffer and enable append mode. self._ble.gatts_set_buffer(self._rx_handle, rxbuf, True) self._connections = set() self._rx_buffer = bytearray() self._handler = None # Optionally add services=[_UART_UUID], but this is likely to make the payload too large. self._payload = advertising_payload(name=name, appearance=_ADV_APPEARANCE_GENERIC_COMPUTER) self._advertise() def irq(self, handler): self._handler = handler def _irq(self, event, data): # Track connections so we can send notifications. if event == _IRQ_CENTRAL_CONNECT: conn_handle, _, _, = data self._connections.add(conn_handle) elif event == _IRQ_CENTRAL_DISCONNECT: conn_handle, _, _, = data if conn_handle in self._connections: self._connections.remove(conn_handle) # Start advertising again to allow a new connection. self._advertise() elif event == _IRQ_GATTS_WRITE: conn_handle, value_handle, = data if conn_handle in self._connections and value_handle == self._rx_handle: self._rx_buffer += self._ble.gatts_read(self._rx_handle) if self._handler: self._handler() def any(self): return len(self._rx_buffer) def read(self, sz=None): if not sz: sz = len(self._rx_buffer) result = self._rx_buffer[0:sz] self._rx_buffer = self._rx_buffer[sz:] return result def write(self, data): for conn_handle in self._connections: self._ble.gatts_notify(conn_handle, self._tx_handle, data) def close(self): for conn_handle in self._connections: self._ble.gap_disconnect(conn_handle) self._connections.clear() def _advertise(self, interval_us=500000): self._ble.gap_advertise(interval_us, adv_data=self._payload) |
We will create a mobile application named ‘esp32_clavier’ with App Inventor which allows to receive a message from the ESP32 card.
We therefore suggest that you create the design of the application, with the following visual:
To program the application, App Inventor offers us to use the Blocks space which allows you to create a program in the form of a block diagram. Very easy to use but requires some programming logic.
Here is the program of the application made in the Blocks space of the App Inventor:
nylto.org 06-08-2323
It's a pity you don't have a donate button! I'd without a doubt donate to this outstanding blog! I suppose for now i'll settle for bookmarking and adding your RSS feed to my Google account. I look forward to fresh updates and will share this website with my Facebook group. Chat soon!