diff --git a/ble_main_3.py b/ble_main_3.py new file mode 100644 index 0000000..80ac074 --- /dev/null +++ b/ble_main_3.py @@ -0,0 +1,247 @@ +# Kevin McAleer +# 2023-06-28 +# Bluetooth cores specification versio 5.4 (0x0D) + +import sys + +import aioble +import bluetooth +import gc +import machine +import uasyncio as asyncio +from micropython import const, mem_info +#from pico_lcd_1_14 import LCD_1inch14 +from machine import Pin,SPI,PWM +import framebuf + + + +def uid(): + """ Return the unique id of the device as a string """ + return "{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}".format( + *machine.unique_id()) + +MANUFACTURER_ID = const(0x02A29) +MODEL_NUMBER_ID = const(0x2A24) +SERIAL_NUMBER_ID = const(0x2A25) +HARDWARE_REVISION_ID = const(0x2A26) +BLE_VERSION_ID = const(0x2A28) + +led = machine.Pin("LED", machine.Pin.OUT) + +# Begin set up of LCD +BL = 13 +DC = 8 +RST = 12 +MOSI = 11 +SCK = 10 +CS = 9 + +pwm = PWM(Pin(BL)) +pwm.freq(1000) +pwm.duty_u16(32768)#max 65535 + +#LCD = LCD_1inch14() +#color BRG +"""" +LCD.fill(LCD.white) + +LCD.show() +LCD.text("Raspberry Pi Pico",90,40,LCD.red) +LCD.text("PicoGo",90,60,LCD.green) +LCD.text("Pico-LCD-1.14",90,80,LCD.blue) + +LCD.hline(10,10,220,LCD.blue) +LCD.hline(10,125,220,LCD.blue) +LCD.vline(10,10,115,LCD.blue) +LCD.vline(230,10,115,LCD.blue) + +LCD.show() +""" + +keyA = Pin(15,Pin.IN,Pin.PULL_UP) +keyB = Pin(17,Pin.IN,Pin.PULL_UP) + +key2 = Pin(2 ,Pin.IN,Pin.PULL_UP) +key3 = Pin(3 ,Pin.IN,Pin.PULL_UP) +key4 = Pin(16 ,Pin.IN,Pin.PULL_UP) +key5 = Pin(18 ,Pin.IN,Pin.PULL_UP) +key6 = Pin(20 ,Pin.IN,Pin.PULL_UP) + +# End of LCD setup + + +# _ENV_SENSE_TEMP_UUID = bluetooth.UUID(0x1800) +_GENERIC = bluetooth.UUID(0x1848) +_BUTTON_UUID = bluetooth.UUID(0x2A6E) +_ROBOT = bluetooth.UUID(0x180A) + +_BLE_APPEARANCE_GENERIC_REMOTE_CONTROL = const(384) + +# Advertising frequency +ADV_INTERVAL_MS = 250_000 + +device_info = aioble.Service(_ROBOT) + +connection = None + +# Create characteristics for device info +aioble.Characteristic(device_info, bluetooth.UUID(MANUFACTURER_ID), read=True, initial="KevsRobotsRemote") +aioble.Characteristic(device_info, bluetooth.UUID(MODEL_NUMBER_ID), read=True, initial="1.0") +aioble.Characteristic(device_info, bluetooth.UUID(SERIAL_NUMBER_ID), read=True, initial=uid()) +aioble.Characteristic(device_info, bluetooth.UUID(HARDWARE_REVISION_ID), read=True, initial=sys.version) +aioble.Characteristic(device_info, bluetooth.UUID(BLE_VERSION_ID), read=True, initial="1.0") + +remote_service = aioble.Service(_GENERIC) + +button_characteristic = aioble.Characteristic( + remote_service, _BUTTON_UUID, read=True, notify=True +) + +print('registering services') +aioble.register_services(remote_service, device_info) + +connected = False + +async def remote_task(): + """ Send the event to the connected device """ + while True: + if not connected: + print('not connected') + await asyncio.sleep_ms(1000) + continue + + if (keyA.value() == 0): + button_characteristic.write(b"a") + button_characteristic.notify(connection, b"a") + + elif (keyB.value() == 0): + button_characteristic.write(b"b") + button_characteristic.notify(connection, b"b") + + elif (key2.value() == 0): + button_characteristic.write(b"u") + button_characteristic.notify(connection, b"u") + + elif (key3.value() == 0): + button_characteristic.write(b"c") + button_characteristic.notify(connection, b"c") + + elif (key4.value() == 0): + button_characteristic.write(b"l") + button_characteristic.notify(connection, b"l") + + elif (key5.value() == 0): + button_characteristic.write(b"d") + button_characteristic.notify(connection, b"d") + + elif (key6.value() == 0): + button_characteristic.write(b"r") + button_characteristic.notify(connection, b"r") + + else: + button_characteristic.notify(connection, b"!") + + # Show button pushed on LCD + if(keyA.value() == 0): +# LCD.fill_rect(208,12,20,20,LCD.red) + print("A") +# else : +# LCD.fill_rect(208,12,20,20,LCD.white) +# LCD.rect(208,12,20,20,LCD.red) + + if(keyB.value() == 0): + print("B") + else : + pass +# LCD.fill_rect(208,103,20,20,LCD.white) +# LCD.rect(208,103,20,20,LCD.red) + + if(key2.value() == 0): + # LCD.fill_rect(37,35,20,20,LCD.red) + print("UP") + else : + pass + # LCD.fill_rect(37,35,20,20,LCD.white) + # LCD.rect(37,35,20,20,LCD.red) + + if(key3.value() == 0): + # LCD.fill_rect(37,60,20,20,LCD.red) + print("CTRL") + else : + pass + # LCD.fill_rect(37,60,20,20,LCD.white) + # LCD.rect(37,60,20,20,LCD.red) + + if(key4.value() == 0): + # LCD.fill_rect(12,60,20,20,LCD.red) + print("LEFT") + else : + pass + # LCD.fill_rect(12,60,20,20,LCD.white) + # LCD.rect(12,60,20,20,LCD.red) + + if(key5.value() == 0): + # LCD.fill_rect(37,85,20,20,LCD.red) + print("DOWN") + else : + pass + # LCD.fill_rect(37,85,20,20,LCD.white) + # LCD.rect(37,85,20,20,LCD.red) + + if(key6.value() == 0): + # LCD.fill_rect(62,60,20,20,LCD.red) + print("RIGHT") + else : + pass + # LCD.fill_rect(62,60,20,20,LCD.white) + # LCD.rect(62,60,20,20,LCD.red) + + # LCD.show() + + await asyncio.sleep_ms(10) + + +# Serially wait for connections. +# Don't advertise while a central is connected +async def peripheral_task(): + print('peripheral task started') + global connected, connection + while True: + connected = False + async with await aioble.advertise( + ADV_INTERVAL_MS, + name="KevsRobots", + appearance=_BLE_APPEARANCE_GENERIC_REMOTE_CONTROL, + services=[_GENERIC] + ) as connection: + print("Connection from", connection.device) + connected = True + print(f"connected: {connected}") + await connection.disconnected(timeout_ms=None) + print(f'disconnected') + + +async def blink_task(): + print('blink task started') + toggle = True + while True: + led.value(toggle) + toggle = not toggle + blink = 1000 + if connected: + blink = 1000 + else: + blink = 250 + await asyncio.sleep_ms(blink) + +async def main(): + tasks = [ + asyncio.create_task(peripheral_task()), + asyncio.create_task(blink_task()), + asyncio.create_task(remote_task()), + ] + await asyncio.gather(*tasks) + + +asyncio.run(main()) \ No newline at end of file diff --git a/main.py b/main.py index 80ac074..d158bb3 100644 --- a/main.py +++ b/main.py @@ -1,247 +1,90 @@ -# Kevin McAleer -# 2023-06-28 -# Bluetooth cores specification versio 5.4 (0x0D) +# ir_tx.test Test for nonblocking OpenLaserTag/SONY IR transmitter. +# Sony SIRC protocol. +# Tomas Krejci [Njord] -import sys - -import aioble -import bluetooth -import gc -import machine +# Implements a 2-button remote control on a Pyboard with auto repeat. +from sys import platform +ESP32 = platform == 'esp32' +RP2 = platform == 'rp2' +PYBOARD = platform == 'pyboard' +if ESP32 or RP2: + from machine import Pin +else: + from pyb import Pin, LED import uasyncio as asyncio -from micropython import const, mem_info -#from pico_lcd_1_14 import LCD_1inch14 -from machine import Pin,SPI,PWM -import framebuf +from primitives.switch import Switch +from primitives.delay_ms import Delay_ms +# Import all implemented classes +from olt_lib.ir_tx.olt import LT_24, SONY_12, SONY_15, SONY_20 +loop = asyncio.get_event_loop() -def uid(): - """ Return the unique id of the device as a string """ - return "{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}".format( - *machine.unique_id()) +# If button is held down normal behaviour is to retransmit +# but most NEC models send a REPEAT code +class Rbutton: + toggle = 1 # toggle is ignored in NEC mode + def __init__(self, irb, pin, addr, data, proto): + self.irb = irb + self.sw = Switch(pin) + self.addr = addr + self.data = data + self.proto = proto -MANUFACTURER_ID = const(0x02A29) -MODEL_NUMBER_ID = const(0x2A24) -SERIAL_NUMBER_ID = const(0x2A25) -HARDWARE_REVISION_ID = const(0x2A26) -BLE_VERSION_ID = const(0x2A28) + self.sw.close_func(self.cfunc) + self.sw.open_func(self.ofunc) + self.tim = Delay_ms(self.repeat) -led = machine.Pin("LED", machine.Pin.OUT) + def cfunc(self): # Button push: send data + tog = 0 # NEC, sony 12, 15: toggle==0 + self.irb.transmit(self.addr, self.data, tog, True) # Test validation + # Auto repeat. The Sony protocol specifies 45ms but this is tight. + # In 20 bit mode a data burst can be upto 39ms long. + self.tim.trigger(108) -# Begin set up of LCD -BL = 13 -DC = 8 -RST = 12 -MOSI = 11 -SCK = 10 -CS = 9 + def ofunc(self): # Button release: cancel repeat timer + self.tim.stop() + Rbutton.toggle ^= 1 # Toggle control -pwm = PWM(Pin(BL)) -pwm.freq(1000) -pwm.duty_u16(32768)#max 65535 + async def repeat(self): + await asyncio.sleep(0) # Let timer stop before retriggering + if not self.sw(): # Button is still pressed: retrigger + self.tim.trigger(108) + tog = 0 # NEC, sony 12, 15: toggle==0 + self.irb.transmit(self.addr, self.data, tog, True) # Test validation -#LCD = LCD_1inch14() -#color BRG -"""" -LCD.fill(LCD.white) +async def main(proto): + # Test uses a 56KHz carrier. + if ESP32: # Pins for IR LED gate + pin = Pin(23, Pin.OUT, value = 0) + elif RP2: + pin = Pin(17, Pin.OUT, value = 0) + else: + pin = Pin('X1') + classes = (LT_24, SONY_12, SONY_15, SONY_20) + irb = classes[proto](pin, 56000) # My decoder chip is 56KHz + # Uncomment the following to print transmit timing + irb.timeit = True -LCD.show() -LCD.text("Raspberry Pi Pico",90,40,LCD.red) -LCD.text("PicoGo",90,60,LCD.green) -LCD.text("Pico-LCD-1.14",90,80,LCD.blue) - -LCD.hline(10,10,220,LCD.blue) -LCD.hline(10,125,220,LCD.blue) -LCD.vline(10,10,115,LCD.blue) -LCD.vline(230,10,115,LCD.blue) - -LCD.show() -""" - -keyA = Pin(15,Pin.IN,Pin.PULL_UP) -keyB = Pin(17,Pin.IN,Pin.PULL_UP) - -key2 = Pin(2 ,Pin.IN,Pin.PULL_UP) -key3 = Pin(3 ,Pin.IN,Pin.PULL_UP) -key4 = Pin(16 ,Pin.IN,Pin.PULL_UP) -key5 = Pin(18 ,Pin.IN,Pin.PULL_UP) -key6 = Pin(20 ,Pin.IN,Pin.PULL_UP) - -# End of LCD setup + b = [] # Rbutton instances + px3 = Pin('X3', Pin.IN, Pin.PULL_UP) if PYBOARD else Pin(18, Pin.IN, Pin.PULL_UP) + px4 = Pin('X4', Pin.IN, Pin.PULL_UP) if PYBOARD else Pin(19, Pin.IN, Pin.PULL_UP) + b.append(Rbutton(irb, px3, 0x1, 0x7, proto)) + b.append(Rbutton(irb, px4, 0x10, 0xb, proto)) + if ESP32: + while True: + print('Running') + await asyncio.sleep(5) + elif RP2: + led = Pin(25, Pin.OUT) + while True: + await asyncio.sleep_ms(500) # Obligatory flashing LED. + led(not led()) + else: + led = LED(1) + while True: + await asyncio.sleep_ms(500) # Obligatory flashing LED. + led.toggle() -# _ENV_SENSE_TEMP_UUID = bluetooth.UUID(0x1800) -_GENERIC = bluetooth.UUID(0x1848) -_BUTTON_UUID = bluetooth.UUID(0x2A6E) -_ROBOT = bluetooth.UUID(0x180A) - -_BLE_APPEARANCE_GENERIC_REMOTE_CONTROL = const(384) - -# Advertising frequency -ADV_INTERVAL_MS = 250_000 - -device_info = aioble.Service(_ROBOT) - -connection = None - -# Create characteristics for device info -aioble.Characteristic(device_info, bluetooth.UUID(MANUFACTURER_ID), read=True, initial="KevsRobotsRemote") -aioble.Characteristic(device_info, bluetooth.UUID(MODEL_NUMBER_ID), read=True, initial="1.0") -aioble.Characteristic(device_info, bluetooth.UUID(SERIAL_NUMBER_ID), read=True, initial=uid()) -aioble.Characteristic(device_info, bluetooth.UUID(HARDWARE_REVISION_ID), read=True, initial=sys.version) -aioble.Characteristic(device_info, bluetooth.UUID(BLE_VERSION_ID), read=True, initial="1.0") - -remote_service = aioble.Service(_GENERIC) - -button_characteristic = aioble.Characteristic( - remote_service, _BUTTON_UUID, read=True, notify=True -) - -print('registering services') -aioble.register_services(remote_service, device_info) - -connected = False - -async def remote_task(): - """ Send the event to the connected device """ - while True: - if not connected: - print('not connected') - await asyncio.sleep_ms(1000) - continue - - if (keyA.value() == 0): - button_characteristic.write(b"a") - button_characteristic.notify(connection, b"a") - - elif (keyB.value() == 0): - button_characteristic.write(b"b") - button_characteristic.notify(connection, b"b") - - elif (key2.value() == 0): - button_characteristic.write(b"u") - button_characteristic.notify(connection, b"u") - - elif (key3.value() == 0): - button_characteristic.write(b"c") - button_characteristic.notify(connection, b"c") - - elif (key4.value() == 0): - button_characteristic.write(b"l") - button_characteristic.notify(connection, b"l") - - elif (key5.value() == 0): - button_characteristic.write(b"d") - button_characteristic.notify(connection, b"d") - - elif (key6.value() == 0): - button_characteristic.write(b"r") - button_characteristic.notify(connection, b"r") - - else: - button_characteristic.notify(connection, b"!") - - # Show button pushed on LCD - if(keyA.value() == 0): -# LCD.fill_rect(208,12,20,20,LCD.red) - print("A") -# else : -# LCD.fill_rect(208,12,20,20,LCD.white) -# LCD.rect(208,12,20,20,LCD.red) - - if(keyB.value() == 0): - print("B") - else : - pass -# LCD.fill_rect(208,103,20,20,LCD.white) -# LCD.rect(208,103,20,20,LCD.red) - - if(key2.value() == 0): - # LCD.fill_rect(37,35,20,20,LCD.red) - print("UP") - else : - pass - # LCD.fill_rect(37,35,20,20,LCD.white) - # LCD.rect(37,35,20,20,LCD.red) - - if(key3.value() == 0): - # LCD.fill_rect(37,60,20,20,LCD.red) - print("CTRL") - else : - pass - # LCD.fill_rect(37,60,20,20,LCD.white) - # LCD.rect(37,60,20,20,LCD.red) - - if(key4.value() == 0): - # LCD.fill_rect(12,60,20,20,LCD.red) - print("LEFT") - else : - pass - # LCD.fill_rect(12,60,20,20,LCD.white) - # LCD.rect(12,60,20,20,LCD.red) - - if(key5.value() == 0): - # LCD.fill_rect(37,85,20,20,LCD.red) - print("DOWN") - else : - pass - # LCD.fill_rect(37,85,20,20,LCD.white) - # LCD.rect(37,85,20,20,LCD.red) - - if(key6.value() == 0): - # LCD.fill_rect(62,60,20,20,LCD.red) - print("RIGHT") - else : - pass - # LCD.fill_rect(62,60,20,20,LCD.white) - # LCD.rect(62,60,20,20,LCD.red) - - # LCD.show() - - await asyncio.sleep_ms(10) - - -# Serially wait for connections. -# Don't advertise while a central is connected -async def peripheral_task(): - print('peripheral task started') - global connected, connection - while True: - connected = False - async with await aioble.advertise( - ADV_INTERVAL_MS, - name="KevsRobots", - appearance=_BLE_APPEARANCE_GENERIC_REMOTE_CONTROL, - services=[_GENERIC] - ) as connection: - print("Connection from", connection.device) - connected = True - print(f"connected: {connected}") - await connection.disconnected(timeout_ms=None) - print(f'disconnected') - - -async def blink_task(): - print('blink task started') - toggle = True - while True: - led.value(toggle) - toggle = not toggle - blink = 1000 - if connected: - blink = 1000 - else: - blink = 250 - await asyncio.sleep_ms(blink) - -async def main(): - tasks = [ - asyncio.create_task(peripheral_task()), - asyncio.create_task(blink_task()), - asyncio.create_task(remote_task()), - ] - await asyncio.gather(*tasks) - - -asyncio.run(main()) \ No newline at end of file +asyncio.run(main(0)) \ No newline at end of file diff --git a/rgb.py b/rgb.py new file mode 100644 index 0000000..79d1fe8 --- /dev/null +++ b/rgb.py @@ -0,0 +1,69 @@ +import sys +import uasyncio +import machine +import uasyncio as asyncio +from machine import Pin, PWM + +led_r = PWM(Pin(22), 5000) +led_g = PWM(Pin(26), 5000) +led_b = PWM(Pin(27), 5000) + +rgb_pwr = 0.1 # 0.0 - 1.0 + + +async def init(): + led_r.duty_u16(0) + led_g.duty_u16(0) + led_b.duty_u16(0) + +async def set_pwr(pwr): + global rgb_pwr + rgb_pwr = pwr + + +async def set(r, g, b): + led_r.duty_u16(int(65535 * r * rgb_pwr)) + led_g.duty_u16(int(65535 * g * rgb_pwr)) + led_b.duty_u16(int(65535 * b * rgb_pwr)) + await uasyncio.sleep(0.01) + + + +async def on(): + led_r.duty_u16(65535 * rgb_pwr) # 65535 = on + led_b.duty_u16(65535 * rgb_pwr) # 65535 = on + led_g.duty_u16(65535 * rgb_pwr) # 65535 = on + +async def off(): + led_r.duty_u16(0) # 0 = off + led_g.duty_u16(0) # 0 = off + led_b.duty_u16(0) # 0 = off + +async def main(): + print("RGB demo") + print("Press Ctrl-C to exit") + print("RGB power:", rgb_pwr) + print("RGB initializing...") + await init() + while True: + print("RGB off") + await set(0, 0, 0) + await uasyncio.sleep(1) + print("Red on") + await set(1, 0, 0) + await uasyncio.sleep(1) + print("Green on") + await set(0, 1, 0) + await uasyncio.sleep(1) + print("Blue on") + await set(0, 0, 1) + await uasyncio.sleep(1) + print("RGB on") + await set(1, 1, 1) + await uasyncio.sleep(1) + +asyncio.run(main()) + + + +