Closed b-blake closed 2 years ago
IR Relay and translate by B.B.Blake 10/10/2021
import board
import digitalio
from digitalio import DigitalInOut, Direction, Pull
import neopixel
import pulseio
import pwmio
import time
import microcontroller
#from microcontroller import pin
#test = pin.GPIO6
import adafruit_esp32spi
from adafruit_esp32spi import PWMOut
import adafruit_irremote
Pico = False
Itsy = False
bd = board.board_id
print("\f" + bd, end=" ")
if(bd == "adafruit_itsybitsy_rp2040"):
Itsy = True
if(bd == "raspberry_pi_pico"):
Pico = True
while(Pico == Itsy):
print("Board Not Supported.")
time.sleep(15)
pass
print("Board Supported.")
if(Pico == True):
IR_RX = board.GP2 # Pin connected to IR receiver.
time.sleep(0.1)
IR_PWR = board.GP1
IR_PWR = DigitalInOut(IR_PWR)
IR_PWR.direction = Direction.OUTPUT
IR_PWR.value = True
time.sleep(0.1)
IR_TX = board.GP26
#IR_TX = DigitalInOut(IR_TX)
#IR_TX.direction = Direction.OUTPUT
#IR_TX.value = True
time.sleep(0.1)
R_LED = DigitalInOut(board.GP6)
R_LED.direction = Direction.OUTPUT
B_LED = DigitalInOut(board.GP7)
B_LED.direction = Direction.OUTPUT
G_LED = DigitalInOut(board.GP8)
G_LED.direction = Direction.OUTPUT
LED = DigitalInOut(board.LED)
LED.direction = Direction.OUTPUT
time.sleep(0.1)
if(Itsy == True):
IR_RX = board.RX # Pin connected to IR receiver.
time.sleep(0.1)
IR_PWR = board.D5
IR_PWR = DigitalInOut(IR_PWR)
IR_PWR.direction = Direction.OUTPUT
IR_PWR.value = True
time.sleep(0.1)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
IR_TX = board.TX
#IR_TX = DigitalInOut(IR_TX)
#IR_TX.direction = Direction.OUTPUT
#IR_TX.value = True
time.sleep(0.1)
PIXEL_PIN1 = board.D7 # NeoPixel #1
PIXELS_NUM1 = 1 # NeoPixel #1
PIXEL_BRIGHT1 = 0.25 # NeoPixel #1
PIXEL_ORDER1 = neopixel.RGB # NeoPixel #1 (In, +5, Gnd, Out]-flat side to Right [RGB]
status_light1 = neopixel.NeoPixel(PIXEL_PIN1, PIXELS_NUM1, brightness=PIXEL_BRIGHT1, auto_write=True, pixel_order=PIXEL_ORDER1)
status_light1[0] = WHITE
LED = DigitalInOut(board.LED)
LED.direction = Direction.OUTPUT
NeoPix = DigitalInOut(board.NEOPIXEL)
NeoPix.direction = Direction.OUTPUT
time.sleep(0.1)
freq = 38000
duty = 32768
# Fuzzy pulse comparison function:
def fuzzy_pulse_compare(pulse1, pulse2, fuzzyness=0.2):
if(Pico): R_LED.value, G_LED.value, B_LED.value = False, False, False
if(Itsy): status_light1.fill(BLACK)
print(len(pulse1), len(pulse2))
if len(pulse1) != len(pulse2):
print("Pulse Lengths don't match.")
if(Pico): B_LED.value = True
if(Itsy): status_light1.fill(BLUE)
return False
for i in range(len(pulse1)):
threshold = (int(pulse1[i]) * fuzzyness)
if abs(pulse1[i] - pulse2[i]) > threshold:
print(abs(pulse1[i] - pulse2[i]), i)
if(Pico): R_LED.value = True
if(Itsy): status_light1.fill(RED)
return False
if(Pico): G_LED.value = True
if(Itsy): status_light1.fill(GREEN)
return True
# Expected pulse, pasted in from previous recording REPL session:
START1 = 9500
START2 = 4500
BEGIN = 562 # Begin Value header
ZERO = 562 # 562.5, 562.5,
ONE = 1687 # 562.5, 1687.5,
STOP = 562 # trail
SKIP30x = ([0xD0, 0x27, 0x30, 0x85])
SKIP30y = ([0xD0, 0x27, 0x30, 0x85])
SKIP30 = [9500, 4500, # Skip 30 0xD0273085
562, 1687, 562, 562, 562, 1687, 562, 562, 562, 562, 562, 562, 562, 562, 562, 1687, # 85
562, 562, 562, 562, 562, 562, 562, 562, 562, 1687, 562, 1687, 562, 562, 562, 562, # 30
562, 1687, 562, 1687, 562, 1687, 562, 562, 562, 562, 562, 1687, 562, 562, 562, 562, # 27
562, 562, 562, 562, 562, 562, 562, 562, 562, 1687, 562, 562, 562, 1687, 562, 1687, # D0
562]
INPUTx = ([0x40, 0xBF, 0xFB, 0x04])
INPUTy = ([0x40, 0xBF, 0xFB, 0x04])
INPUT = [9500, 4500, # Input 0x40BFFB04
562, 562, 562, 562, 562, 1687, 562, 562, 562, 562, 562, 562, 562, 562, 562, 562, # 04
562, 1687, 562, 1687, 562, 562, 562, 1687, 562, 1687, 562, 1687, 562, 1687, 562, 1687, # FB
562, 1687, 562, 1687, 562, 562, 562, 1687, 562, 562, 562, 562, 562, 562, 562, 562, # BF
562, 562, 562, 562, 562, 1687, 562, 562, 562, 1687, 562, 1687, 562, 1687, 562, 1687, # 40
562]
OKx = ([0xE3, 0x1C, 0xFF, 0x00])
OKy = ([0xE3, 0x1C, 0xFF, 0x00])
OK = [9500, 4500, # OK 0xE31CFFOO
562, 562, 562, 562, 562, 562, 562, 562, 562, 562, 562, 562, 562, 562, 562, 562, # 00
562, 1687, 562, 1687, 562, 1687, 562, 1687, 562, 1687, 562, 1687, 562, 1687, 562, 1687, # FF
562, 562, 562, 562, 562, 1687, 562, 1687, 562, 1687, 562, 562, 562, 562, 562, 562, # 1C
562, 1687, 562, 1687, 562, 562, 562, 562, 562, 562, 562, 1687, 562, 1687, 562, 1687, # E3
562]
# Create pulse INPUT and IR decoder.
pulses = pulseio.PulseIn(IR_RX, maxlen=200, idle_state=True)
#pulseout = pulseio.PulseOut(IR_TX, frequency=freq, duty_cycle=duty) Duplicate
decoder = adafruit_irremote.GenericDecode()
# Create a 'pwmio' OUTPUT, to send infrared signals on the IR transmitter @ 38KHz
pwm = pwmio.PWMOut(IR_TX, frequency=freq, duty_cycle=duty)
pulseout = pulseio.PulseOut(pwm)
# Create an encoder that will take numbers and turn them into NEC IR pulses
encoder = adafruit_irremote.GenericTransmit(header=[9500, 4500], zero=[562, 562], one=[562, 1687], trail=562, debug=False)
#encoder = adafruit_irremote.GenericTransmit((9500, 4500), (562, 1687), (562, 562), 562)
print("#"*80)
#detected = encoder.transmit(pulseout, OK)
#Send_IR_Code(OK)
ion = False
while ion:
time.sleep(0.3)
pulses.clear()
time.sleep(0.4)
pulses.resume()
time.sleep(0.3)
pulse1 = decoder.read_pulses(pulses)
print("IR Code Received")
print(len(pulse1))
print(pulse1)
print("#"*80)
while not ion:
time.sleep(0.3)
pulses.clear()
time.sleep(0.4)
pulses.resume()
time.sleep(0.3)
# Loop waiting to receive pulses.
while True:
print('IR listener started...')
# Wait for an IR Code to be detected.
detected = decoder.read_pulses(pulses)
time.sleep(.001)
# print(detected)
print('got an IR Code...')
# Got an IR Code, now compare.
if fuzzy_pulse_compare(INPUT, detected, 0.5):
LED.value = True
print('Received correct INPUT remote control press!')
for xx in range(7):
print(7-xx, end=" ")
Kz = [0,0,0,0]
SKIP30y = ([0xD0, 0x27, 0x30, 0x85])
Ky = SKIP30y
# print(Ky)
for y in range(8): # Reverse the bits, Not sure why.
for x in range(4):
Bit = (Ky[x] & 1)
# print(Bit, end="")
Ky[x] = (Ky[x] >> 1)
Kz[3-x] = ((Kz[3-x] << 1) + Bit)
# print(" ", end="")
IR_Command = (Kz)
encoder.transmit(pulseout, IR_Command, nbits=32)
time.sleep(0.5)
LED.value = False
print("")
pulses.clear()
time.sleep(0.4)
pulses.resume()
time.sleep(0.5)
elif fuzzy_pulse_compare(OK, detected, 0.5):
print('Received correct OK remote control press!')
elif fuzzy_pulse_compare(SKIP30, detected, 0.5):
print('Received correct SKIP30 remote control press!')
print("#"*80)
'''
>>> import board
>>> dir(board)
['__class__', '__name__', 'A0', 'A1', 'A2', 'A3',
'GP0', 'GP1', 'GP2', 'GP3', 'GP4', 'GP5', 'GP6', 'GP7', 'GP8', 'GP9',
'GP10', 'GP11', 'GP12', 'GP13', 'GP14', 'GP15', 'GP16', 'GP17', 'GP18', 'GP19',
'GP20', 'GP21', 'GP22', 'GP23', 'GP24', 'GP25',
'GP26', 'GP26_A0', 'GP27', 'GP27_A1', 'GP28', 'GP28_A2',
'LED', 'SMPS_MODE', 'VBUS_SENSE', 'VOLTAGE_MONITOR', 'board_id']
>>>
>>> import supervisor
>>> dir(supervisor)
['__class__', '__name__', 'RunReason', 'disable_autoreload', 'enable_autoreload',
'disable_ble_workflow', 'get_previous_traceback', 'reload', 'runtime',
'set_next_code_file', 'set_next_stack_limit', 'set_rgb_status_brightness', 'ticks_ms']
>>>
>>> import microcontroller
>>> dir(microcontroller)
['__class__', '__name__', 'Pin', 'Processor', 'ResetReason', 'RunMode',
'cpu', 'cpus', 'delay_us', 'disable_interrupts', 'enable_interrupts',
'nvm', 'on_next_reset', 'pin', 'reset', 'watchdog']
>>>
>>> import microcontroller
>>> dir(microcontroller.pin)
['__class__', 'GPIO0', 'GPIO1', 'GPIO2', 'GPIO3', 'GPIO4', 'GPIO5', 'GPIO6', 'GPIO7', 'GPIO8', 'GPIO9',
'GPIO10', 'GPIO11', 'GPIO12', 'GPIO13', 'GPIO14', 'GPIO15', 'GPIO16', 'GPIO17', 'GPIO18', 'GPIO19',
'GPIO20', 'GPIO21', 'GPIO22', 'GPIO23', 'GPIO24', 'GPIO25', 'GPIO26', 'GPIO27', 'GPIO28', 'GPIO29']
>>>
>>> help("modules")
__main__ bitops math sdcardio
_bleio board microcontroller sharpdisplay
adafruit_bus_device builtins micropython storage
adafruit_pixelbuf busio msgpack struct
aesio collections neopixel_write supervisor
alarm countio onewireio synthio
analogio digitalio os sys
array displayio pulseio terminalio
atexit errno pwmio time
audiobusio fontio qrio touchio
audiocore framebufferio rainbowio traceback
audiomixer gc random ulab
audiomp3 getpass re usb_cdc
audiopwmio imagecapture rgbmatrix usb_hid
binascii io rotaryio usb_midi
bitbangio json rp2pio vectorio
bitmaptools keypad rtc watchdog
Plus any modules on the filesystem
>>>
Looks like you have a boot.py
file. Please attach its content in case it is relevant.
Jepler,
Below is my boot.py file. The result is not used. The pin to determine what action to take is changed board to board to avoid conflict. I get the same results when I remove boot.py. Pin A3 is unused on the ItsyBitsy.
###########################################
"""CircuitPython Essentials Storage logging boot.py file"""
import board
from digitalio import DigitalInOut, Direction, Pull
import storage
# For Feather M0/M4 Express, RPi Pico, etc.
switch = DigitalInOut(board.A3)
switch.direction = Direction.INPUT
switch.pull = Pull.UP
# If the switch pin is connected to ground CircuitPython can write to the root drive
storage.remount("/", switch.value)
print("\tWrite to Flash :", (not switch.value))
print("\tWrite to SD Card:", switch.value)
print("\tboot.py Finis")
###########################################
The code has evolved. below is the code as it stands now. Also the symptoms have changed on the ItsyBitsy only. If "import microcontroller" ((Line 13)) is not commented out the device crashes after 4 codes are transmitted ((Line 245)). No error codes given on REPL. A hard reset is required. There was an issue between .mpy and .py library files but that went away for no good reason.
((Problem with .py library files. Replaced with .mpy files. Things OK. Test again with .py, problem gone.))
##
## IR Relay and translate by B.B.Blake 10/10/2021
##
#################### Import entrincic libraries ####################
import array
import board
import digitalio
from digitalio import DigitalInOut, Direction, Pull
import neopixel
import pulseio
import pwmio
import time
##import microcontroller # I don't know why we need it, but we do.
#################### Import extrincic libraries ####################
import adafruit_esp32spi
from adafruit_esp32spi import PWMOut
import adafruit_irremote
#################### Figure out what board we have ####################
Pico, Itsy, QTPy, Fthr, ANRC = False, False, False, False, False
bd = board.board_id # Ask the AdaFruit OS what board we are using
print("\f" + bd, end=" - ")
if (bd == "raspberry_pi_pico"): Pico = True
elif(bd == "adafruit_itsybitsy_rp2040"): Itsy = True
elif(bd == "adafruit_qtpy_rp2040"): QTPy = True
elif(bd == "adafruit_feather_rp2040"): Fthr = True
elif(bd == "arduino_nano_rp2040_connect_rp2040"): ANRC = True
else:
while(True):
print("Board Not Supported.")
time.sleep(15)
pass
print("Board Supported.")
#################### Set some variables and constants ####################
freq = 38000 # IR Tone Frequency
duty = 32768 # IR Tone Duty Cycle, aka 50%
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
CYAN = (0,255,255)
MAGENTA = (255,0,255)
YELLOW = (255,255,0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
AdaFruit = False
## IR Codes from TiVo IR transmitter, the Peanut
SKIP30 = [0xD0, 0x27, 0x30, 0x85] # SKIP30 - TiVo
INPUT = [0xF4, 0x0B, 0xFB, 0x04] # INPUT - RCA Source Select
## IR Codes from eBay IR transmitter
Skip_1 = [0xBA, 0x45, 0xFF, 0x00]
Skip_2 = [0xB9, 0x46, 0xFF, 0x00]
Skip_3 = [0xB8, 0x47, 0xFF, 0x00]
Skip_4 = [0xBB, 0x44, 0xFF, 0x00]
Skip_5 = [0xBF, 0x40, 0xFF, 0x00]
Skip_6 = [0xBC, 0x43, 0xFF, 0x00]
Skip_7 = [0xF8, 0x07, 0xFF, 0x00]
Skip_8 = [0xEA, 0x15, 0xFF, 0x00]
Skip_9 = [0xF6, 0x09, 0xFF, 0x00]
Skip_10 = [0xE6, 0x19, 0xFF, 0x00]
OK = [0xE3, 0x1C, 0xFF, 0x00]
## IR Codes from AdaFruit IR transmitter
if(AdaFruit):
Skip_1 = [0xEF, 0x10, 0xBF, 0x00]
Skip_2 = [0xEE, 0x11, 0xBF, 0x00]
Skip_3 = [0xED, 0x12, 0xBF, 0x00]
Skip_4 = [0xEB, 0x14, 0xBF, 0x00]
Skip_5 = [0xEA, 0x15, 0xBF, 0x00]
Skip_6 = [0xE9, 0x16, 0xBF, 0x00]
Skip_7 = [0xE7, 0x18, 0xBF, 0x00]
Skip_8 = [0xE6, 0x19, 0xBF, 0x00]
Skip_9 = [0xE5, 0x1A, 0xBF, 0x00]
Skip_10 = [0xF3, 0x0C, 0xBF, 0x00]
OK = [0xF6, 0x09, 0xBF, 0x00] # aka ENTER/SAVE
#################### Configure things based on the board found ####################
if(Pico == True):
IR_TX = board.GP26
IR_RX = board.GP2
IR_PWR = board.GP1 # Draw power for the CHQ1838 form GPIO pin 1
IR_PWR = DigitalInOut(IR_PWR)
IR_PWR.direction = Direction.OUTPUT
IR_PWR.value = True
R_LED = DigitalInOut(board.GP6)
R_LED.direction = Direction.OUTPUT
B_LED = DigitalInOut(board.GP7)
B_LED.direction = Direction.OUTPUT
G_LED = DigitalInOut(board.GP8)
G_LED.direction = Direction.OUTPUT
R_LED.value, B_LED.value, G_LED.value = True, True, True
time.sleep(0.5)
R_LED.value, B_LED.value, G_LED.value = False, True, False
if(Itsy == True):
IR_TX = board.TX
IR_RX = board.RX # Pin connected to IR receiver.
IR_PWR = board.D5
IR_PWR = DigitalInOut(IR_PWR)
IR_PWR.direction = Direction.OUTPUT
IR_PWR.value = True
PIXEL_PIN0 = board.NEOPIXEL # NeoPixel #0
PIXELS_NUM0 = 1 # NeoPixel #0
PIXEL_BRIGHT0 = 0.25 # NeoPixel #0
PIXEL_ORDER0 = neopixel.GRB # NeoPixel #0
status_light0 = neopixel.NeoPixel(PIXEL_PIN0, PIXELS_NUM0, brightness=PIXEL_BRIGHT0, auto_write=True, pixel_order=PIXEL_ORDER0)
status_light0[0] = WHITE
PIXEL_PIN1 = board.D7 # NeoPixel #1
PIXELS_NUM1 = 1 # NeoPixel #1
PIXEL_BRIGHT1 = 0.25 # NeoPixel #1
PIXEL_ORDER1 = neopixel.RGB # NeoPixel #1 (In, +5, Gnd, Out]-flat side to Right [RGB]
status_light1 = neopixel.NeoPixel(PIXEL_PIN1, PIXELS_NUM1, brightness=PIXEL_BRIGHT1, auto_write=True, pixel_order=PIXEL_ORDER1)
status_light1[0] = WHITE
time.sleep(0.5)
status_light0[0] = BLUE
status_light1[0] = BLUE
if(QTPy):
IR_TX = board.TX
IR_RX = board.RX
PIXEL_PIN0 = board.NEOPIXEL # NeoPixel #0
PIXELS_NUM0 = 1 # NeoPixel #0
PIXEL_BRIGHT0 = 0.25 # NeoPixel #0
PIXEL_ORDER0 = neopixel.GRB # NeoPixel #0
status_light0 = neopixel.NeoPixel(PIXEL_PIN0, PIXELS_NUM0, brightness=PIXEL_BRIGHT0, auto_write=True, pixel_order=PIXEL_ORDER0)
status_light0[0] = WHITE
time.sleep(0.5)
status_light0[0] = BLUE
if(Fthr):
IR_TX = board.TX
IR_RX = board.RX
PIXEL_PIN0 = board.NEOPIXEL # NeoPixel #0
PIXELS_NUM0 = 1 # NeoPixel #0
PIXEL_BRIGHT0 = 0.25 # NeoPixel #0
PIXEL_ORDER0 = neopixel.GRB # NeoPixel #0
status_light0 = neopixel.NeoPixel(PIXEL_PIN0, PIXELS_NUM0, brightness=PIXEL_BRIGHT0, auto_write=True, pixel_order=PIXEL_ORDER0)
status_light0[0] = WHITE
time.sleep(0.5)
status_light0[0] = BLUE
if not QTPy: LED = DigitalInOut(board.LED)
if not QTPy: LED.direction = Direction.OUTPUT
#################### Create IR encoder and decoder ####################
# Create pulse INPUT and IR decoder.
pulses = pulseio.PulseIn(IR_RX, maxlen=200, idle_state=True)
#pulseout = pulseio.PulseOut(IR_TX, frequency=freq, duty_cycle=duty) Duplicate
decoder = adafruit_irremote.GenericDecode()
## Create a 'pwmio' OUTPUT, to send infrared signals on the IR transmitter @ 38KHz
pwm = pwmio.PWMOut(IR_TX, frequency=freq, duty_cycle=duty)
pulseout = pulseio.PulseOut(pwm)
## Create an encoder that will take numbers and turn them into NEC IR pulses
encoder = adafruit_irremote.GenericTransmit(header=[9500, 4500], zero=[562, 562], one=[562, 1687], trail=562, debug=False)
##encoder = adafruit_irremote.GenericTransmit((9500, 4500), (562, 1687), (562, 562), 562)
print("#"*80)
#################### Function Definitions ####################
## Fuzzy pulse comparison function:
def fuzzy_pulse_compare(pulse1, pulse2, fuzzyness=0.2):
if(Pico): R_LED.value, G_LED.value, B_LED.value = False, False, False
if(Itsy): status_light0.fill(BLACK)
if(Itsy): status_light1.fill(BLACK)
if(QTPy): status_light0.fill(BLACK)
## print(len(pulse1), len(pulse2))
if len(pulse1) != len(pulse2):
## print("Pulse Lengths don't match.")
if(Pico): B_LED.value = True
if(Itsy): status_light0.fill(BLUE)
if(Itsy): status_light1.fill(BLUE)
if(QTPy): status_light0.fill(BLUE)
return False
for i in range(len(pulse1)):
threshold = (int(pulse1[i]) * fuzzyness)
if abs(pulse1[i] - pulse2[i]) > threshold:
## print(abs(pulse1[i] - pulse2[i]), i)
if(Pico): R_LED.value = True
if(Itsy): status_light0.fill(RED)
if(Itsy): status_light1.fill(RED)
if(QTPy): status_light0.fill(RED)
return False
if(Pico): G_LED.value = True
if(Itsy): status_light0.fill(GREEN)
if(Itsy): status_light1.fill(GREEN)
if(QTPy): status_light0.fill(GREEN)
return True
def make_fingerprint(datain, nbits=32, debug=False):
datax = datain.copy()
header=[9500, 4500]
zero=[562, 562]
one=[562, 1687]
trail=562
bits_to_send = len(datax) * 8
if nbits is not None and nbits < bits_to_send:
bits_to_send = nbits
durations = array.array("H", [0] * (2 + bits_to_send * 2 + (0 if trail is None else 1)))
durations[0] = header[0]
durations[1] = header[1]
if trail is not None:
durations[-1] = trail
out = 2
bit_count = 0
for byte_index, _ in enumerate(datax):
byte_count = byte_index # bbb
for j in range(byte_count, -1, -1): # bbb
for i in range(7, -1, -1): # bbb
bit = datax[j] & 1 # bbb
datax[j] = datax[j] >> 1 # bbb
if(bit): # bbb
durations[out] = one[0]
durations[out + 1] = one[1]
else:
durations[out] = zero[0]
durations[out + 1] = zero[1]
out += 2
bit_count += 1
if bit_count >= bits_to_send:
break
if debug:
print(durations)
return(durations)
def skip_loop(loops):
time.sleep(1)
if not QTPy: LED.value = True
for xx in range(loops):
print(loops-xx, end=" ")
## print( SKIP30 ) # [0xD0, 0x27, 0x30, 0x85] # SKIP30
## IR_Command = [0xD0, 0x27, 0x30, 0x85] # SKIP30
Ky = [0xD0, 0x27, 0x30, 0x85]
IR_Command = Ky.copy()
## print(SKIP30, IR_Command, Ky, 1)
encoder.transmit(pulseout, reverse_bits(IR_Command), nbits=32)
## print(SKIP30, IR_Command, Ky, 2)
time.sleep(0.5)
print("")
if not QTPy: LED.value = False
def reverse_bits(IN):
OUT = [0,0,0,0]
Ks = IN.copy()
for y in range(8): # Reverse the bits.
for x in range(4): # Bytes 1 thru 4
Bit = (Ks[x] & 1)
Ks[x] = (Ks[x] >> 1)
OUT[3-x] = ((OUT[3-x] << 1) + Bit)
return(OUT)
#################### Main program ####################
ion = False
while ion: # Just print what the IR receiver receives
time.sleep(0.3)
pulses.clear()
time.sleep(0.4)
pulses.resume()
time.sleep(0.3)
pulse1 = decoder.read_pulses(pulses)
print("IR Code Received")
print(len(pulse1))
print(pulse1)
print("#"*80)
while not ion: # Perform actions depending what the IR receiver receives
## Loop waiting to receive pulses.
while True:
if(AdaFruit): IR_ = 'AdaFruit'
else: IR_ = 'eBay'
time.sleep(0.1)
pulses.clear()
time.sleep(0.1)
pulses.resume()
time.sleep(0.1)
print('IR listener started...')
# Wait for an IR Code to be detected.
detected = decoder.read_pulses(pulses)
## print(detected)
print('got an IR Code...')
# Got an IR Code, now compare.
if fuzzy_pulse_compare(make_fingerprint(INPUT), detected, 0.5):
print('Received correct INPUT TiVo/RCA remote control press!')
print('Send Command to turn off the Source Select menu on the TV screen.')
time.sleep(0.5)
IR_Command = [0xF4, 0x0B, 0xFB, 0x04] # INPUT - Clear TV Screen
encoder.transmit(pulseout, reverse_bits(IR_Command), nbits=32)
skip_loop(7)
elif fuzzy_pulse_compare(make_fingerprint(OK), detected, 0.5):
print('Received correct OK '+IR_+' remote control press!')
pass
elif fuzzy_pulse_compare(make_fingerprint(SKIP30), detected, 0.5):
print('Received correct SKIP30 TiVo remote control press!')
pass
elif(fuzzy_pulse_compare(make_fingerprint(Skip_1), detected, 0.5)):
print('Received Skip_1 '+IR_+' remote control press!')
skip_loop(1)
elif(fuzzy_pulse_compare(make_fingerprint(Skip_2), detected, 0.5)):
print('Received Skip_2 '+IR_+' remote control press!')
skip_loop(2)
elif(fuzzy_pulse_compare(make_fingerprint(Skip_3), detected, 0.5)):
print('Received Skip_3 '+IR_+' remote control press!')
skip_loop(3)
elif(fuzzy_pulse_compare(make_fingerprint(Skip_4), detected, 0.5)):
print('Received Skip_4 '+IR_+' remote control press!')
skip_loop(4)
elif(fuzzy_pulse_compare(make_fingerprint(Skip_5), detected, 0.5)):
print('Received Skip_5 '+IR_+' remote control press!')
skip_loop(5)
elif(fuzzy_pulse_compare(make_fingerprint(Skip_6), detected, 0.5)):
print('Received Skip_6 '+IR_+' remote control press!')
skip_loop(6)
elif(fuzzy_pulse_compare(make_fingerprint(Skip_7), detected, 0.5)):
print('Received Skip_7 '+IR_+' remote control press!')
skip_loop(7)
elif(fuzzy_pulse_compare(make_fingerprint(Skip_8), detected, 0.5)):
print('Received Skip_8 '+IR_+' remote control press!')
skip_loop(8)
elif(fuzzy_pulse_compare(make_fingerprint(Skip_9), detected, 0.5)):
print('Received Skip_9 '+IR_+' remote control press!')
skip_loop(9)
elif(fuzzy_pulse_compare(make_fingerprint(Skip_10), detected, 0.5)):
print('Received Skip_10 '+IR_+' remote control press!')
skip_loop(10)
else:
print(detected)
pass
if(Pico): G_LED.value = False
if(Itsy): status_light0.fill(BLACK)
if(Itsy): status_light1.fill(BLACK)
if(QTPy): status_light0.fill(BLACK)
time.sleep(0.1)
pulses.clear()
time.sleep(0.1)
pulses.resume()
time.sleep(0.1)
print("#"*80)
When you say "crash", do you mean that it just hangs, as opposed to reseting into safe mode or throwing an exception?
Crash = No exception thrown, no safe mode, it stops responding to all REPL commands Ctrl-C, Ctrl-D, etc. After ~45 seconds it disconnects from my Windows 10 machine then I get an alert box with "USB device not recognized" when it tries to connect. Pushing RESET brings it back.
Bruce
With further experimentation...
It is not import microcontroller that alone is the issue. I added code, modified code, and removed code with no issue, no crashes.
Then I made a minor change and the crashes came back at a different place. It was after 4 SKIP30 sends, now it is after 10 SKIP30 sends. It can be 10 sends at one time or two of 5 sends. I stopped the crashes this time by adding import supervisor. supervisor is never called, but the crashes stopped.
I am starting to suspect complied object code size. Is there a way to find out if, where, and when the object code, variables, or lists fall on a memory boundary(s)?
Bruce
I don't think it is just size. There is memory corruption somewhere. You might leave all these imports in and turn off various parts of the program with if False:
etc.
Dan,
I have narrowed it down to this function call: print(SKIP30, IR_Command, Ky, 1) encoder.transmit(pulseout, reverse_bits(IR_Command), nbits=32) print(SKIP30, IR_Command, Ky, 2)
Encoder is defined much earlier by:
## Create an encoder that will take numbers and turn them into NEC IR pulses
encoder = adafruit_irremote.GenericTransmit(header=[9500, 4500], zero=[562, 562], one=[562, 1687], trail=562, debug=False)
I have no control over adafruit_irremote or the intrinsic functions it calls. I doubt they are part of the issue.
The code crashes after the first print call but before the second. Previously when it was crashing at 4 SKIP30 calls there was a bunch of diagnostic code and lots of crap coding. When I cleaned up a bunch of the crap code and diagnostic stuff, the issue went away. When I added in some code to make the program more flexible the crashes cam back. So size is a tell; as to what/where, I have no clue.
Your idea about memory corruption is interesting because the issue only happens in my ItsyBitsy RP2040. It does not raise its ugly head on my QT Py RP2040, Feather RP2040, or Raspberry Pi Pico. I started development on the RPi Pico but wanted to make it portable to the other RP2040 platforms. (Don't tell anybody, but the AdaFruit platforms are better in several ways.) There was also an issue of bad algorithm execution on the ItsyBitsy that went away for no discernable reason. Not working with .py library. Working with .mpy library. *Working with .py library. Trying to isolate to an .py library issue didn't work. Both started working. So much for that idea.
Bruce
There have been changes in the native PulseOut
code recently. I suspect that some memory or timing problem may be coming from that. @DavePutz and @tannewt may be interested in this bug.
I have not been able to reproduce this on my RP2040 ItsyBitsy running CP 7.0.0. Can I ask you to add an import of the gc module and then put a 'print ("Mem Free: ", gc.mem_free())' right before the encoder.transmit line? This will show us if we're running low on memory as a possible cause. Thanks!
Dave,
Here ya go. Crash after 4 IR commands sent. No joy in Mudville.
IR listener started... got an IR Code... Received Skip_10 eBay remote control press! 10 Mem Free: 174944 9 Mem Free: 174256 8 Mem Free: 173568 7 Mem Free: 172880
Dave,
GC Supervisor
OFF OFF = Crash @ 4 sends
ON ON = OK
Insert print mem statement
OFF ON = Crash @ 7
On OFF = Crash @ 4
Print mem commented out
OFF OFF = OK
Delete print statement
OFF OFF = OK
Delete import gc, Import supervisor commented out
OFF OFF = OK
Remove # from import supervisor
compile error - - - - 7 good loops then throw error code. No crash this time.
Received Skip_10 eBay remote control press!
10 9 8 7 6 5 4 Traceback (most recent call last):
File "code.py", line 381, in <module>
File "code.py", line 287, in skip_loop
File "adafruit_irremote.py", line 377, in transmit
TypeError: can't convert NoneType to int
This is line 381
skip_loop(10)
This is skip_loop(foo)
def skip_loop(loops):
time.sleep(1)
for xx in range(loops):
if not QTPy: LED.value = True
print(loops-xx, end=" ")
IR_Command = SKIP30.copy()
### print(SKIP30, IR_Command, 1)
encoder.transmit(pulseout, reverse_bits(IR_Command), nbits=32)
### print(SKIP30, IR_Command, 2)
if not QTPy: LED.value = False
time.sleep(0.5)
print("")
[ @b-blake you can put code or output in triple back-ticks (or single if it's one line). I have been editing your posts a bit to do that. You can use the "< >" button in the post editor. Select what needs to be shown as code or output and then click the button. ]
Dave, Dan,
Thank you.
Bruce
Well, that's clear evidence that memory is getting stepped on. Line 377 in adafruit_irremote.mpy is
durations[out] = self.one[0]
in the transmit function. The 'out' variable is a simple integer, so something has corrupted where it
is stored. I will continue to attempt to reproduce the issue. May I ask what hardware you are using for
the IR receiver and transmitter (in case that may be having some impact here).
Dave,
The Line 377 error drop is the first real clue I saw. Previously all I got was a crash. If you can't reproduce my symptoms, I have .zip file with ALL that is on the ItsyBitsy. It is 980MB so quite big. If I remove the lib subdirectory it drops in size considerably. The library DTG is 10/2/2021 @ 12:59 PM. I agree the IR parts should not have an effect, but . . .
IR (Infrared) Receiver Sensor - TSOP38238 PRODUCT ID: 157 Pin #1 goes to the RX pin on the ItsyBitsy. Ground to the center pin #2. +5 Vcc/USB to pin #3 of the IR receiver
Super-bright 5mm IR LED - 940nm PRODUCT ID: 387 The TX LEDs are driven by a 2N3904 NPN transistor with 5.1k Ohm resistor from Base to the TX pin on the ItsyBitsy. Emitter to Ground. Collector to a 57 Ohm resistor to a pair of IR LEDs in series to +5 Vcc/USB.
If you toggle the AdaFruit variable to True, this remote's IR codes will be understood by the program. Mini Remote Control PRODUCT ID: 389
Bruce
Bruce,
Just curious; is there a reason you are using the esp32spi PWMOut instead of the RP2040 PWMOut that is part of pwmio? I've tried both and saw no hangs with either; but I was wondering why you did things that way.
Dave
@DavePutz I think @b-blake is using the native pwmio.PWMOut
. These are the imports:
import pwmio
from adafruit_esp32spi import PWMOut
and this is the sole use I see:
pwm = pwmio.PWMOut(IR_TX, frequency=freq, duty_cycle=duty)
@DavePutz Dave,
is there a reason you are using the esp32spi PWMOut instead of the RP2040 PWMOut that is part of pwmio?
Yes, a very sophisticated reason. It is what I copied off of the AdaFruit web site and github. If had stumbled on code that uses RP2040 PWMOut, that is what I would have used. How would I use it? P.S. I had to look up how to spell 'sophisticated' ;-)
@dhalbert Dan,
See above. No sophisticated reasons for what I do. My only class on programming was for FORTRAN back in 1966 and I just sat in on it while my girlfriend took the class. After that one class, I started playing with the IBM 1620 that was in the U of Wisconsin Space Astronomy Laboratory where I worked for $1.00/hour. FORGO, BASIC, QBASIC, Assembly on 3 platforms, Pearl, Python, and Circuit Python have all been self taught.
Bruce
@DavePutz Dave,
OK... I made the following change.
from pwmio import PWMOut
#from adafruit_esp32spi import PWMOut
What have I made better by doing this? Eliminating the need for adafruit_esp32spi is a plus, but is there more?
Bruce
With the above change I get the following on the second push of Skip 10;
Traceback (most recent call last):
File "code.py", line 345, in <module>
NameError: name 'OK' is not defined
The error goes away when I import supervisor.
Bruce
A reminder. It only happens on the ItsyBitsy. What is so unique with the ItsyBitsy? The errors/crashes do not happen on the Raspberry Pi Pico or the QT Py. To my mind the QT Py is no more than a folded ItsyBitsy.
The from adafruit_esp32spi import PWMOut
should be irrelevant, because the only use of PWMOut
is in pwmio.PWMOut
. If removing the from adafruit_esp32spi import PWMOut
affects the bug, then that points even more to some kind of memory problem, where random changes about what's in RAM cause problems at different places in the program.
ItsyBitsy vs Pi Pico vs QT Py also points to that. The ItsyBitsy has more definitions in board
, and some other slight differences. It is just an accident that we are seeing the problem on the Itsy and not the other boards. I would guess the boards may have memory corruption as well: the corruption is just affecting something else, which is less obvious.
@dhalbert Dan,
Removing the from adafruit_esp32spi import PWMOut does not affect the bug. Of all the people in all the world using CP 7.0.0, why only me? Is it that obscure?
Bruce
P.S. Dan, I am watching laundry wash, what is your excuse for not enjoying Saturday? Get a 6-pack of PBR or a bottle of T-Bird and sit by the lake and relive your teens. Take your SO with you and make bad decisions.
Dan,
where random changes about what's in RAM cause problems at different places in the program.
At one point I was getting wrong IR output with the .py library, but when I changed to the .mpy library the problem went a way.
Bruce
Guys,
With the latest change;
from pwmio import PWMOut
I now can get the Feather to crash.
Well, I've managed to re-create memory corruption using a Pico. Now the issue is hunting down the source of the problem.
Dave,
I wish you the best of luck. I am available for testing at any time. Being retired has its advantages.
Bruce
It looks like the issue can occur when an incoming pulse (even a stray IR signal) comes in while sending the pulseout. The following stack was captured:
#0 0x10040b4a in common_hal_pulseio_pulsein_interrupt (self=0x20009200) at common-hal/pulseio/PulseIn.c:148
#1 0x1003468a in rp2pio_statemachine_interrupt_handler () at common-hal/rp2pio/StateMachine.c:819
#2 <signal handler called>
#3 0x200025aa in supervisor_run_background_tasks_if_tick () at ../../supervisor/shared/tick.c:127
#4 0x10041164 in common_hal_pulseio_pulseout_send (self=self@entry=0x20009330, pulses=<optimized out>,
length=<optimized out>) at common-hal/pulseio/PulseOut.c:132
#5 0x1004ac6c in pulseio_pulseout_obj_send (self_in=0x20009330, pulses=0x2000f4f0)
at ../../shared-bindings/pulseio/PulseOut.c:151
Investigating how to handle this.
Bruce,
Are you able to pull and build this test patch? https://github.com/DavePutz/circuitpython.git, branch issue_5469.
If not we'll have to work out some other way to get you some test uf2s.
Dave
If not we'll have to work out some other way to get you some test uf2s.
You can zip the .uf2 and attach it to an issue comment.
Bruce,,
Attached is a zip file with uf2s for Pico, ItsyBitsy, and Feather. If you can test, let me know how it goes; thanks!
Dave, Dan,
I have not been able to cause a crash or memory violation on the three platforms that replacement *uf2 files were provided for. As I do not trust electronics, I will never say it is 100% fixed. I have been bit too many times ;-)
When will this change be posted to BROWSE S3?
Thank you both very much for all your help.
Bruce
Dave,
I am trying adafruit-circuitpython-arduino_nano_rp2040_connect-en_US-20211025-66e7dbe.uf2 on my Nano RP2040 Connect and the issue shows its ugly head. No add or subtract of libraries makes it work.
Am I using old code?
Bruce
Bruce,
As far as I know the Pull Request has not been merged, so there is
no build yet on circuitpython.org that includes it. You can follow the Pull Request (at https://github.com/adafruit/circuitpython/pull/5509 ) and after it is approved and merged it will be in the latest build(s). Hope this helps,
Dave
On Mon, Oct 25, 2021 at 2:45 PM b-blake @.***> wrote:
Dave,
I am trying adafruit-circuitpython-arduino_nano_rp2040_connect-en_US-20211025-66e7dbe.uf2 on my Nano RP2040 Connect and the issue shows its ugly head. No add or subtract of libraries makes it work.
Am I using old code?
Bruce
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/adafruit/circuitpython/issues/5469#issuecomment-951251014, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFNJKEVVOFTJVQR526W34HTUIWXUTANCNFSM5GCPYWTQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.
Fixed by #5509.
My Nano RP2040 Connect is happy now.
Thanks Dave and Dan.
Bruce
CircuitPython version
Code/REPL
Behavior
Crash without 'import microcontroller' even though not used. Runs just fine with 'import microcontroller'
Description
I built an application that would take in an RCA IR code of 'change input' and put out 7 'skip 30 seconds' TiVo IR codes. The application was working fine. I wanted to find out how to reference a pin that is not defined by CircuitPython but is on the RP2040. I used 'import microcontroller' to test how to define a pin using 'from microcontroller import pin' then 'test = pin.GPIO6'. It worked fine. I have commented out lines 2 and 3 of the test code. and things work fine. If I comment out the first test line (import microcontroller) the program crashes within the 'import adafruit_irremote' library after iteration #4 of 7 each time. microcontroller is not referenced in my code or in adafruit_irremote.py code. Below is my code that works/doesn't work minus the libraries. There are no error codes displayed on REPL. The only way out is a hard reset with the reset button or pulling power. Ctrl-C has no effect.
Additional information
No response