Here MicroPython test code for CyberBrick official remote (with X12 shield) to transmit 12-bit proportional inputs in 12-bit resolution and 4 binary channels via ESP-NOW to CyberBrick Core running on the receiver side (demo example with debug printout in Where is documentation on building applications for Cyberbrick? - #27 by xrk - more than debug output demo on receiver side not yet available, thus not yet able to drive or control a model).
The demo below transmits data at 10 Hz (indulge me the added fun with the “breathing” NeoPixel in the code below).
from machine import Pin, ADC
import network
import aioespnow
import asyncio
from neopixel import NeoPixel
# Comment lists controls as used by the CyberBrick official standard remote
l1 = ADC(Pin(0), atten=ADC.ATTN_11DB) # 3-way-switch
l2 = ADC(Pin(1), atten=ADC.ATTN_11DB) # LH
l3 = ADC(Pin(2), atten=ADC.ATTN_11DB) # LV
r1 = ADC(Pin(3), atten=ADC.ATTN_11DB) # S1
r2 = ADC(Pin(4), atten=ADC.ATTN_11DB) # RH
r3 = ADC(Pin(5), atten=ADC.ATTN_11DB) # RV
k1 = Pin(6, Pin.IN) # Button
k2 = Pin(7, Pin.IN) # Not used
k3 = Pin(21, Pin.IN) # Not used
k4 = Pin(20, Pin.IN) # Not used
# NeoPixel on CyberBrick Core
npcore = Pin(8, Pin.OUT)
np = NeoPixel(npcore, 1)
# Initialize Wi-Fi in station mode
sta = network.WLAN(network.STA_IF)
sta.active(True)
sta.config(channel=1) # Set channel explicitly if packets are not delivered
sta.disconnect()
# Initialize AIOESPNow
e = aioespnow.AIOESPNow()
try:
e.active(True)
except OSError as err:
print("Failed to initialize AIOESPNow:", err)
raise
# Receiver's MAC address (Replace with your receiver MAC aa:bb:cc:dd:ee:ff!)
receiver_mac = b'\xaa\xbb\xcc\xdd\xee\xff'
#receiver_mac = b'\xff\xff\xff\xff\xff\xff' #broadcast
# Add peer
try:
e.add_peer(receiver_mac)
except OSError as err:
print("Failed to add peer:", err)
raise
# Async function to send messages
async def send_messages(e, peer, np):
val = 16 # Initial value for NeoPixel pulsing
while True:
try:
message = f"{l1.read()},{l2.read()},{l3.read()},{r1.read()},{r2.read()},{r3.read()},{k1.value()},{k2.value()},{k3.value()},{k4.value()}"
await e.asend(peer, message)
# Breathing LED effect in violet tone
if (val > 255): #0 to 255 ascending
np[0] = ((int)((511-val)/2), 0, (511-val))
else: #256 to 511 decending
np[0] = ((int)(val/2), 0, val)
np.write()
val = val + 8 # NeoPixel intensity change step size
if val > (511-16):
val = 16 #Lowest value for NeoPixel pulsing
await asyncio.sleep(0.1) # Send every 100 millisecond / @10 Hz
except OSError as err:
print("Error:", err)
await asyncio.sleep(0.5)
# Main async function
async def main(e, peer, np):
await send_messages(e, peer, np)
# Run the async program
try:
asyncio.run(main(e, receiver_mac, np))
except KeyboardInterrupt:
print("Stopping sender...")
e.active(False)
sta.active(False)
The above code transmits the 6 proportional channel and 4 digital channel data from X12 transmitter shield inputs in human-readable ASCII form. This is nice for debugging and initial tests, but not good for bandwidth. To send six 12-bit proportional values with 4 digital values, only ceiling((6*12 + 4)/8) = 10 bytes are needed, when the data is better packed (and there will even be 4 spare bits to use). Compacting with uctypes is unfortunately not an option, as CyberBrick firmware has uctypes.struct() removed
https://makerworld.com/en/cyberbrick/api-doc/library/index.html#modifications-to-built-in-micropython-interfaces-on-cyberbrick-multi-function-core-board
The X11 receiver and X12 transmitter shields carry the MAC address sticker, but the MAC address is not bound to the shields, but to the ESP32-C3 chip on the Core module sitting on top of the X11 and X12 shields. Thus keep in mind, if you mix or replace the shields, then the sticker is listing incorrect MAC address…
Bambu/MakerWorld would have best used a sticker on the Core module, and if there was no room on the top side due to serial number QR code sticker, they could have sticked the MAC sticker to the backside of the Core module…