Useful Links:
~ Install CircuitPython 7.2.0 on ESP32-S3 (ESP32-S3-DevKitC-1), using esptool v3.2 on Linux Mint
Exercise of using
CircuitPython 7.2.0 on ESP32-C3-DevKitM-1
with 1.44" 128x128 ST7735 SPI TFT (KMR1441_SPI V2):
- display bmp in
slideshow
- display bmp using OnDiskBitmap/adafruit_imageload
The
display module used in this exercise is a with 1.44" 128x128 SPI TFT marked
"KMR1441_SPI V2".
ST7735 ESP32-C3-DevKitM-1
------------------------------
VCC 3V3
GND GND
CS IO10
RESET IO1
A0 IO0
SDA IO3
SCK IO2
LED 3V3
Library:
Visit
CircuitPython Library page
to download Bundle for Version 7.x, and extract it.
Copy the
libraries to lib folder in Circuit device.
- adafruit_st7735r.mpy
-
adafruit_display_text folder
- adafruit_slideshow.mpy
-
adafruit_imageload folder
Exercise code:
cpyESP32C3_st7735_128x128.py, functional testing.
"""
CircuitPython 7.2.0 exercise run on ESP32-C3-DevKitM-1
with 1.44" 128x128 (KMR1441_SPI V2)
ref:
adafruit/Adafruit_CircuitPython_ST7735R
https://github.com/adafruit/Adafruit_CircuitPython_ST7735R
"""
from sys import implementation as sysImplementation
import time
import os
import board
import busio
import displayio
import terminalio
from adafruit_st7735r import ST7735R as TFT_ST7735
from adafruit_st7735r import __name__ as ST7735_NAME
from adafruit_st7735r import __version__ as ST7735_VERSION
from adafruit_display_text import label
# Release any resources currently in use for the displays
displayio.release_displays()
#Connection between ESP32-C3 and SPI ST7735 display
#marking on display
tft_sck = board.IO2 #SCK
tft_mosi = board.IO3 #SDA
tft_dc = board.IO0 #A0
tft_reset = board.IO1 #RESET
tft_cs = board.IO10 #CS
#Backlight (LED) connect to ESP32-C3 3V3
#TFT VCC - ESP32-C3 3V3
#TFT GND - ESP32-C3 GND
tft_spi = busio.SPI(clock=tft_sck, MOSI=tft_mosi)
display_bus = displayio.FourWire(
tft_spi, command=tft_dc, chip_select=tft_cs, reset=tft_reset)
display = TFT_ST7735(display_bus, width=128, height=128,
rotation=90,
bgr=True)
strSys = sysImplementation[0] + ' ' + \
str(sysImplementation[1][0]) +'.'+ \
str(sysImplementation[1][1]) +'.'+ \
str(sysImplementation[1][2])
print("==========================================")
print(strSys)
print('run on ' + os.uname()[4])
print('using', ST7735_NAME, ST7735_VERSION)
print("==========================================")
print(type(display))
print("display.width: ", display.width)
print("display.height: ", display.height)
# Make the display context
splash = displayio.Group()
display.show(splash)
color_bitmap = displayio.Bitmap(display.width, display.height, 1)
color_palette = displayio.Palette(1)
color_palette[0] = 0x000000
time.sleep(1)
bg_sprite = displayio.TileGrid(color_bitmap,
pixel_shader=color_palette, x=0, y=0)
splash.append(bg_sprite)
for c in [["RED", 0xFF0000],
["GREEN", 0x00FF00],
["BLUE", 0x0000FF]]:
print(c[0], " : ", hex(c[1]))
color_palette[0] = c[1]
time.sleep(2)
splash.remove(bg_sprite)
#---
# Make the display context
#splash = displayio.Group()
#display.show(splash)
color_bitmap = displayio.Bitmap(display.width, display.height, 1)
color_palette = displayio.Palette(1)
color_palette[0] = 0x00FF00
bg_sprite = displayio.TileGrid(color_bitmap,
pixel_shader=color_palette, x=0, y=0)
splash.append(bg_sprite)
# Draw a smaller inner rectangle
inner_bitmap = displayio.Bitmap(display.width-2, display.height-2, 1)
inner_palette = displayio.Palette(1)
inner_palette[0] = 0x0000FF
inner_sprite = displayio.TileGrid(inner_bitmap,
pixel_shader=inner_palette, x=1, y=1)
splash.append(inner_sprite)
# Draw a label
text_group1 = displayio.Group(scale=1, x=5, y=10)
text1 = "ESP32-C3"
text_area1 = label.Label(terminalio.FONT, text=text1, color=0xFF0000)
text_group1.append(text_area1) # Subgroup for text scaling
# Draw a label
text_group2 = displayio.Group(scale=1, x=5, y=25)
text2 = strSys
text_area2 = label.Label(terminalio.FONT, text=text2, color=0xFFFFFF)
text_group2.append(text_area2) # Subgroup for text scaling
# Draw a label
text_group3 = displayio.Group(scale=1, x=5, y=40)
text3 = ST7735_NAME
text_area3 = label.Label(terminalio.FONT, text=text3, color=0x0000000)
text_group3.append(text_area3) # Subgroup for text scaling
# Draw a label
text_group4 = displayio.Group(scale=1, x=5, y=55)
text4 = ST7735_VERSION
text_area4 = label.Label(terminalio.FONT, text=text4, color=0x000000)
text_group4.append(text_area4) # Subgroup for text scaling
text_group5 = displayio.Group(scale=1, x=5, y=70)
text5 = str(display.width) + " x " + str(display.height)
text_area5 = label.Label(terminalio.FONT, text=text5, color=0x000000)
text_group5.append(text_area5) # Subgroup for text scaling
splash.append(text_group1)
splash.append(text_group2)
splash.append(text_group3)
splash.append(text_group4)
splash.append(text_group5)
time.sleep(3.0)
rot = 90
while True:
time.sleep(5.0)
rot = rot + 90
if (rot>=360):
rot = 0
display.rotation = rot
cpyESP32C3_st7735_slideshow.py, Test with exercise in "Creating Slideshows in CircuitPython".
"""
CircuitPython 7.2.0 exercise run on ESP32-C3-DevKitM-1
with 1.44" 128x128 (KMR1441_SPI V2)
- slideshow
ref:
adafruit/Adafruit_CircuitPython_ST7735R
https://github.com/adafruit/Adafruit_CircuitPython_ST7735R
"""
from sys import implementation as sysImplementation
import time
import os
import board
import busio
import displayio
import terminalio
from adafruit_st7735r import ST7735R as TFT_ST7735
from adafruit_st7735r import __name__ as ST7735_NAME
from adafruit_st7735r import __version__ as ST7735_VERSION
from adafruit_display_text import label
# Release any resources currently in use for the displays
displayio.release_displays()
#Connection between ESP32-C3 and SPI ST7735 display
#marking on display
tft_sck = board.IO2 #SCK
tft_mosi = board.IO3 #SDA
tft_dc = board.IO0 #A0
tft_reset = board.IO1 #RESET
tft_cs = board.IO10 #CS
#Backlight (LED) connect to ESP32-C3 3V3
#TFT VCC - ESP32-C3 3V3
#TFT GND - ESP32-C3 GND
tft_spi = busio.SPI(clock=tft_sck, MOSI=tft_mosi)
display_bus = displayio.FourWire(
tft_spi, command=tft_dc, chip_select=tft_cs, reset=tft_reset)
display = TFT_ST7735(display_bus, width=128, height=128,
rotation=90,
bgr=True)
strSys = sysImplementation[0] + ' ' + \
str(sysImplementation[1][0]) +'.'+ \
str(sysImplementation[1][1]) +'.'+ \
str(sysImplementation[1][2])
print("==========================================")
print(strSys)
print('run on ' + os.uname()[4])
print('using', ST7735_NAME, ST7735_VERSION)
print("==========================================")
print(type(display))
print("display.width: ", display.width)
print("display.height: ", display.height)
#===============================
# SPDX-FileCopyrightText: 2019 Anne Barela for Adafruit Industries
#
# SPDX-License-Identifier: MIT
# CircuitPython Slideshow - uses the adafruit_slideshow.mpy library
#import board
from adafruit_slideshow import PlayBackOrder, SlideShow
# Create the slideshow object that plays through once alphabetically.
slideshow = SlideShow(display,
folder="/images",
loop=True,
order=PlayBackOrder.ALPHABETICAL,
dwell=5)
while slideshow.update():
pass
cpyESP32C3_st7735_OnDiskBitmap.py, test with OnDiskBitmap example in "Display a Bitmap".
"""
CircuitPython 7.2.0 exercise run on ESP32-C3-DevKitM-1
with 1.44" 128x128 (KMR1441_SPI V2)
- OnDiskBitmap
ref:
adafruit/Adafruit_CircuitPython_ST7735R
https://github.com/adafruit/Adafruit_CircuitPython_ST7735R
"""
from sys import implementation as sysImplementation
import time
import os
import board
import busio
import displayio
import terminalio
from adafruit_st7735r import ST7735R as TFT_ST7735
from adafruit_st7735r import __name__ as ST7735_NAME
from adafruit_st7735r import __version__ as ST7735_VERSION
from adafruit_display_text import label
# Release any resources currently in use for the displays
displayio.release_displays()
#Connection between ESP32-C3 and SPI ST7735 display
#marking on display
tft_sck = board.IO2 #SCK
tft_mosi = board.IO3 #SDA
tft_dc = board.IO0 #A0
tft_reset = board.IO1 #RESET
tft_cs = board.IO10 #CS
#Backlight (LED) connect to ESP32-C3 3V3
#TFT VCC - ESP32-C3 3V3
#TFT GND - ESP32-C3 GND
tft_spi = busio.SPI(clock=tft_sck, MOSI=tft_mosi)
display_bus = displayio.FourWire(
tft_spi, command=tft_dc, chip_select=tft_cs, reset=tft_reset)
display = TFT_ST7735(display_bus, width=128, height=128,
rotation=90,
bgr=True)
strSys = sysImplementation[0] + ' ' + \
str(sysImplementation[1][0]) +'.'+ \
str(sysImplementation[1][1]) +'.'+ \
str(sysImplementation[1][2])
print("==========================================")
print(strSys)
print('run on ' + os.uname()[4])
print('using', ST7735_NAME, ST7735_VERSION)
print("==========================================")
print(type(display))
print("display.width: ", display.width)
print("display.height: ", display.height)
#===============================
# SPDX-FileCopyrightText: 2019 Carter Nelson for Adafruit Industries
#
# SPDX-License-Identifier: MIT
#import board
#import displayio
#display = board.DISPLAY
# Future method for CircuitPython 7 onwards
# Setup the file as the bitmap data source
bitmap = displayio.OnDiskBitmap("images/002.bmp")
# Create a TileGrid to hold the bitmap
tile_grid = displayio.TileGrid(bitmap, pixel_shader=bitmap.pixel_shader)
# Create a Group to hold the TileGrid
group = displayio.Group()
# Add the TileGrid to the Group
group.append(tile_grid)
# Add the Group to the Display
display.show(group)
# Loop forever so you can enjoy your image
while True:
pass
cpyESP32C3_st7735_ImageLoad.py, test with example of ImageLoad in "Display a Bitmap"
"""
CircuitPython 7.2.0 exercise run on ESP32-C3-DevKitM-1
with 1.44" 128x128 (KMR1441_SPI V2)
- ImageLoad
ref:
adafruit/Adafruit_CircuitPython_ST7735R
https://github.com/adafruit/Adafruit_CircuitPython_ST7735R
"""
from sys import implementation as sysImplementation
import time
import os
import board
import busio
import displayio
import terminalio
from adafruit_st7735r import ST7735R as TFT_ST7735
from adafruit_st7735r import __name__ as ST7735_NAME
from adafruit_st7735r import __version__ as ST7735_VERSION
from adafruit_display_text import label
# Release any resources currently in use for the displays
displayio.release_displays()
#Connection between ESP32-C3 and SPI ST7735 display
#marking on display
tft_sck = board.IO2 #SCK
tft_mosi = board.IO3 #SDA
tft_dc = board.IO0 #A0
tft_reset = board.IO1 #RESET
tft_cs = board.IO10 #CS
#Backlight (LED) connect to ESP32-C3 3V3
#TFT VCC - ESP32-C3 3V3
#TFT GND - ESP32-C3 GND
tft_spi = busio.SPI(clock=tft_sck, MOSI=tft_mosi)
display_bus = displayio.FourWire(
tft_spi, command=tft_dc, chip_select=tft_cs, reset=tft_reset)
display = TFT_ST7735(display_bus, width=128, height=128,
rotation=90,
bgr=True)
strSys = sysImplementation[0] + ' ' + \
str(sysImplementation[1][0]) +'.'+ \
str(sysImplementation[1][1]) +'.'+ \
str(sysImplementation[1][2])
print("==========================================")
print(strSys)
print('run on ' + os.uname()[4])
print('using', ST7735_NAME, ST7735_VERSION)
print("==========================================")
print(type(display))
print("display.width: ", display.width)
print("display.height: ", display.height)
#===============================
# SPDX-FileCopyrightText: 2019 Carter Nelson for Adafruit Industries
#
# SPDX-License-Identifier: MIT
#import board
#import displayio
import adafruit_imageload
#display = board.DISPLAY
bitmap, palette = adafruit_imageload.load("images/003i.bmp",
bitmap=displayio.Bitmap,
palette=displayio.Palette)
# Create a TileGrid to hold the bitmap
tile_grid = displayio.TileGrid(bitmap, pixel_shader=palette)
# Create a Group to hold the TileGrid
group = displayio.Group()
# Add the TileGrid to the Group
group.append(tile_grid)
# Add the Group to the Display
display.show(group)
# Loop forever so you can enjoy your image
while True:
pass
$ esptool.py --port /dev/ttyUSB0 erase_flash
$ esptool.py --chip esp32c3 --port /dev/ttyUSB0 write_flash \-z 0x0 \
adafruit-circuitpython-espressif_esp32c3_devkitm_1_n4-en_US-7.2.0.bin
"""
CircuitPython 7.2.0 exercise run on ESP32-C3,
get system info.
"""
import board
import sys
import os
"""
ref:
The entire table of ANSI color codes working in C:
https://gist.github.com/RabaDabaDoba/145049536f815903c79944599c6f952a
"""
class color:
RED = '\033[1;31;48m'
BLUE = '\033[1;34;48m'
BLACK = '\033[1;30;48m'
END = '\033[1;37;0m'
print(board.board_id)
print(sys.implementation[0] + ' ' +
str(sys.implementation[1][0]) +'.'+
str(sys.implementation[1][1]) +'.'+
str(sys.implementation[1][2]))
print("==========================================")
info = color.RED + \
sys.implementation[0] + ' ' + \
os.uname()[3] + color.END + '\n' + \
'run on ' + color.BLUE + os.uname()[4] + color.END
print(info)
print("==========================================")
print()
import time
import os
import microcontroller
import neopixel
import board
def cycleNeopixel(wait):
for r in range(255):
pixel[0] = (r, 0, 0)
time.sleep(wait)
for r in range(255, 0, -1):
pixel[0] = (r, 0, 0)
time.sleep(wait)
for g in range(255):
pixel[0] = (0, g, 0)
time.sleep(wait)
for g in range(255, 0, -1):
pixel[0] = (0, g, 0)
time.sleep(wait)
for b in range(255):
pixel[0] = (0, 0, b)
time.sleep(wait)
for b in range(255, 0, -1):
pixel[0] = (0, 0, b)
time.sleep(wait)
print("==============================")
print("Hello ESP32-C3/CircuitPython NeoPixel exercise")
#print(os.uname())
for u in os.uname():
print(u)
print()
print("neopixel version: " + neopixel.__version__)
print()
# Create the NeoPixel object
pixel = neopixel.NeoPixel(board.NEOPIXEL,
1,
pixel_order=neopixel.RGB)
pixel[0] = (0, 0, 0)
time.sleep(2.0)
cycleNeopixel(0.01)
pixel[0] = (0, 0, 0)
time.sleep(2.0)
print("- bye -\n")
"""
CircuitPython 7.2.0 exercise run on ESP32-C3
with unknown brand 0.96 inch 80x160 SPI ST7735 IPS
ref:
adafruit/Adafruit_CircuitPython_ST7735R
https://github.com/adafruit/Adafruit_CircuitPython_ST7735R
"""
from sys import implementation as sysImplementation
import time
import board
import busio
import displayio
import terminalio
from adafruit_st7735r import ST7735R as TFT_ST7735
from adafruit_st7735r import __name__ as ST7735_NAME
from adafruit_st7735r import __version__ as ST7735_VERSION
from adafruit_display_text import label
# Release any resources currently in use for the displays
displayio.release_displays()
#Connection between ESP32-C3 and SPI ST7735 display
#marking on display
tft_sck = board.IO2 #SCL
tft_mosi = board.IO3 #SDA
tft_reset = board.IO0 #RES
tft_dc = board.IO1 #DC
tft_cs = board.IO10 #CS
#Backlight (BLK) connect to ESP32-C3 3V3
#TFT VCC - ESP32-C31 3V3
#TFT GND - ESP32-C3 GND
tft_spi = busio.SPI(clock=tft_sck, MOSI=tft_mosi)
display_bus = displayio.FourWire(
tft_spi, command=tft_dc, chip_select=tft_cs, reset=tft_reset
)
# I find out colrstart/rowstart by try/error and retry
display = TFT_ST7735(display_bus, width=160, height=80,
colstart=26, rowstart=1,
rotation=90,
invert=True
)
print(type(display))
print("display.width: ", display.width)
print("display.height: ", display.height)
# Make the display context
splash = displayio.Group()
display.show(splash)
color_bitmap = displayio.Bitmap(display.width, display.height, 1)
color_palette = displayio.Palette(1)
color_palette[0] = 0x000000
time.sleep(1)
bg_sprite = displayio.TileGrid(color_bitmap,
pixel_shader=color_palette, x=0, y=0)
splash.append(bg_sprite)
for c in [["RED", 0xFF0000],
["GREEN", 0x00FF00],
["BLUE", 0x0000FF]]:
print(c[0], " : ", hex(c[1]))
color_palette[0] = c[1]
time.sleep(2)
splash.remove(bg_sprite)
#---
# Make the display context
#splash = displayio.Group()
#display.show(splash)
color_bitmap = displayio.Bitmap(display.width, display.height, 1)
color_palette = displayio.Palette(1)
color_palette[0] = 0x00FF00
bg_sprite = displayio.TileGrid(color_bitmap,
pixel_shader=color_palette, x=0, y=0)
splash.append(bg_sprite)
# Draw a smaller inner rectangle
inner_bitmap = displayio.Bitmap(display.width-2, display.height-2, 1)
inner_palette = displayio.Palette(1)
inner_palette[0] = 0x0000FF
inner_sprite = displayio.TileGrid(inner_bitmap,
pixel_shader=inner_palette, x=1, y=1)
splash.append(inner_sprite)
# Draw a label
text_group1 = displayio.Group(scale=1, x=5, y=10)
text1 = "ESP32-C3"
text_area1 = label.Label(terminalio.FONT, text=text1, color=0xFF0000)
text_group1.append(text_area1) # Subgroup for text scaling
# Draw a label
strSys = sysImplementation[0] + ' ' + \
str(sysImplementation[1][0]) +'.'+ \
str(sysImplementation[1][1]) +'.'+ \
str(sysImplementation[1][2])
text_group2 = displayio.Group(scale=1, x=5, y=25)
text2 = strSys
text_area2 = label.Label(terminalio.FONT, text=text2, color=0xFFFFFF)
text_group2.append(text_area2) # Subgroup for text scaling
# Draw a label
text_group3 = displayio.Group(scale=1, x=5, y=40)
text3 = ST7735_NAME
text_area3 = label.Label(terminalio.FONT, text=text3, color=0x0000000)
text_group3.append(text_area3) # Subgroup for text scaling
# Draw a label
text_group4 = displayio.Group(scale=1, x=5, y=55)
text4 = ST7735_VERSION
text_area4 = label.Label(terminalio.FONT, text=text4, color=0x000000)
text_group4.append(text_area4) # Subgroup for text scaling
text_group5 = displayio.Group(scale=1, x=5, y=70)
text5 = str(display.width) + " x " + str(display.height)
text_area5 = label.Label(terminalio.FONT, text=text5, color=0x000000)
text_group5.append(text_area5) # Subgroup for text scaling
splash.append(text_group1)
splash.append(text_group2)
splash.append(text_group3)
splash.append(text_group4)
splash.append(text_group5)
time.sleep(3.0)
rot = 90
while True:
time.sleep(5.0)
rot = rot + 90
if (rot>=360):
rot = 0
display.rotation = rot
$ esptool.py --chip esp32c3 --port /dev/ttyUSB0 write_flash \-z 0x0
adafruit-circuitpython-ai_thinker_esp32-c3s-en_US-7.2.0.bin
This exercise run on ESP32-C3-DevKitM-1 in arduino-esp32 2.0.2, display on unknown brand 0.96" 80x160 IPS.
Library used:
- Adafruit ST7735 and ST7789 Library
- Adafruit GFX
Library
TFT_ST7735 ESP32-C3
-------------------
VCC 3V3
GND GND
CS 10
RESET 9
A0(DC) 8
SDA 6
SCK 4
LED 3V3
In this exercise, I create a custom class (MyST7735) extend
Adafruit_ST7735:
- call setColRowStart(26, 1) in init() to correct the
shifting.
- override setRotation() function, to use ST7735_MADCTL_BGR
instead of ST77xx_MADCTL_RGB.
Exercise code:
/*
* arduino-esp32 exercise run on ESP32-C3-DevKitM-1,
* display on 0.96" 80x160 TFT with SPI ST7735,
* using 'Adafruit ST7735 and ST7789 Library'.
*
* Base on Adafruit ST7735 and ST7789 Library 1.9.1
*
* Fix offset and color with
* custom class (MyST7735) extending Adafruit_ST7735,
* to call protected function setColRowStart(),
* and override setRotation().
*
* ref:
* Adafruit-ST7735-Library:
* https://github.com/adafruit/Adafruit-ST7735-Library
* Adafruit-GFX-Library:
* https://github.com/adafruit/Adafruit-GFX-Library
*
*/
#include <Adafruit_GFX.h> // Core graphics library
//#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include "MyST7735.h"
#define TFT_CS_ST7735 10
#define TFT_RST_ST7735 9 // Or set to -1 and connect to Arduino RESET pin
#define TFT_CS_ST7789 2
#define TFT_RST_ST7789 3
#define TFT_DC 8
/*
* Erik:
* on ESP32-C3-DevKitM-1
* SS: 7 - not used
* MOSI: 6
* MISO: 5 - not used
* SCK: 4
* ===================
* Conection:
*
* TFT_ST7735 ESP32-C3
* -------------------
* VCC 3V3
* GND GND
* CS 10
* RESET 9
* A0(DC) 8
* SDA 6
* SCK 4
* LED 3V3
*
*/
//Adafruit_ST7735 tft_ST7735 = Adafruit_ST7735(TFT_CS_ST7735, TFT_DC, TFT_RST_ST7735);
MyST7735 tft_ST7735 = MyST7735(TFT_CS_ST7735, TFT_DC, TFT_RST_ST7735);
void setup(void) {
delay(500);
Serial.begin(115200);
delay(500);
Serial.print(F("Hello!\n"));
Serial.print(F("0.96 80X160 (RGB) IPS Test\n\n"));
//tft_ST7735.initR(INITR_MINI160x80); // Init ST7735S mini display
tft_ST7735.init();
tft_ST7735.invertDisplay(true);
tft_ST7735.setRotation(3);
// SPI speed defaults to SPI_DEFAULT_FREQ defined in the library, you can override it here
// Note that speed allowable depends on chip and quality of wiring, if you go too fast,
// you may end up with a black screen some times, or all the time.
//tft.setSPISpeed(40000000);
Serial.println(F("Initialized"));
// large block of text
tft_ST7735.fillScreen(ST77XX_BLACK);
tft_ST7735.setTextWrap(true);
tft_ST7735.setTextColor(ST77XX_WHITE);
drawBorderline();
delay(1000);
tft_ST7735.setCursor(0, 0);
tft_ST7735.print("Hello ESP32C3");
tft_ST7735.setCursor(0, 20);
tft_ST7735.print("Chip Model: " + String(ESP.getChipModel()));
tft_ST7735.setCursor(0, 30);
tft_ST7735.print("rotation: " + String(tft_ST7735.getRotation()));
tft_ST7735.setCursor(0, 40);
tft_ST7735.print(String(tft_ST7735.width()) + " x " + String(tft_ST7735.height()));
delay(1000);
colorTest();
delay(1000);
for(int offset=0; offset<tft_ST7735.height()/2-10; offset++){
int col;
if(offset%4 == 0)
col = ST77XX_WHITE;
else
col = ST77XX_BLACK;
tft_ST7735.drawRect(offset, offset,
tft_ST7735.width()-1-2*offset, tft_ST7735.height()-1-2*offset,
col);
delay(100);
}
delay(2000);
tft_ST7735.setRotation(0);
tft_ST7735.fillScreen(ST77XX_BLACK);
tft_ST7735.setTextWrap(true);
tft_ST7735.setTextColor(ST77XX_WHITE);
tft_ST7735.drawRect(0, 0,
tft_ST7735.width()-1, tft_ST7735.height()-1,
ST77XX_WHITE);
delay(1000);
colorTest();
drawBorderline();
Serial.println("\n\n- setup() end -\n");
delay(1000);
}
void drawBorderline(){
tft_ST7735.fillScreen(ST77XX_BLACK);
tft_ST7735.drawRect(0, 0,
tft_ST7735.width()-1, tft_ST7735.height()-1,
ST77XX_WHITE);
Serial.println();
Serial.printf("\nrotation %d", tft_ST7735.getRotation());
Serial.printf("\nwidth %d", tft_ST7735.width());
Serial.printf("\nheight %d", tft_ST7735.height());
}
void colorTest(){
tft_ST7735.fillScreen(ST77XX_RED);
tft_ST7735.setCursor(50, 50);
tft_ST7735.print("RED");
delay(1000);
tft_ST7735.fillScreen(ST77XX_GREEN);
tft_ST7735.setCursor(50, 50);
tft_ST7735.print("GREEN");
delay(1000);
tft_ST7735.fillScreen(ST77XX_BLUE);
tft_ST7735.setCursor(50, 50);
tft_ST7735.print("BLUE");
delay(1000);
}
/*
* Cnvert R, G, B (in uint8_t)
* to color (in uint16_t) in 565 format for Adafruit GFX library
* rrrrrggg gggbbbbb
*/
uint16_t convertRGBtoColor(uint8_t r, uint8_t g, uint8_t b){
return (((r & 0xF8) << 8) |
((g & 0xFC) << 3) |
(b >> 3));
}
void loop() {
tft_ST7735.setRotation(1);
for (int x = 0; x < tft_ST7735.width(); x++){
int c =255 * x/tft_ST7735.width();
uint16_t color = convertRGBtoColor(c, c, c);
tft_ST7735.drawLine(x, 0, x, tft_ST7735.height()-1, color);
}
delay(1000);
tft_ST7735.setRotation(2);
for (int x = 0; x < tft_ST7735.width(); x++){
int r =255 * x/tft_ST7735.width();
uint16_t color = convertRGBtoColor(r, 0, 0);
tft_ST7735.drawLine(x, 0, x, tft_ST7735.height()-1, color);
}
delay(1000);
tft_ST7735.setRotation(3);
for (int x = 0; x < tft_ST7735.width(); x++){
int g =255 * x/tft_ST7735.width();
uint16_t color = convertRGBtoColor(0, g, 0);
tft_ST7735.drawLine(x, 0, x, tft_ST7735.height()-1, color);
}
delay(1000);
tft_ST7735.setRotation(4);
for (int x = 0; x < tft_ST7735.width(); x++){
int b =255 * x/tft_ST7735.width();
uint16_t color = convertRGBtoColor(0, 0, b);
tft_ST7735.drawLine(x, 0, x, tft_ST7735.height()-1, color);
}
delay(1000);
}
#include "MyST7735.h"
#include "Adafruit_ST7735.h"
#include "Adafruit_ST77xx.h"
MyST7735::MyST7735(int8_t cs, int8_t dc, int8_t rst)
: Adafruit_ST7735(cs, dc, rst) {}
/*************************************************************************
init() to fix offset
by calling protected function setColRowStart().
*************************************************************************/
void MyST7735::init(void) {
initR(INITR_MINI160x80);
setColRowStart(26, 1);
}
/*************************************************************************
override setRotation() to fix color order using ST7735_MADCTL_BGR.
To make it simple, option INITR_MINI160x80 is assumed and handled only.
*************************************************************************/
void MyST7735::setRotation(uint8_t m) {
uint8_t madctl = 0;
rotation = m & 3; // can't be higher than 3
switch (rotation) {
case 0:
madctl = ST77XX_MADCTL_MX | ST77XX_MADCTL_MY | ST7735_MADCTL_BGR;
_height = ST7735_TFTHEIGHT_160;
_width = ST7735_TFTWIDTH_80;
_xstart = _colstart;
_ystart = _rowstart;
break;
case 1:
madctl = ST77XX_MADCTL_MY | ST77XX_MADCTL_MV | ST7735_MADCTL_BGR;
_width = ST7735_TFTHEIGHT_160;
_height = ST7735_TFTWIDTH_80;
_ystart = _colstart;
_xstart = _rowstart;
break;
case 2:
madctl = ST7735_MADCTL_BGR;
_height = ST7735_TFTHEIGHT_160;
_width = ST7735_TFTWIDTH_80;
_xstart = _colstart;
_ystart = _rowstart;
break;
case 3:
madctl = ST77XX_MADCTL_MX | ST77XX_MADCTL_MV | ST7735_MADCTL_BGR;
_width = ST7735_TFTHEIGHT_160;
_height = ST7735_TFTWIDTH_80;
_ystart = _colstart;
_xstart = _rowstart;
break;
}
sendCommand(ST77XX_MADCTL, &madctl, 1);
}
#ifndef _MyST7735_
#define _MyST7735_
#include "Adafruit_ST77xx.h"
#include "Adafruit_ST7735.h"
#define ST7735_MADCTL_BGR 0x08
#define ST77XX_MADCTL_RGB 0x00
class MyST7735 : public Adafruit_ST7735 {
public:
MyST7735(int8_t cs, int8_t dc, int8_t rst);
void init(void);
void setRotation(uint8_t m);
};
#endif // _MyST7735_
This exercise run on ESP32/ESP32-C3 to perform BLE communication, to notify data update. Both run on arduino-esp32 framework.
Basically, the server copy from my former exercise "ESP32 + DHT11 temperature & humidity sensor with display on ST7789 and BLE function", the client copy from BLE_client example.
But with my original setting (follow BLE_notify example) in server side:
pAdvertising->setScanResponse(false);
pAdvertising->setMinPreferred(0x0);
both advertisedDevice.haveServiceUUID() and
advertisedDevice.isAdvertisingService(serviceUUID) in client return false. So
the client cannot find the server. pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06);
pAdvertising->setMinPreferred(0x12);
then both advertisedDevice.haveServiceUUID() and
advertisedDevice.isAdvertisingService(serviceUUID) in client return true, such
that the server can be found.
/*
Execise run on ESP32 (ESP32-DevKitC V4) with arduino-esp32 2.0.1,
read DHT11 Humidity & Temperature Sensor,
and display on ST7789 SPI TFT, 2" IPS 240x320, with graph.
BLE function added.
Library needed:
- DHT sensor library for ESPx by beegee_tokyo
- Adafruit ST7735 and ST7789 Library by Adafruit
- Adafruit GFX Library by Adafruit
Modify from examples DHT_ESP32 of DHT sensor library for ESPx
Connection between DHT11 and ESP32 (GPIO#)
-----------------------------------------------
DHT11 ESP32
----- -----
VCC* 3V3
DATA** 32
NC
GND GND
* * - depends on module, my DHT11 module is 3V3~5V operate.
* ** - depends on your module, maybe you have to add a
pull-up resistor (~10K Ohm) betwee DATA and VCC.
Connection between ST7789 SPI and ESP32 (GPIO#)
-----------------------------------------------
ST7789 SPI ESP32
---------- -----
GND GND
VCC 3V3
SCL 18
SDA 23
RES 26
DC 25
CS 33
BLK 3V3
*/
#include "DHTesp.h"
#include <Ticker.h>
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#include <Fonts/FreeMonoBold12pt7b.h>
#include <SPI.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#ifndef ESP32
#pragma message(THIS EXAMPLE IS FOR ESP32 ONLY!)
#error Select ESP32 board.
#endif
DHTesp dht;
void tempTask(void *pvParameters);
bool getTemperature();
void triggerGetTemp();
/** Task handle for the light value read task */
TaskHandle_t tempTaskHandle = NULL;
/** Ticker for temperature reading */
Ticker tempTicker;
/** Comfort profile */
ComfortState cf;
/** Flag if task should run */
bool tasksEnabled = false;
/** Pin number for DHT11 data pin */
int dhtPin = 32; //17;
//hardware SPI MOSI 23
//hardware SPI SCK 18
#define TFT_CS 33
#define TFT_RST 26
#define TFT_DC 25
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
bool rqsUpdate = false;
TempAndHumidity updateValues;
unsigned long prvUpdateMillis;
#define FRAME_TOPX 0
#define FRAME_TOPY 200
#define FRAME_WIDTH 240
#define FRAME_HEIGHT 100
#define FRAME_BOTTOMY FRAME_TOPY + FRAME_HEIGHT
#define SCR_HEIGHT 320
int idx = 0;
#define IDX_MAX 240
BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
BLECharacteristic* pChar_temp = NULL;
BLECharacteristic* pChar_humi = NULL;
bool deviceConnected = false;
bool oldDeviceConnected = false;
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "FC8601FC-7829-407B-9C2E-4D3F117DFF2D"
#define CHAR_UUID_TEMP "0FD31907-35AE-4BB0-8AB1-51F98C05B326"
#define CHAR_UUID_HUMI "D01D3AF7-818D-4A90-AECF-0E1EC48AA5F0"
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
BLEDevice::startAdvertising();
Serial.println("MyServerCallbacks.onConnect");
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
Serial.println("MyServerCallbacks.onDisconnect");
}
};
/**
initTemp
Setup DHT library
Setup task and timer for repeated measurement
@return bool
true if task and timer are started
false if task or timer couldn't be started
*/
bool initTemp() {
byte resultValue = 0;
// Initialize temperature sensor
dht.setup(dhtPin, DHTesp::DHT11);
Serial.println("DHT initiated");
// Start task to get temperature
xTaskCreatePinnedToCore(
tempTask, /* Function to implement the task */
"tempTask ", /* Name of the task */
4000, /* Stack size in words */
NULL, /* Task input parameter */
5, /* Priority of the task */
&tempTaskHandle, /* Task handle. */
1); /* Core where the task should run */
if (tempTaskHandle == NULL) {
Serial.println("Failed to start task for temperature update");
return false;
} else {
// Start update of environment data every XX seconds
tempTicker.attach(2, triggerGetTemp);
}
return true;
}
/**
triggerGetTemp
Sets flag dhtUpdated to true for handling in loop()
called by Ticker getTempTimer
*/
void triggerGetTemp() {
if (tempTaskHandle != NULL) {
xTaskResumeFromISR(tempTaskHandle);
}
}
/**
Task to reads temperature from DHT11 sensor
@param pvParameters
pointer to task parameters
*/
void tempTask(void *pvParameters) {
Serial.println("tempTask loop started");
while (1) // tempTask loop
{
if (tasksEnabled) {
// Get temperature values
getTemperature();
}
// Got sleep again
vTaskSuspend(NULL);
}
}
/**
getTemperature
Reads temperature from DHT11 sensor
@return bool
true if temperature could be aquired
false if aquisition failed
*/
bool getTemperature() {
// Reading temperature for humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (it's a very slow sensor)
TempAndHumidity newValues = dht.getTempAndHumidity();
// Check if any reads failed and exit early (to try again).
if (dht.getStatus() != 0) {
Serial.println("DHT11 error status: " + String(dht.getStatusString()));
return false;
}
rqsUpdate = true;
updateValues = newValues;
return true;
}
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println("DHT ESP32 example with tasks");
//init DHT
initTemp();
// Signal end of setup() to tasks
tasksEnabled = true;
//init BLE
// Create the BLE Device
BLEDevice::init("ESP32-DHT11");
// 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 temp and humi
pChar_temp = pService->createCharacteristic(
CHAR_UUID_TEMP,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
pChar_humi = pService->createCharacteristic(
CHAR_UUID_HUMI,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
pChar_temp->addDescriptor(new BLE2902());
pChar_humi->addDescriptor(new BLE2902());
// Start the service
pService->start();
// Start advertising
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
// Erik updated@2021-12-14
//pAdvertising->setScanResponse(false);
//pAdvertising->setMinPreferred(0x0); // set value to 0x00 to not advertise this parameter
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06); // functions that help with iPhone connections issue
pAdvertising->setMinPreferred(0x12);
//print for information only
Serial.println("pAdvertising->setScanResponse(true)");
Serial.println("pAdvertising->setMinPreferred(0x06)");
Serial.println("pAdvertising->setMinPreferred(0x12)");
BLEDevice::startAdvertising();
Serial.println("Waiting a client connection to notify...");
//init ST7789
tft.init(240, 320); // Init ST7789 320x240
tft.setRotation(2);
tft.setFont(&FreeMonoBold12pt7b);
tft.setTextWrap(true);
tft.fillScreen(ST77XX_RED);
delay(300);
tft.fillScreen(ST77XX_GREEN);
delay(300);
tft.fillScreen(ST77XX_BLUE);
delay(300);
tft.setCursor(0, 0);
tft.setTextColor(ST77XX_RED);
tft.print("\n");
tft.print("ESP32 + DHT11 + ST7789\n");
prvUpdateMillis = millis();
}
void loop() {
if (!tasksEnabled) {
// Wait 2 seconds to let system settle down
delay(2000);
// Enable task that will read values from the DHT sensor
tasksEnabled = true;
if (tempTaskHandle != NULL) {
vTaskResume(tempTaskHandle);
}
}
if (rqsUpdate) {
unsigned long curUpdateMillis = millis();
tft.fillRect(0, 53, 240, 75, ST77XX_BLUE );
tft.setCursor(0, 70);
tft.setTextColor(ST77XX_WHITE);
tft.print(" temp.: " + String(updateValues.temperature));
tft.setCursor(0, 95);
tft.setTextColor(ST77XX_WHITE);
tft.print(" humi.: " + String(updateValues.humidity));
tft.setCursor(0, 115);
tft.setTextColor(ST77XX_WHITE);
tft.print(" mills.: " + String(curUpdateMillis - prvUpdateMillis));
prvUpdateMillis = curUpdateMillis;
if (idx == 0) {
tft.fillRect(FRAME_TOPX, FRAME_TOPY,
FRAME_WIDTH, SCR_HEIGHT - FRAME_TOPY,
ST77XX_BLUE);
}
tft.drawLine(
FRAME_TOPX + idx, FRAME_BOTTOMY,
FRAME_TOPX + idx, FRAME_BOTTOMY - (int)updateValues.temperature,
ST77XX_WHITE);
idx++;
if (idx >= IDX_MAX)
idx = 0;
char bufTemp[5];
char bufHumi[5];
//convert floating point value to String
dtostrf(updateValues.temperature, 0, 2, bufTemp);
dtostrf(updateValues.humidity, 0, 2, bufHumi);
pChar_temp->setValue((uint8_t*)bufTemp, 5);
pChar_temp->notify();
pChar_humi->setValue((uint8_t*)bufHumi, 5);
pChar_humi->notify();
//Serial.println(" T:" + String(updateValues.temperature) + " H:" + String(updateValues.humidity));
rqsUpdate = false;
}
// disconnecting
if (!deviceConnected && oldDeviceConnected) {
Serial.println("disconnecting");
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) {
Serial.println("connecting");
// do stuff here on connecting
oldDeviceConnected = deviceConnected;
}
yield();
}
/**
* A BLE client example that is rich in capabilities.
* There is a lot new capabilities implemented.
* author unknown
* updated by chegewara
*/
#include "BLEDevice.h"
//#include "BLEScan.h"
#define SERVICE_UUID "FC8601FC-7829-407B-9C2E-4D3F117DFF2D"
#define CHAR_UUID_TEMP "0FD31907-35AE-4BB0-8AB1-51F98C05B326"
#define CHAR_UUID_HUMI "D01D3AF7-818D-4A90-AECF-0E1EC48AA5F0"
// The remote service we wish to connect to.
static BLEUUID serviceUUID(SERVICE_UUID);
// The characteristic of the remote service we are interested in.
static BLEUUID charUUID(CHAR_UUID_TEMP);
static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;
static BLEAdvertisedDevice* myDevice;
static void notifyCallback(
BLERemoteCharacteristic* pBLERemoteCharacteristic,
uint8_t* pData,
size_t length,
bool isNotify) {
Serial.print("Notify callback for characteristic ");
Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
Serial.print(" of data length ");
Serial.println(length);
Serial.print("data: ");
Serial.println((char*)pData);
}
class MyClientCallback : public BLEClientCallbacks {
void onConnect(BLEClient* pclient) {
}
void onDisconnect(BLEClient* pclient) {
connected = false;
Serial.println("onDisconnect");
}
};
bool connectToServer() {
Serial.print("Forming a connection to ");
Serial.println(myDevice->getAddress().toString().c_str());
BLEClient* pClient = BLEDevice::createClient();
Serial.println(" - Created client");
pClient->setClientCallbacks(new MyClientCallback());
// Connect to the remove BLE Server.
pClient->connect(myDevice); // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
Serial.println(" - Connected to server");
pClient->setMTU(517); //set client to request maximum MTU from server (default is 23 otherwise)
// Obtain a reference to the service we are after in the remote BLE server.
BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
if (pRemoteService == nullptr) {
Serial.print("Failed to find our service UUID: ");
Serial.println(serviceUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found our service");
// Obtain a reference to the characteristic in the service of the remote BLE server.
pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
if (pRemoteCharacteristic == nullptr) {
Serial.print("Failed to find our characteristic UUID: ");
Serial.println(charUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found our characteristic");
// Read the value of the characteristic.
if(pRemoteCharacteristic->canRead()) {
std::string value = pRemoteCharacteristic->readValue();
Serial.print("The characteristic value was: ");
Serial.println(value.c_str());
}
if(pRemoteCharacteristic->canNotify())
pRemoteCharacteristic->registerForNotify(notifyCallback);
connected = true;
return true;
}
/**
* Scan for BLE servers and find the first one that advertises the service we are looking for.
*/
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
/**
* Called for each advertising BLE server.
*/
void onResult(BLEAdvertisedDevice advertisedDevice) {
Serial.print("BLE Advertised Device found: ");
Serial.println(advertisedDevice.toString().c_str());
if(advertisedDevice.haveServiceUUID()){
Serial.println("- advertisedDevice.haveServiceUUID()");
}
if(advertisedDevice.isAdvertisingService(serviceUUID)){
Serial.println("- advertisedDevice.isAdvertisingService(serviceUUID)");
}
// We have found a device, let us now see if it contains the service we are looking for.
if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {
BLEDevice::getScan()->stop();
myDevice = new BLEAdvertisedDevice(advertisedDevice);
doConnect = true;
doScan = true;
Serial.println("*** device found ***");
} // Found our server
} // onResult
}; // MyAdvertisedDeviceCallbacks
void setup() {
Serial.begin(115200);
Serial.println("Starting Arduino BLE Client application...");
BLEDevice::init("");
// Retrieve a Scanner and set the callback we want to use to be informed when we
// have detected a new device. Specify that we want active scanning and start the
// scan to run for 5 seconds.
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setInterval(1349);
pBLEScan->setWindow(449);
pBLEScan->setActiveScan(true);
pBLEScan->start(5, false);
} // End of setup.
// This is the Arduino main loop function.
void loop() {
// If the flag "doConnect" is true then we have scanned for and found the desired
// BLE Server with which we wish to connect. Now we connect to it. Once we are
// connected we set the connected flag to be true.
if (doConnect == true) {
if (connectToServer()) {
Serial.println("We are now connected to the BLE Server.");
} else {
Serial.println("We have failed to connect to the server; there is nothin more we will do.");
}
doConnect = false;
}
// If we are connected to a peer BLE Server, update the characteristic each time we are reached
// with the current time since boot.
if (connected) {
String newValue = "Time since boot: " + String(millis()/1000);
Serial.println("Setting new characteristic value to \"" + newValue + "\"");
// Set the characteristic's value to be the array of bytes that is actually a string.
pRemoteCharacteristic->writeValue(newValue.c_str(), newValue.length());
}else if(doScan){
BLEDevice::getScan()->start(0); // this is just example to start scan after disconnect, most likely there is better way to do it in arduino
}
delay(1000); // Delay a second between loops.
} // End of loop
/**
* modified from BLE_client
* to work with ESP32_DHT_ST789_graphic_BLE.ino,
* to monitor temp/humi.
*/
#include "BLEDevice.h"
//#include "BLEScan.h"
#define SERVICE_UUID "FC8601FC-7829-407B-9C2E-4D3F117DFF2D"
#define CHAR_UUID_TEMP "0FD31907-35AE-4BB0-8AB1-51F98C05B326"
#define CHAR_UUID_HUMI "D01D3AF7-818D-4A90-AECF-0E1EC48AA5F0"
// The remote service we wish to connect to.
static BLEUUID serviceUUID(SERVICE_UUID);
// The characteristic of the remote service we are interested in.
static BLEUUID charUUID_TEMP(CHAR_UUID_TEMP);
static BLEUUID charUUID_HUMI(CHAR_UUID_HUMI);
static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLERemoteCharacteristic* pRemoteChar_temp;
static BLERemoteCharacteristic* pRemoteChar_humi;
static BLEAdvertisedDevice* myDevice;
static void notifyCallback(
BLERemoteCharacteristic* pBLERemoteCharacteristic,
uint8_t* pData,
size_t length,
bool isNotify) {
String strCharUUID = pBLERemoteCharacteristic->getUUID().toString().c_str();
Serial.printf("Notify callback for characteristic: ");
strCharUUID.toUpperCase();
Serial.println(strCharUUID);
if(strCharUUID.equals(CHAR_UUID_TEMP)){
Serial.print("temp: ");
for (int i=0; i<length; i++)
Serial.print((char) pData[i]);
}else if(strCharUUID.equals(CHAR_UUID_HUMI)){
Serial.print("humi: ");
for (int i=0; i<length; i++)
Serial.print((char) pData[i]);
}
Serial.println();
}
class MyClientCallback : public BLEClientCallbacks {
void onConnect(BLEClient* pclient) {
}
void onDisconnect(BLEClient* pclient) {
connected = false;
Serial.println("onDisconnect");
}
};
bool connectToServer() {
Serial.print("Forming a connection to ");
Serial.println(myDevice->getAddress().toString().c_str());
BLEClient* pClient = BLEDevice::createClient();
Serial.println(" - Created client");
pClient->setClientCallbacks(new MyClientCallback());
// Connect to the remove BLE Server.
// if you pass BLEAdvertisedDevice instead of address,
// it will be recognized type of peer device address (public or private)
pClient->connect(myDevice);
Serial.println(" - Connected to server");
//set client to request maximum MTU from server (default is 23 otherwise)
pClient->setMTU(517);
// Obtain a reference to the service we are after in the remote BLE server.
BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
if (pRemoteService == nullptr) {
Serial.print("Failed to find our service UUID: ");
Serial.println(serviceUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found our service");
// Obtain a reference to the characteristic in the service
// of the remote BLE server.
pRemoteChar_temp = pRemoteService->getCharacteristic(charUUID_TEMP);
if (pRemoteChar_temp == nullptr) {
Serial.print("Failed to find our characteristic UUID: ");
Serial.println(charUUID_TEMP.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found temp characteristic");
pRemoteChar_humi = pRemoteService->getCharacteristic(charUUID_HUMI);
if (pRemoteChar_humi == nullptr) {
Serial.print("Failed to find our characteristic UUID: ");
Serial.println(charUUID_TEMP.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found humi characteristic");
// Read the value of the characteristic.
if(pRemoteChar_temp->canRead()) {
std::string value = pRemoteChar_temp->readValue();
Serial.print("The characteristic temp value was: ");
Serial.println(value.c_str());
}
if(pRemoteChar_humi->canRead()) {
std::string value = pRemoteChar_humi->readValue();
Serial.print("The characteristic humi value was: ");
Serial.println(value.c_str());
}
if(pRemoteChar_temp->canNotify())
pRemoteChar_temp->registerForNotify(notifyCallback);
if(pRemoteChar_humi->canNotify())
pRemoteChar_humi->registerForNotify(notifyCallback);
connected = true;
return true;
}
/**
* Scan for BLE servers and
* find the first one that advertises the service we are looking for.
*/
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
/**
* Called for each advertising BLE server.
*/
void onResult(BLEAdvertisedDevice advertisedDevice) {
Serial.print("BLE Advertised Device found: ");
Serial.println(advertisedDevice.toString().c_str());
if(advertisedDevice.haveServiceUUID()){
Serial.println("- haveServiceUUID()");
}
if(advertisedDevice.isAdvertisingService(serviceUUID)){
Serial.println("- isAdvertisingService(serviceUUID)");
}
// We have found a device,
// let us now see if it contains the service we are looking for.
if (advertisedDevice.haveServiceUUID() &&
advertisedDevice.isAdvertisingService(serviceUUID)) {
BLEDevice::getScan()->stop();
myDevice = new BLEAdvertisedDevice(advertisedDevice);
doConnect = true;
doScan = true;
Serial.println("*** device found ***");
} // Found our server
} // onResult
}; // MyAdvertisedDeviceCallbacks
void setup() {
Serial.begin(115200);
Serial.println("Starting Arduino BLE Client application...");
BLEDevice::init("");
// Retrieve a Scanner and set the callback we want to use to be informed when we
// have detected a new device. Specify that we want active scanning and start the
// scan to run for 5 seconds.
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setInterval(1349);
pBLEScan->setWindow(449);
pBLEScan->setActiveScan(true);
pBLEScan->start(5, false);
} // End of setup.
// This is the Arduino main loop function.
void loop() {
// If the flag "doConnect" is true then we have scanned for and found the desired
// BLE Server with which we wish to connect. Now we connect to it. Once we are
// connected we set the connected flag to be true.
if (doConnect == true) {
if (connectToServer()) {
Serial.println("We are now connected to the BLE Server.");
} else {
Serial.println("We have failed to connect to the server.");
}
doConnect = false;
}
// If we are connected to a peer BLE Server,
// update the characteristic each time we are reached
// with the current time since boot.
if (connected) {
}else if(doScan){
// this is just example to start scan after disconnect,
// most likely there is better way to do it in arduino
BLEDevice::getScan()->start(0);
}
delay(1000); // Delay a second between loops.
} // End of loop
/**
* modified from BLE_client
* to work with ESP32_DHT_ST789_graphic_BLE.ino,
* to monitor temp/humi.
* and display on SSD1306 I2C OLED
*/
#include "BLEDevice.h"
//#include "BLEScan.h"
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define SDA_pin 3
#define SCL_pin 2
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C //0x3D ///
Adafruit_SSD1306 display;
#define SERVICE_UUID "FC8601FC-7829-407B-9C2E-4D3F117DFF2D"
#define CHAR_UUID_TEMP "0FD31907-35AE-4BB0-8AB1-51F98C05B326"
#define CHAR_UUID_HUMI "D01D3AF7-818D-4A90-AECF-0E1EC48AA5F0"
// The remote service we wish to connect to.
static BLEUUID serviceUUID(SERVICE_UUID);
// The characteristic of the remote service we are interested in.
static BLEUUID charUUID_TEMP(CHAR_UUID_TEMP);
static BLEUUID charUUID_HUMI(CHAR_UUID_HUMI);
static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLERemoteCharacteristic* pRemoteChar_temp;
static BLERemoteCharacteristic* pRemoteChar_humi;
static BLEAdvertisedDevice* myDevice;
static void notifyCallback(
BLERemoteCharacteristic* pBLERemoteCharacteristic,
uint8_t* pData,
size_t length,
bool isNotify) {
String strCharUUID = pBLERemoteCharacteristic->getUUID().toString().c_str();
Serial.printf("Notify callback for characteristic: ");
strCharUUID.toUpperCase();
Serial.println(strCharUUID);
if(strCharUUID.equals(CHAR_UUID_TEMP)){
Serial.print("temp: ");
String strTemp = (char*)pData;
Serial.print(strTemp);
displayTemp(strTemp);
}else if(strCharUUID.equals(CHAR_UUID_HUMI)){
Serial.print("humi: ");
String strHumi = (char*)pData;
Serial.print(strHumi);
displayHumi(strHumi);
}
Serial.println();
}
class MyClientCallback : public BLEClientCallbacks {
void onConnect(BLEClient* pclient) {
displayPrompt("onConnect");
}
void onDisconnect(BLEClient* pclient) {
connected = false;
Serial.println("onDisconnect");
displayPrompt("onDisconnect");
}
};
bool connectToServer() {
Serial.print("Forming a connection to ");
Serial.println(myDevice->getAddress().toString().c_str());
BLEClient* pClient = BLEDevice::createClient();
Serial.println(" - Created client");
pClient->setClientCallbacks(new MyClientCallback());
// Connect to the remove BLE Server.
// if you pass BLEAdvertisedDevice instead of address,
// it will be recognized type of peer device address (public or private)
pClient->connect(myDevice);
Serial.println(" - Connected to server");
//set client to request maximum MTU from server (default is 23 otherwise)
pClient->setMTU(517);
// Obtain a reference to the service we are after in the remote BLE server.
BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
if (pRemoteService == nullptr) {
Serial.print("Failed to find our service UUID: ");
Serial.println(serviceUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found our service");
// Obtain a reference to the characteristic in the service
// of the remote BLE server.
pRemoteChar_temp = pRemoteService->getCharacteristic(charUUID_TEMP);
if (pRemoteChar_temp == nullptr) {
Serial.print("Failed to find our characteristic UUID: ");
Serial.println(charUUID_TEMP.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found temp characteristic");
pRemoteChar_humi = pRemoteService->getCharacteristic(charUUID_HUMI);
if (pRemoteChar_humi == nullptr) {
Serial.print("Failed to find our characteristic UUID: ");
Serial.println(charUUID_TEMP.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found humi characteristic");
// Read the value of the characteristic.
if(pRemoteChar_temp->canRead()) {
std::string value = pRemoteChar_temp->readValue();
Serial.print("The characteristic temp value was: ");
Serial.println(value.c_str());
displayTemp(value.c_str());
}
if(pRemoteChar_humi->canRead()) {
std::string value = pRemoteChar_humi->readValue();
Serial.print("The characteristic humi value was: ");
Serial.println(value.c_str());
displayHumi(value.c_str());
}
if(pRemoteChar_temp->canNotify())
pRemoteChar_temp->registerForNotify(notifyCallback);
if(pRemoteChar_humi->canNotify())
pRemoteChar_humi->registerForNotify(notifyCallback);
connected = true;
return true;
}
/**
* Scan for BLE servers and
* find the first one that advertises the service we are looking for.
*/
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
/**
* Called for each advertising BLE server.
*/
void onResult(BLEAdvertisedDevice advertisedDevice) {
Serial.print("BLE Advertised Device found: ");
Serial.println(advertisedDevice.toString().c_str());
if(advertisedDevice.haveServiceUUID()){
Serial.println("- haveServiceUUID()");
}
if(advertisedDevice.isAdvertisingService(serviceUUID)){
Serial.println("- isAdvertisingService(serviceUUID)");
}
// We have found a device,
// let us now see if it contains the service we are looking for.
if (advertisedDevice.haveServiceUUID() &&
advertisedDevice.isAdvertisingService(serviceUUID)) {
BLEDevice::getScan()->stop();
myDevice = new BLEAdvertisedDevice(advertisedDevice);
doConnect = true;
doScan = true;
Serial.println("*** device found ***");
displayPrompt("found");
} // Found our server
} // onResult
}; // MyAdvertisedDeviceCallbacks
void initScreen(){
Wire.setPins(SDA_pin,SCL_pin);
display = Adafruit_SSD1306(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
display.clearDisplay();
display.display();
delay(500);
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE); // Draw white text
display.cp437(true); // Use full 256 char 'Code Page 437' font
display.setCursor(10, 10);
display.printf("ESP32C3");
display.setCursor(10, 28);
display.printf("BLE");
display.fillRect(0, 0, display.width()-1, display.height()-1, SSD1306_INVERSE);
display.display();
delay(3000);
// Clear the buffer
display.clearDisplay();
display.display();
}
void displayTemp(String temp){
//erase display of old temp
display.fillRect(40, 10, 80, 18, SSD1306_BLACK);
display.setCursor(10, 10);
display.setTextSize(1);
display.print("temp");
display.setCursor(40, 10);
display.setTextSize(2);
display.print(temp);
display.display();
}
void displayHumi(String humi){
//erase display of old humi
display.fillRect(40, 30, 80, 18, SSD1306_BLACK);
display.setCursor(10, 30);
display.setTextSize(1);
display.print("humi");
display.setCursor(40, 30);
display.setTextSize(2);
display.print(humi);
display.display();
}
void displayPrompt(String prompt){
//erase display of old temp
display.fillRect(10, 10, 110, 40, SSD1306_BLACK);
display.setCursor(40, 10);
display.setTextSize(1);
display.print(prompt);
display.display();
}
void setup() {
Serial.begin(115200);
Serial.println("Starting Arduino BLE Client application...");
initScreen();
BLEDevice::init("");
// Retrieve a Scanner and set the callback we want to use to be informed when we
// have detected a new device. Specify that we want active scanning and start the
// scan to run for 5 seconds.
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setInterval(1349);
pBLEScan->setWindow(449);
pBLEScan->setActiveScan(true);
pBLEScan->start(5, false);
displayPrompt("Scan");
Serial.println("Scan");
} // End of setup.
// This is the Arduino main loop function.
void loop() {
// If the flag "doConnect" is true then we have scanned for and found the desired
// BLE Server with which we wish to connect. Now we connect to it. Once we are
// connected we set the connected flag to be true.
if (doConnect == true) {
if (connectToServer()) {
Serial.println("We are now connected to the BLE Server.");
} else {
Serial.println("We have failed to connect to the server.");
}
doConnect = false;
}
// If we are connected to a peer BLE Server,
// update the characteristic each time we are reached
// with the current time since boot.
if (connected) {
}else if(doScan){
// this is just example to start scan after disconnect,
// most likely there is better way to do it in arduino
displayPrompt("Scan");
Serial.println("Scan");
BLEDevice::getScan()->start(0);
}
delay(1000); // Delay a second between loops.
} // End of loop
.
.
.
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// The pins for I2C are defined by the Wire-library.
// On an arduino UNO: A4(SDA), A5(SCL)
// On an arduino MEGA 2560: 20(SDA), 21(SCL)
// On an arduino LEONARDO: 2(SDA), 3(SCL), ...
/* remarked by Erik 2021-12-13
* On my SSD1306 128x64 OLED
* - No RESET pin
* - I2C Address = 0x3C
* - I have to re-allocate I2C SDA/SCL, due to conflict with onboard RGB LED.
* - SDA = 3
* - SCL = 2
*/
#define SDA_pin 3
#define SCL_pin 2
#define OLED_RESET -1 //4 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C //0x3D /// ...
//Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Adafruit_SSD1306 display;
#define NUMFLAKES 10 // Number of snowflakes in the animation example
.
.
.
void setup() {
Serial.begin(9600);
// by Erik 2021-12-13
// Call Wire.setPins to assign SDA/SCL pins
Wire.setPins(SDA_pin,SCL_pin);
display = Adafruit_SSD1306(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
.
.
.
i2c_scanner
is a simple sketch scans the I2C-bus for devices. If a device is found,
it is reported to the Arduino serial monitor.
With arduino-esp32,
the default I2C of "ESP32C3 Dev Modul" is assigned on:
- SDA:
GPIO8
- SCL: GPIO9
(ref: arduino-esp32, list the pre-defined function pins of ESP32C3/S2 Dev
Module)
But on ESP32-C3-DevKitM-1,GPIO8 is connected to on-board
RGB LED (WS2812).
(ref:
ESP32-C3-DevKitM-1 User Guide)
So I have to assign I2C to other custom SDA/SCL pins, by
calling Wire.setPins() before Wire.begin().
Wire.setPins(SDA_pin, SCL_pin);
Wire.begin();
How it run on ESP32-C3-DevKitM-1, with SSD1306 conected. The detected I2C
address is 0x3C.