adafruit_miniqr
is a A non-hardware dependant miniature QR generator library.
Once
Adafruit CircuitPython Libraries downloaded (as shown in
last post's video), there are two examples miniqr_simpletest.py and miniqr_displaytest.py in
extracted examples foler, or can be found
here.
cpyX_miniqr_ssd1306.py is modified from miniqr_displaytest.py,
to run on Seeed XIAO BLE Sense (nRF52840)/CircuitPython 7.2.3 to generate QR
Code and display on SSD1306 I2C OLED.
cpyX_miniqr_ssd1306.py
"""
CircuitPython 7.2.3 exercise run on
Seeed XIAO nRF52840 Sense with nRF52840
- generate QR Code using adafruit_miniqr
- display on SSD1306 I2C OLED
lib needed:
- adafruit_displayio_ssd1306.mpy
- adafruit_miniqr.mpy
"""
import os
import sys
import board
import busio
import displayio
import adafruit_displayio_ssd1306
import adafruit_miniqr
displayio.release_displays()
print("=================================================")
info = sys.implementation[0] + ' ' + os.uname()[3] + '\n' + \
'run on ' + os.uname()[4]
print(info)
print("=================================================")
print(adafruit_miniqr.__name__,
adafruit_miniqr.__version__)
print(adafruit_displayio_ssd1306.__name__,
adafruit_displayio_ssd1306.__version__)
# Create the I2C interface and display object of SSD1306_I2C.
i2c = busio.I2C(board.SCL, board.SDA)
ssd1306_i2c_addr = 60
display_width =128
display_height = 64
display_bus = displayio.I2CDisplay(
i2c, device_address=ssd1306_i2c_addr)
display = adafruit_displayio_ssd1306.SSD1306(
display_bus, width=display_width, height=display_height)
# remark by Erik:
# base on my testing on 128x64 SSD1306,
# A full white background can improve the recognition
# so I add a background in white
background_bitmap = displayio.Bitmap(display_width,
display_height, 1)
background_palette = displayio.Palette(1)
background_palette[0] = 0xFFFFFF
bg_sprite = displayio.TileGrid(background_bitmap,
pixel_shader=background_palette,
x=0, y=0)
def bitmap_QR(matrix):
# monochome (2 color) palette
BORDER_PIXELS = 2
# bitmap the size of the screen, monochrome (2 colors)
bitmap = displayio.Bitmap(
matrix.width + 2 * BORDER_PIXELS,
matrix.height + 2 * BORDER_PIXELS, 2
)
# raster the QR code
for y in range(matrix.height): # each scanline in the height
for x in range(matrix.width):
if matrix[x, y]:
bitmap[x + BORDER_PIXELS, y + BORDER_PIXELS] = 1
else:
bitmap[x + BORDER_PIXELS, y + BORDER_PIXELS] = 0
return bitmap
qr = adafruit_miniqr.QRCode(qr_type=3,
error_correct=adafruit_miniqr.L)
qr.add_data(b"http://embedded-things.blogspot.com/")
qr.make()
# generate the 1-pixel-per-bit bitmap
qr_bitmap = bitmap_QR(qr.matrix)
# We'll draw with a classic black/white palette
palette = displayio.Palette(2)
palette[0] = 0xFFFFFF
palette[1] = 0x000000
# we'll scale the QR code as big as the display can handle
scale = min(
display_width // qr_bitmap.width,
display_height // qr_bitmap.height
)
# then center it!
pos_x = int(((display_width / scale) - qr_bitmap.width) / 2)
pos_y = int(((display_height / scale) - qr_bitmap.height) / 2)
qr_img = displayio.TileGrid(qr_bitmap,
pixel_shader=palette,
x=pos_x, y=pos_y)
splash = displayio.Group(scale=scale)
splash.append(bg_sprite)
splash.append(qr_img)
display.show(splash)
# Hang out forever
while True:
pass
In CircuitPython, to display on SSD1306, there are two approach: -
framebuf (using adafruit_ssd1306/adafruit_framebuf) - displayio
(using adafruit_displayio_ssd1306)
NUCLEO-F401RE
is a STM32 Nucleo-64 development board with STM32F401RE MCU.
Development Tools/platforms:
-
STM32CubeIDE
is an advanced C/C++ development platform with peripheral configuration, code
generation, code compilation, and debug features for STM32 microcontrollers and
microprocessors.
- Mbed Studio is a free desktop IDE for Mbed OS application and library development, including all the dependencies and tools you need in a single package so that you can create, compile and debug your Mbed programs on the desktop.
"""
CircuitPython 7 exercise run on XIAO BLE Sense,
get system info.
"""
import board
import sys
import os
import microcontroller
# 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(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("microcontroller.cpu.frequency:\t\t" + color.RED +
str(microcontroller.cpu.frequency) + color.END + " Hz")
print("microcontroller.cpu.temperature:\t" + color.RED +
str(microcontroller.cpu.temperature) + color.END + " C")
print("microcontroller.cpu.voltage:\t\t" + color.RED +
str(microcontroller.cpu.voltage) + color.END + " V")
print()
cpyX_pins_name.py, list pins name.
"""CircuitPython Essentials Pin Map Script"""
import microcontroller
import board
board_pins = []
for pin in dir(microcontroller.pin):
if isinstance(getattr(microcontroller.pin, pin), microcontroller.Pin):
pins = []
pins.append("microcontroller.{}".format(pin))
pins.append('\t-')
for alias in dir(board):
if getattr(board, alias) is getattr(microcontroller.pin, pin):
pins.append("board.{}\t".format(alias))
if len(pins) > 0:
board_pins.append(" ".join(pins))
for pins in sorted(board_pins):
print(pins)
It's just my exercise running on Arduino Nano RP2040 Connect/CircuitPython
7.2.3, to work with ov7670 cam module and display on ST7789 SPI display.
For the connection between Nano RP2040 Connect and ov7670/st7789, refer to
the code listed below.
In my practice, pre-defined SPI MOSI/SCK are
assigned to SDA/SCL for ST7789. I2C SCL/SDA are assigned to SCL/SDA for
ov7670.
*ov7670 SCL/SDA are I2C-like control pins, pull-up resistors
are needed. 2K ohm resistors are used in my exercise.
For the st7789
part, it's very straightforward - just install libraries and run the exercise
code. Libraries adafruit_st7789 and adafruit_display_text are needed.
For
ov7670 part, libraries adafruit_st7789 and adafruit_ov7670 are needed.
adafruit_ov7670 is a CircuitPython driver for OV7670 cameras.
The
problem is in adafruit_ov7670, data_pins is a list of 8 data pins in sequential
order. But I can't find 8 continuous sequence GPIO on Nano RP2040 Connect.
As an exercise, GPIO14~21 are assigned to ov7670 d0~d7, GPIO14 is internal
connceted to SCK of the onboard ESP32 (U-blox Nina W102), so it's actually no
use. So there are only 7 bits in parallel data bus, and ESP32 SCK is mis-used
(you should cannot use ESP32 at the same time). That's why I call it
"incomplete".
It seem functionally work, as shown in the video. But I
don't know any side-effect. It's just my exercise and not suggested, or follow
at your own risk.
To list pins name of all GPIOs (include internal),
read
last post.
cpyNrp2040_spiST7789_320.py
"""
Example of Arduino Nano RP2040 Connect/CircuitPython 7.2.3
to display on 2.0" IPS 240x320 (RGB) screen
with SPI ST7789 driver.
Connection between Nano RP2040 Connect and
the SPI ST7789 IPS screen.
BLK - 3V3 (backlight, always on)
CS - A0
DC - A1
RES - A2
SDA - D11 (=MOSI)
SCL - D13 (=SCK)
VCC - 3V3
GND - GND
"""
import os
import sys
import board
import microcontroller
import time
import terminalio
import displayio
import busio
from adafruit_display_text import label
#from adafruit_st7789 import ST7789
import adafruit_st7789
print("=====================================")
info = sys.implementation[0] + ' ' + \
os.uname()[3] + '\n' + \
'run on ' + os.uname()[4]
print(info)
print("board_id:", board.board_id)
print("with number of cpu: " +
str(len(microcontroller.cpus)))
print("=====================================")
print(adafruit_st7789.__name__ + " version: "
+ adafruit_st7789.__version__)
print()
# Release any resources currently in use for the displays
displayio.release_displays()
tft_cs = board.A0
tft_dc = board.A1
tft_res = board.A2
spi_mosi = board.D11
spi_clk = board.D13
"""
classbusio.SPI(clock: microcontroller.Pin,
MOSI: Optional[microcontroller.Pin] = None,
MISO: Optional[microcontroller.Pin] = None)
"""
spi = busio.SPI(clock=spi_clk, MOSI=spi_mosi)
display_bus = displayio.FourWire(
spi, command=tft_dc, chip_select=tft_cs, reset=tft_res
)
display = adafruit_st7789.ST7789(display_bus,
width=240, height=320)
# Make the display context
splash = displayio.Group()
display.show(splash)
color_bitmap = displayio.Bitmap(135, 240, 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(133, 238, 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=20, y=40)
text1 = os.uname()[4]
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=20, y=60)
text2 = sys.implementation[0] + " " + os.uname()[3]
text_area2 = label.Label(terminalio.FONT, text=text2, color=0x00FF00)
text_group2.append(text_area2) # Subgroup for text scaling
# Draw a label
text_group3 = displayio.Group(scale=2, x=20, y=100)
text3 = adafruit_st7789.__name__
text_area3 = label.Label(terminalio.FONT, text=text3, color=0xFFFFFF)
text_group3.append(text_area3) # Subgroup for text scaling
# Draw a label
text_group4 = displayio.Group(scale=2, x=20, y=120)
text4 = adafruit_st7789.__version__
text_area4 = label.Label(terminalio.FONT, text=text4, color=0xFFFFFF)
text_group4.append(text_area4) # Subgroup for text scaling
splash.append(text_group1)
splash.append(text_group2)
splash.append(text_group3)
splash.append(text_group4)
time.sleep(3.0)
rot = 0
while True:
time.sleep(5.0)
rot = rot + 90
if (rot>=360):
rot =0
display.rotation = rot
cpyNrp2040_ov7670_displayio_pico_st7789.py
"""
Run on Arduino NANO RP2040 Connect/CircuitPython 7.2.3
+ ov7670 cam + st7789 LCD.
Capture images from the camera and display it on LCD.
Modified from ov7670_displayio_pico_st7789_2in.py example
ref:
Adafruit CircuitPython ov7670 Library
https://docs.circuitpython.org/projects/ov7670/
"""
import time
from displayio import (
Bitmap,
Group,
TileGrid,
FourWire,
release_displays,
ColorConverter,
Colorspace,
)
import board
import microcontroller
import busio
import digitalio
import displayio
import adafruit_st7789
import adafruit_ov7670
"""
Connection between Nano RP2040 Connect and
the SPI ST7789 IPS screen.
==========================================
BLK - 3V3 (backlight, always on)
CS - A0
DC - A1
RES - A2
SDA - D11 (MOSI)
SCL - D13 (SCK)
VCC - 3V3
GND - GND
"""
tft_cs = board.A0
tft_dc = board.A1
tft_res = board.A2
spi_mosi = board.D11
spi_clk = board.D13
"""
Connection between Arduino Nano RP2040 Connect and
the ov7670 camera module.
==========================================
ov7670
+-----------+
3V3 |3V3 GND | GND
A5 (SCL) |SCL SDA | A4 (SDA)
TX |VS HS | RX
D12 |PLK XLK | D10
D9 |D7 D6 | D8
D7 |D5 D4 | D6
D5 |D3 D2 | D4
D3 |D1 D0 | XXX
A3 |RET PWDN| -
+-----------+
*ov7670 SCL/SDA are I2C-like control pins, pull-up resistors are needed.
I use 2K ohm resistor for it.
"""
cam_scl = board.A5
cam_sda = board.A4
cam_vs = board.TX
cam_hs = board.RX
cam_plk = board.D12
cam_xlk = board.D10
cam_ret = board.A3
# cam data pins must be sequential
# I can't find 8 continuous sequence GPIO on Nano RP2040 Connect
# As a exercise, I assign GPIO14~21 to d0~d7,
# GPIO14 is internal connceted to onboard ESP32 SCK,
# so it's actually no use.
cam_d0 = board.SCK1 # GPIO14
cam_d1 = board.D3 # GPIO15
cam_d2 = board.D4 # GPIO16
cam_d3 = board.D5 # GPIO17
cam_d4 = board.D6 # GPIO18
cam_d5 = board.D7 # GPIO19
cam_d6 = board.D8 # GPIO20
cam_d7 = board.D9 # GPIO21
release_displays()
# Set up the display
spi = busio.SPI(clock=spi_clk, MOSI=spi_mosi)
display_bus = displayio.FourWire(
spi, command=tft_dc, chip_select=tft_cs, reset=tft_res)
display = adafruit_st7789.ST7789(display_bus,
width=240, height=320)
display.auto_refresh = False
# Ensure the camera is shut down,
# so that it releases the SDA/SCL lines,
# then create the configuration I2C bus
with digitalio.DigitalInOut(cam_ret) as reset:
reset.switch_to_output(False)
time.sleep(0.001)
bus = busio.I2C(cam_scl, cam_sda)
# Set up the camera
cam = adafruit_ov7670.OV7670(
bus,
data_pins=[
cam_d0,
cam_d1,
cam_d2,
cam_d3,
cam_d4,
cam_d5,
cam_d6,
cam_d7,
], #Pins must be sequential
clock=cam_plk,
vsync=cam_vs,
href=cam_hs,
mclk=cam_xlk,
shutdown=None,
reset=cam_ret,
)
#cam.test_pattern = adafruit_ov7670.OV7670_TEST_PATTERN_COLOR_BAR
print(adafruit_ov7670.__name__ + " version: "
+ adafruit_ov7670.__version__)
print(adafruit_st7789.__name__ + " version: "
+ adafruit_st7789.__version__)
pid = cam.product_id
ver = cam.product_version
print(f"Detected cam pid={pid:x} ver={ver:x}")
width = display.width
height = display.height
bitmap = None
# Select the biggest size for which we can allocate a bitmap successfully,
# and which is not bigger than the display
for size in range(adafruit_ov7670.OV7670_SIZE_DIV1,
adafruit_ov7670.OV7670_SIZE_DIV16 + 1):
cam.size = size
if cam.width > width:
continue
if cam.height > height:
continue
try:
bitmap = Bitmap(cam.width, cam.height, 65536)
break
except MemoryError:
continue
print(width, height, cam.width, cam.height)
if bitmap is None:
raise SystemExit("Could not allocate a bitmap")
g = Group(scale=1,
x=(width - cam.width) // 2,
y=(height - cam.height) // 2)
tg = TileGrid(
bitmap, pixel_shader=ColorConverter(
input_colorspace=Colorspace.RGB565_SWAPPED)
)
g.append(tg)
display.show(g)
#t0 = time.monotonic_ns()
display.auto_refresh = False
while True:
cam.capture(bitmap)
bitmap.dirty()
display.refresh(minimum_frames_per_second=0)
#t1 = time.monotonic_ns()
#print("fps", 1e9 / (t1 - t0))
#t0 = t1
"""CircuitPython Essentials Pin Map Script"""
import microcontroller
import board
board_pins = []
for pin in dir(microcontroller.pin):
if isinstance(getattr(microcontroller.pin, pin), microcontroller.Pin):
pins = []
pins.append("microcontroller.{}".format(pin))
pins.append('\t-')
for alias in dir(board):
if getattr(board, alias) is getattr(microcontroller.pin, pin):
pins.append("board.{}\t".format(alias))
if len(pins) > 0:
board_pins.append(" ".join(pins))
for pins in sorted(board_pins):
print(pins)
After CircuitPython 7.2.3 was installed on Arduino Nano
RP2040 Connect, I can run REPL. BUT...I can't access CircuitPython
device (named "?"), Problem when handling 'get_dirs_children_info_response'
with "RuntimeError: None data for /?"!
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/thonny/workbench.py", line 1711, in event_generate
handler(event)
File "/usr/lib/python3/dist-packages/thonny/base_file_browser.py", line 1001, in update_dir_data
self.render_children_from_cache(msg["node_id"])
File "/usr/lib/python3/dist-packages/thonny/base_file_browser.py", line 430, in render_children_from_cache
raise RuntimeError("None data for %s" % path)
RuntimeError: None data for /?
Seeed XIAO BLE Sense: XIAOBLE_CallbackLED_OLED.ino, act as BLE
Peripheral, control LED and OLED display base on BLE received data.
Arduino Nano RP2040 Connect: RP2040Con_LedControl_OLED.ino, act as
BLE Central, read button (the yellow wire) and get user input from Serial,
send to Peripheral to control LED and display on OLED.
XIAOBLE_CallbackLED_OLED.ino
/*
Run on XIAO BLESensor:
This example creates a BLE peripheral with service that contains a
characteristic to control an LED and OLED. The callback features of the
library are used.
Modified from ArduinoBLE > Peripheral > CallbackLED example
*/
#include <ArduinoBLE.h>
#include <Arduino.h>
#include <U8x8lib.h>
#include <Wire.h>
#define MyLocalName "XIAO BLE"
#define MyStringChar_UUID "22a28815-c6bd-401b-a0f1-d47c42a0bd70"
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);
BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // create service
// create switch characteristic and allow remote device to read and write
BLEByteCharacteristic switchCharacteristic(
"19B10001-E8F2-537E-4F6C-D104768A1214",
BLERead | BLEWrite);
BLEStringCharacteristic myStringCharacteristic(
MyStringChar_UUID,
BLERead | BLEWrite, 16);
const int ledPin = LED_BUILTIN; // pin to use for the LED
void setup() {
u8x8.begin();
u8x8.setFlipMode(1); //rotary 180
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8.setCursor(0, 0);
u8x8.print("XIAO BLE");
Serial.begin(9600);
//comment to skip Serial port waiting,
//such that it can sork stand alone without computer.
//while (!Serial);
pinMode(ledPin, OUTPUT); // use the LED pin as an output
// begin initialization
if (!BLE.begin()) {
Serial.println("starting BLE failed!");
while (1);
}
// set the local name peripheral advertises
BLE.setLocalName(MyLocalName);
// set the UUID for the service this peripheral advertises
BLE.setAdvertisedService(ledService);
// add the characteristic to the service
ledService.addCharacteristic(switchCharacteristic);
ledService.addCharacteristic(myStringCharacteristic);
// add service
BLE.addService(ledService);
// assign event handlers for connected, disconnected to peripheral
BLE.setEventHandler(BLEConnected, blePeripheralConnectHandler);
BLE.setEventHandler(BLEDisconnected, blePeripheralDisconnectHandler);
// assign event handlers for characteristic
switchCharacteristic.setEventHandler(BLEWritten, switchCharacteristicWritten);
myStringCharacteristic.setEventHandler(BLEWritten, myStringCharacteristicWritten);
// set an initial value for the characteristic
switchCharacteristic.setValue(0);
myStringCharacteristic.setValue("XIAO BLE");
// start advertising
BLE.advertise();
Serial.println(("Bluetooth device active, waiting for connections..."));
}
void loop() {
// poll for BLE events
BLE.poll();
}
void blePeripheralConnectHandler(BLEDevice central) {
// central connected event handler
Serial.print("Connected event, central: ");
Serial.println(central.address());
}
void blePeripheralDisconnectHandler(BLEDevice central) {
// central disconnected event handler
Serial.print("Disconnected event, central: ");
Serial.println(central.address());
}
void switchCharacteristicWritten(BLEDevice central,
BLECharacteristic characteristic) {
// central wrote new value to characteristic, update LED
Serial.print("Characteristic event, written: ");
if (switchCharacteristic.value()) {
Serial.println("LED on");
digitalWrite(ledPin, !HIGH);
} else {
Serial.println("LED off");
digitalWrite(ledPin, !LOW);
}
}
void myStringCharacteristicWritten(BLEDevice central,
BLECharacteristic characteristic) {
// central wrote new value to characteristic, update LED
Serial.println("mySttringCharacteristic event, written: ");
Serial.println("myStringCharacteristic received: len=" +
String(myStringCharacteristic.valueLength()));
String valString = myStringCharacteristic.value();
Serial.println(valString);
u8x8.clear();
u8x8.setCursor(0, 0);
u8x8.print(valString);
Serial.println();
}
RP2040Con_LedControl_OLED.ino
/*
run on Aduino RP2040 NANO Connect
This example scans for BLE peripherals until one with the advertised service
"19b10000-e8f2-537e-4f6c-d104768a1214" UUID is found. Once discovered and connected,
it will remotely control the BLE Peripheral's LED, when the button is pressed or released.
And also get user input from Serial Monitor, send to BLE Peripheral
modified from ArduinoBLE > Central > LedControl
*/
#include <ArduinoBLE.h>
// variables for button
const int buttonPin = 2;
int oldButtonState = LOW;
#define MyLocalName "XIAO BLE"
#define MyStringChar_UUID "22a28815-c6bd-401b-a0f1-d47c42a0bd70"
void setup() {
Serial.begin(9600);
while (!Serial);
// configure the button pin as input
pinMode(buttonPin, INPUT_PULLUP);
// initialize the BLE hardware
BLE.begin();
Serial.println("BLE Central - LED control");
// start scanning for peripherals
BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214");
}
void loop() {
// check if a peripheral has been discovered
BLEDevice peripheral = BLE.available();
if (peripheral) {
// discovered a peripheral, print out address, local name, and advertised service
Serial.print("Found ");
Serial.print(peripheral.address());
Serial.print(" '");
Serial.print(peripheral.localName());
Serial.print("' ");
Serial.print(peripheral.advertisedServiceUuid());
Serial.println();
if (peripheral.localName() != MyLocalName) {
return;
}
// stop scanning
BLE.stopScan();
controlLed(peripheral);
// peripheral disconnected, start scanning again
BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214");
}
}
void controlLed(BLEDevice peripheral) {
// connect to the peripheral
Serial.println("Connecting ...");
if (peripheral.connect()) {
Serial.println("Connected");
} else {
Serial.println("Failed to connect!");
return;
}
// discover peripheral attributes
Serial.println("Discovering attributes ...");
if (peripheral.discoverAttributes()) {
Serial.println("Attributes discovered");
} else {
Serial.println("Attribute discovery failed!");
peripheral.disconnect();
return;
}
// retrieve the LED/OLED characteristic
BLECharacteristic ledCharacteristic = peripheral.characteristic("19b10001-e8f2-537e-4f6c-d104768a1214");
BLECharacteristic oledCharacteristic = peripheral.characteristic(MyStringChar_UUID);
/*
if (!ledCharacteristic) {
Serial.println("Peripheral does not have LED characteristic!");
peripheral.disconnect();
return;
} else if (!ledCharacteristic.canWrite()) {
Serial.println("Peripheral does not have a writable LED characteristic!");
peripheral.disconnect();
return;
}
*/
while (peripheral.connected()) {
// while the peripheral is connected
// read the button pin
int buttonState = !digitalRead(buttonPin);
if (oldButtonState != buttonState) {
// button changed
oldButtonState = buttonState;
if (buttonState) {
Serial.println("button pressed");
// button is pressed, write 0x01 to turn the LED on
ledCharacteristic.writeValue((byte)0x01);
} else {
Serial.println("button released");
// button is released, write 0x00 to turn the LED off
ledCharacteristic.writeValue((byte)0x00);
}
}
if (Serial.available() > 0){
String stringIn = Serial.readString();
Serial.println(stringIn);
oledCharacteristic.writeValue(stringIn.c_str());
}
}
Serial.println("Peripheral disconnected");
}
XIAO BLE Sense (with Seeeduino XIAO Expansion board)
act as Central, connect Peripher, send command base on user button on Expansion
board, to control LED on off.
Load with ArduinoBLE > Central >
LedControl example.
To make it work, change in following,
marked in RED:
XIAOBLE_LedControl.ino
/*
LED Control
This example scans for BLE peripherals until one with the advertised service
"19b10000-e8f2-537e-4f6c-d104768a1214" UUID is found. Once discovered and connected,
it will remotely control the BLE Peripheral's LED, when the button is pressed or released.
The circuit:
- Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.
- Button with pull-up resistor connected to pin 2.
You can use it with another board that is compatible with this library and the
Peripherals -> LED example.
This example code is in the public domain.
*/
#include <ArduinoBLE.h>
// variables for button
const int buttonPin = 1;
int oldButtonState = LOW;
void setup() {
Serial.begin(9600);
while (!Serial);
// configure the button pin as input
pinMode(buttonPin, INPUT_PULLUP);
// initialize the BLE hardware
BLE.begin();
Serial.println("BLE Central - LED control");
// start scanning for peripherals
BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214");
}
void loop() {
// check if a peripheral has been discovered
BLEDevice peripheral = BLE.available();
if (peripheral) {
// discovered a peripheral, print out address, local name, and advertised service
Serial.print("Found ");
Serial.print(peripheral.address());
Serial.print(" '");
Serial.print(peripheral.localName());
Serial.print("' ");
Serial.print(peripheral.advertisedServiceUuid());
Serial.println();
if (peripheral.localName() != "LED") {
return;
}
// stop scanning
BLE.stopScan();
controlLed(peripheral);
// peripheral disconnected, start scanning again
BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214");
}
}
void controlLed(BLEDevice peripheral) {
// connect to the peripheral
Serial.println("Connecting ...");
if (peripheral.connect()) {
Serial.println("Connected");
} else {
Serial.println("Failed to connect!");
return;
}
// discover peripheral attributes
Serial.println("Discovering attributes ...");
if (peripheral.discoverAttributes()) {
Serial.println("Attributes discovered");
} else {
Serial.println("Attribute discovery failed!");
peripheral.disconnect();
return;
}
// retrieve the LED characteristic
BLECharacteristic ledCharacteristic = peripheral.characteristic("19b10001-e8f2-537e-4f6c-d104768a1214");
if (!ledCharacteristic) {
Serial.println("Peripheral does not have LED characteristic!");
peripheral.disconnect();
return;
} else if (!ledCharacteristic.canWrite()) {
Serial.println("Peripheral does not have a writable LED characteristic!");
peripheral.disconnect();
return;
}
while (peripheral.connected()) {
// while the peripheral is connected
// read the button pin
int buttonState = !digitalRead(buttonPin);
if (oldButtonState != buttonState) {
// button changed
oldButtonState = buttonState;
if (buttonState) {
Serial.println("button pressed");
// button is pressed, write 0x01 to turn the LED on
ledCharacteristic.writeValue((byte)0x01);
} else {
Serial.println("button released");
// button is released, write 0x00 to turn the LED off
ledCharacteristic.writeValue((byte)0x00);
}
}
}
Serial.println("Peripheral disconnected");
}
After then, there are two selection of "Arduino Nano RP2040
Connect" from "Arduino Mbed OS Boards" and "Arduino Mbed OS Nano Boards".
Case I - "Arduino Nano RP2040 Connect" from "Arduino Mbed OS Boards", actually
it come from Seeed nRF52 Boards 2.6.1:
Select board "Arduino Nano RP2040 Connect" from "Arduino Mbed OS Boards"
If you have ArduinoBLE library installed, its examples is located
within INCOMPATIBLE.
If you compile any example, even Blink, error will be reported!
Arduino: 1.8.15 (Linux), Board: "Arduino Nano RP2040 Connect"
WARNING: library ArduinoBLE claims to run on samd, megaavr, mbed, apollo3, mbed_nano, mbed_portenta architecture(s) and may be incompatible with your current board which runs on nrf52 architecture(s).
Traceback (most recent call last):
File "/home/pi/.local/bin/adafruit-nrfutil", line 10, in <module>
sys.exit(cli())
File "/usr/lib/python3/dist-packages/click/core.py", line 764, in __call__
return self.main(*args, **kwargs)
File "/usr/lib/python3/dist-packages/click/core.py", line 717, in main
rv = self.invoke(ctx)
File "/usr/lib/python3/dist-packages/click/core.py", line 1137, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/usr/lib/python3/dist-packages/click/core.py", line 1137, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/usr/lib/python3/dist-packages/click/core.py", line 956, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/usr/lib/python3/dist-packages/click/core.py", line 555, in invoke
return callback(*args, **kwargs)
File "/home/pi/.local/lib/python3.7/site-packages/nordicsemi/__main__.py", line 239, in genpkg
package.generate_package(zipfile_path)
File "/home/pi/.local/lib/python3.7/site-packages/nordicsemi/dfu/package.py", line 189, in generate_package
Package.normalize_firmware_to_bin(work_directory, firmware[FirmwareKeys.FIRMWARE_FILENAME])
File "/home/pi/.local/lib/python3.7/site-packages/nordicsemi/dfu/package.py", line 329, in normalize_firmware_to_bin
temp.tobinfile(new_filepath)
File "/home/pi/.local/lib/python3.7/site-packages/nordicsemi/dfu/nrfhex.py", line 160, in tobinfile
start_address = self.minaddr()
File "/home/pi/.local/lib/python3.7/site-packages/nordicsemi/dfu/nrfhex.py", line 114, in minaddr
min_address = max(self.get_mbr_end_address(), min_address)
TypeError: '>' not supported between instances of 'NoneType' and 'int'
exit status 1
Error compiling for board Arduino Nano RP2040 Connect.
This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.
Case II - "Arduino Nano RP2040 Connect" from"Arduino Mbed OS Nano Boards" 2.8.0:
Select board "Arduino Nano RP2040 Connect" from "Arduino Mbed OS Nano Boards"
Now ArduinoBLE example is located under Custom Libraries.
To make it work on XIAO BLE
Sense/Expansion board (Arduino Framework), change the code as
below, using U8X8_SSD1306_128X64_NONAME_HW_I2C instead of
U8X8_SSD1306_128X64_NONAME_SW_I2C.
Tools > Board > Boards Manager... - Search and install "Seeed nRF52
Boards by Seeed Studio"
Select board: - Tools > Board >
Arduino Mbed OS Boards > "Seeed XIAO nRF52840 Sense" - Select correct
port
Now you can try to program and upload to your XIAO BLE
(Sense).
If you run on Linux, including Raspberry Pi OS, you will be reported with
error:
exec: "adafruit-nrfutil": executable file not found in $PATH Error compiling for board Seeed XIAO nRF52840 Sense. You have to install adafruit-nrfutil manually:
CircuitPython 7.2.0 was
released. With espressif ESP32-S3 and ESP32-C3 supported (considered alpha and will
have bugs and missing functionality).
To flash firmware on esp32s3, esptool v3.2 is needed. This post
show the steps to flash CircuitPython 7.2.0 on
ESP32-S3-DevKitC-1 N8R8
(with 8MB Flash and 8MB PSRAM) run on Linux Mint (over VirtualBox/Windows
10).
Visit
CircuitPython download page, search "S3" and download .BIN for "ESP32-S3-DevKitC-1-N8R8 by
Espressif".
Connect USB to the port marked "UART".
To
check the ESP chip ID and Flash using commands: $ esptool.py --chip auto
--port /dev/ttyUSB0 chip_id $ esptool.py --chip auto --port /dev/ttyUSB0
flash_id
To program using
CircuitPython, re-connect USB to the port marked "USB".
cpyESP32S3_info.py
"""
CircuitPython 7.2.0 exercise run on ESP32-S3,
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()
cpyESP32S3_NEOPIXEL.py, control onboard RGB LED.
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.GRB)
pixel[0] = (0, 0, 0)
time.sleep(2.0)
cycleNeopixel(0.01)
pixel[0] = (0, 0, 0)
time.sleep(2.0)
print("- bye -\n")
Related: ~ To flash ESP32-S3, esptool v3.2 or above is needed. With esptool upgraded, we can now flash ESP32-S3 on Rspberry Pi.
$ esptool.py --chip auto --port /dev/ttyUSB0 chip_id
$ esptool.py --chip auto --port /dev/ttyUSB0 flash_id
for ESP-C3-32S-Kit:
pi@raspberrypi:~ $ esptool.py --chip auto --port /dev/ttyUSB0 chip_id
esptool.py v3.1
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... ESP32-C3
Chip is unknown ESP32-C3 (revision 3)
Features: Wi-Fi
Crystal is 40MHz
MAC: 34:b4:72:4e:19:f4
Uploading stub...
Running stub...
Stub running...
Warning: ESP32-C3 has no Chip ID. Reading MAC instead.
MAC: 34:b4:72:4e:19:f4
Hard resetting via RTS pin...
pi@raspberrypi:~ $ esptool.py --chip auto --port /dev/ttyUSB0 flash_id
esptool.py v3.1
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... ESP32-C3
Chip is unknown ESP32-C3 (revision 3)
Features: Wi-Fi
Crystal is 40MHz
MAC: 34:b4:72:4e:19:f4
Uploading stub...
Running stub...
Stub running...
Manufacturer: 20
Device: 4016
Detected flash size: 4MB
Hard resetting via RTS pin...
ESP-S3-12K-Kit: (esptool v3.2 is needed, error reported in esptool v3.1)
Using
esptool v3.1 on Raspberry Pi, detected as ESP32-S3(beta3) and reported "A
fatal error occurred: Invalid head of packet (0x65)"!
pi@raspberrypi:~ $ esptool.py --chip auto --port /dev/ttyUSB0 chip_id
esptool.py v3.1
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... ESP32-S3(beta3)
Chip is ESP32-S3(beta3)
Features: WiFi, BLE
Crystal is 40MHz
MAC: 00:00:00:00:00:00
Uploading stub...
Running stub...
Stub running...
Warning: ESP32-S3(beta3) has no Chip ID. Reading MAC instead.
A fatal error occurred: Invalid head of packet (0x65)
pi@raspberrypi:~ $ esptool.py --chip auto --port /dev/ttyUSB0 flash_id
esptool.py v3.1
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... ESP32-S3(beta3)
Chip is ESP32-S3(beta3)
Features: WiFi, BLE
Crystal is 40MHz
MAC: 00:00:00:00:00:00
Uploading stub...
Running stub...
Stub running...
A fatal error occurred: Invalid head of packet (0x65)
Using esptool v3.2 on Linux Mint, detected as ESP32-S3 and no error.
eric@eric-VirtualBox:~$ esptool.py --chip auto --port /dev/ttyUSB0 chip_id
esptool.py v3.2
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... ESP32-S3
Chip is ESP32-S3
Features: WiFi, BLE
Crystal is 40MHz
MAC: f4:12:fa:43:65:2c
Uploading stub...
Running stub...
Stub running...
Warning: ESP32-S3 has no Chip ID. Reading MAC instead.
MAC: f4:12:fa:43:65:2c
Hard resetting via RTS pin...
eric@eric-VirtualBox:~$ esptool.py --chip auto --port /dev/ttyUSB0 flash_id
esptool.py v3.2
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... ESP32-S3
Chip is ESP32-S3
Features: WiFi, BLE
Crystal is 40MHz
MAC: f4:12:fa:43:65:2c
Uploading stub...
Running stub...
Stub running...
Manufacturer: c8
Device: 4017
Detected flash size: 8MB
Hard resetting via RTS pin...