You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am trying to get two Raspberry Pi Pico W's to communicate. The Pico that transmits the data is hooked up to an accelerometer (MPU6050). As it takes the x, y, and z values from the accelerometer, it then attempts to send the data to the receiving Pico. The example code, temp_client.py and temp_sensor.py, was used as a baseline for my code. As for setup, I am using the IDE, Thonny, which is currently running MicroPython v1.22.2.
When I run the program, the two devices connect successfully, and the transmitter appears to successfully retrieve and send the data to the receiver. The problem I'm having is at the receiver end -- when I attempt to read the data using data = accel_char.read() , I get an error that says "TypeError: can't convert NoneType to int". I am unsure why this error is appearing, since it is written the exact way the examples have it (and I tested the example numerous times, along with using a MAX31855 breakout board to receive temperature data.) Here is the code for my receiver which I am having issues for.
importsys# ruff: noqa: E402sys.path.append("")
frommicropythonimportconstfrommachineimportRTCimportuasyncioasasyncioimportaiobleimportbluetoothimportrandomimportstruct# org.bluetooth.service.environmental_sensing_ENV_SENSE_UUID=bluetooth.UUID(0x181A)
# org.bluetooth.characteristic.temperature_ENV_SENSE_TEMP_UUID=bluetooth.UUID(0x2A6E)
# Experiment ID (arbitrary for now), for file nameExp_ID="Acc"+str(24)
# Row ID for fileglobalrowIDrowID=1# Initialize RTCrtc=machine.RTC()
# Write CSV headerdefstart_csv(timestamp):
globalaccelFileaccelFile=Exp_ID+'-'+timestamp+'.csv'withopen(accelFile, 'a') asf:
f.write("Row ID"+",")
f.write("X Accel")
f.write(",")
f.write("Y Accel")
f.write(",")
f.write("Z Accel")
f.write("\r\n")
# Get current time to attach to file namedefget_current_time():
current_time=rtc.datetime()
curr_year=current_time[0] # '2024' in 5/20/2024curr_month=current_time[1] # '5' in 5/20/2024curr_day=current_time[2] # '20' in 5/20/2024curr_hour=current_time[4] # '10' in '10:25:56'curr_min=current_time[5] # '25' in '10:25:56'curr_sec=current_time[6] # '56' in '10:25:56'# Convert to string to maintain double-digit format during transferyear='{:02d}'.format(curr_year)
month='{:02d}'.format(curr_month)
day='{:02d}'.format(curr_day)
hour='{:02d}'.format(curr_hour)
minute='{:02d}'.format(curr_min)
sec='{:02d}'.format(curr_sec)
returnyear, month, day, hour, minute, sec# Write to CSV filedefwrite2file(rowID:int, x_accel:int, y_accel:int, z_accel:int):
withopen(accelFile, 'a') asf:
f.write(str(rowID))
f.write(",")
f.write(str(x_accel))
f.write(",")
f.write(str(y_accel))
f.write(",")
f.write(str(z_accel))
f.write("\r\n")
rowID+=1# Scan for devices to connect to asyncdeffind_temp_sensor():
# Scan for 5 seconds, in active mode, with very low interval/window (to# maximise detection rate).asyncwithaioble.scan(5000, interval_us=30000, window_us=30000, active=True) asscanner:
asyncforresultinscanner:
# See if it matches our name and the environmental sensing service.ifresult.name() =="mpy-accel"and_ENV_SENSE_UUIDinresult.services():
# print(result.services())returnresult.devicereturnNone# Helper to decode the temperature characteristic encoding (sint16, hundredths of a degree).defdecode_data(data):
returnstruct.unpack("8s8s8s", data)
# Reconstruct packets, receive data and append current time to CSV entryasyncdefreceive_data(data):
recv_data=b''unpacked_data=Falserecv_data+=dataiflen(recv_data) >=24:
unpacked_data=Truedata=decode_data(recv_data[:24])
x, y, z=data[0], data[1], data[2]
decoded_x=x.decode('utf-8')
decoded_y=y.decode('utf-8')
decoded_z=z.decode('utf-8')
write2file(rowID, decoded_x, decoded_y, decoded_z)
print(f"rowID: {rowID}, X Accel: {decoded_x}, Y Accel: {decoded_y}, Z Accel: {decoded_z}") # Print received data to central outputrecv_data=b''# Reset the received data bufferasyncdefmain():
connected=Falsedevice=awaitfind_temp_sensor()
ifnotdevice:
print("Temperature sensor not found")
returntry:
connection=awaitdevice.connect()
print("Connecting to", device)
connected=Trueexceptasyncio.TimeoutError:
print("Timeout during connection")
returnasyncwithconnection:
try:
accel_service=awaitconnection.service(_ENV_SENSE_UUID)
print("Accel service: ", accel_service)
ifaccel_serviceisNone:
print("Environmental sensing service not found")
returnaccel_char=awaitaccel_service.characteristic(_ENV_SENSE_TEMP_UUID)
print("Accel characteristic: ", accel_char)
ifaccel_charisNone:
print("Characteristic not found")
return# await asyncio.sleep(1)exceptasyncio.TimeoutErrorase:
print("Error registering services/characteristics: ", e)
# Start CSV fileglobalaccelFileyear, month, day, hour, minute, sec=get_current_time()
timestamp=f"{year:04}_{month:02}_{day:02}_{hour:02}-{minute:02}-{sec:02}"start_csv(timestamp)
whileconnected:
data=b''whiledataisb'':
data=awaitaccel_char.read()
print(type(data))
print("Waiting until data is not None")
ifdataisNone:
print("No more data to receive.")
breakprint("Received data type: ", type(data))
print(data)
awaitreceive_data(data)
''' except Exception as e: print("Error receiving data: ", e) '''awaitasyncio.sleep_ms(1000)
print("Disconnected")
asyncio.run(main())
Receiver Output:
MPY: soft reboot
Connecting to Device(ADDR_PUBLIC, 28:cd:c1:0b:30:b9, CONNECTED)
Accel service: Service: 7 9 UUID(0x181a)
Accel characteristic: Characteristic: 11 9 10 UUID(0x2a6e)
<class 'bytes'>
Waiting until data is not None
Received data type: <class 'bytes'>
b''
Traceback (most recent call last):
File "", line 195, in
File "asyncio/core.py", line 1, in run
File "asyncio/core.py", line 1, in run_until_complete
File "asyncio/core.py", line 1, in run_until_complete
File "", line 173, in main
File "aioble/client.py", line 251, in read
TypeError: can't convert NoneType to int
The receiver initially does not receive any data (as marked by b''), but I figure this is due to a timing issue. To my understanding, this error should still not be happening despite this since the datatype of the received data is 'bytes.'
Any help would be greatly appreciated! I've been stuck on this problem for a couple weeks now and have not found a solution despite scrounging through numerous discussion posts and comparing my code to the original example code multiple times. I originally thought it was because the service and characteristic was not being registered properly, but I added a short delay to ensure that it is and the problem is still occurring. I've also added my transmitter code below just in case.
# BLE Transmitter: attached to accelerometer (MPU6050) and an external power supplyimportsys# ruff: noqa: E402sys.path.append("")
importmachineimportmicropythonfrommicropythonimportconstfrommachineimportPin# For MPU6050importtimeimportMPU6050# For BLEimportuasyncioasasyncioimportaiobleimportbluetoothimportstruct# org.bluetooth.service.environmental_sensing_ENV_SENSE_UUID=bluetooth.UUID(0x181A)
# org.bluetooth.characteristic.temperature_ENV_SENSE_TEMP_UUID=bluetooth.UUID(0x2A6E)
# org.bluetooth.characteristic.gap.appearance.xml_ADV_APPEARANCE_CYCLING_SPEED_SENSOR=const(1154)
# How frequently to send advertising beacons._ADV_INTERVAL_MS=250_000# Register GATT server.accel_service=aioble.Service(_ENV_SENSE_UUID)
accel_char=aioble.Characteristic(accel_service, _ENV_SENSE_TEMP_UUID, read=True, write=True)
aioble.register_services(accel_service)
# Set GPIO pinsstart_pin=machine.Pin(5, Pin.IN)
sda=machine.Pin(2)
scl=machine.Pin(3)
# Initialize I2C ([group I2C0 or I2C1], [sda pin], [scl pin], [frequency])i2c=machine.I2C(1, sda=sda, scl=scl, freq=400000)
# Setup readings (note: transmitter only needs to know duration, receiver will handle# time and writing/naming filedefsetup_readings():
# Set duration (how long are we measuring? (ms))duration=1000returnduration# Measure data from accelerometerasyncdefget_measuring():
setup=setup_readings()
duration=setup#print(f"Duration: {duration}")# Set up read period (how often accelerometer reads (sec))read_period=1# Set up measurement durationend_time=time.ticks_add(time.ticks_ms(), duration)
#print(f"End time: {end_time}")# Loop continuously to print datawhiletime.ticks_diff(end_time, time.ticks_ms()) >0:
# 'Accel' is tuple of 3 that contains x, y, andz dataaccel=mpu.read_accel_data()
x_accel=accel[0]
y_accel=accel[1]
z_accel=accel[2]
print("Accel data type: ", type(x_accel))
print("Accel X: "+str(x_accel))
print("Accel Y: "+str(y_accel))
print("Accel Z: "+str(z_accel))
encoded_data=encode_data(x_accel, y_accel, z_accel)
awaitsend_data(encoded_data)
time.sleep(read_period)
iftime.ticks_diff(end_time, time.ticks_ms()) <=0:
breakprint("Completed measuring for given duration")
return# Helper to encode the temperature characteristic encoding (sint16, hundredths of a degree).defencode_data(x_accel, y_accel, z_accel):
# Convert 'float' data to stringsstr_x=str(x_accel)
str_y=str(y_accel)
str_z=str(z_accel)
# Encode to bytes for transfer / data consistencyencode_x=str_x.encode('utf-8')
encode_y=str_y.encode('utf-8')
encode_z=str_z.encode('utf-8')
print("Encoded data type: ", type(encode_x))
''' print(len(encode_x)) print(len(encode_y)) print(len(encode_z)) '''returnstruct.pack("8s8s8s", encode_x, encode_y, encode_z)
# Break data into packets to sendasyncdefsend_data(data):
accel_char.write(data)
print("Data type of data: ", type(data))
# Scan for I2C devicesasyncdefscan_I2C():
print('Scanning I2C bus...')
devices=i2c.scan() # returns all viable I2C devices on busiflen(devices) ==0: # if devices list is length 0, report no devicesprint('No I2C device!')
else:
print('I2C devices found: ', len(devices))
fordeviceindevices: # Run loop for every device in list, print corresponding addressprint('Decimal address: ', device, ' | Hexa address: ', hex(device))
# Set up MPU6050 objectglobalmpumpu=MPU6050.MPU6050(i2c)
# Wake up MPU6050 in case it was sleepingmpu.wake()
# Serially wait for connections. Don't advertise while a central is# connected.asyncdefperipheral_task():
connected=FalsewhileTrue:
# Advertise deviceprint("Advertising device, waiting for connection...")
try:
asyncwithawaitaioble.advertise(
_ADV_INTERVAL_MS,
name="mpy-accel",
services=[_ENV_SENSE_UUID],
appearance=_ADV_APPEARANCE_CYCLING_SPEED_SENSOR,
) asconnection:
# Print connected deviceprint("Connection from ", connection.device)
connected=Trueawaitasyncio.sleep(1)
exceptExceptionase:
print("Error while advertising: ", e)
whileconnected:
# await asyncio.sleep(0.5)# Scan I2C devicesawaitscan_I2C()
# Retrieve measurements from accelerometer, pack and sendawaitget_measuring()
# Disconnect after measuring interval has finished# await connection.disconnect()print("Disconnected")
#returnasyncdefmain():
awaitperipheral_task()
asyncio.run(main())
Thank you!
The text was updated successfully, but these errors were encountered:
Personally I have always been frustrated with being able to tell what is in scope and what is not in scope in python/micropython.
accel_service and accel_char are both first defined in a try - except clause and then they are accessed later outside of that clause. Now in C and in Java, those variables would be out of scope once outside of the try clause.
Try something simple like placing them at the top of the file along with the connected = False (I type everything I can not only for my benefit but for a future reader of my code's benefit....
then check that they are not None before accessing them. Just because you are getting the error that what you are accessing is of NoneType suggests that they are out of scope. I recall being instructed that variables defined in a try clause should not go out of scope but that has not always been my experience.
In any case, if you have not found a solution this is an easy thing to try.
Hi all,
I am trying to get two Raspberry Pi Pico W's to communicate. The Pico that transmits the data is hooked up to an accelerometer (MPU6050). As it takes the x, y, and z values from the accelerometer, it then attempts to send the data to the receiving Pico. The example code, temp_client.py and temp_sensor.py, was used as a baseline for my code. As for setup, I am using the IDE, Thonny, which is currently running MicroPython v1.22.2.
When I run the program, the two devices connect successfully, and the transmitter appears to successfully retrieve and send the data to the receiver. The problem I'm having is at the receiver end -- when I attempt to read the data using
data = accel_char.read()
, I get an error that says "TypeError: can't convert NoneType to int". I am unsure why this error is appearing, since it is written the exact way the examples have it (and I tested the example numerous times, along with using a MAX31855 breakout board to receive temperature data.) Here is the code for my receiver which I am having issues for.Receiver Output:
MPY: soft reboot
Connecting to Device(ADDR_PUBLIC, 28:cd:c1:0b:30:b9, CONNECTED)
Accel service: Service: 7 9 UUID(0x181a)
Accel characteristic: Characteristic: 11 9 10 UUID(0x2a6e)
<class 'bytes'>
Waiting until data is not None
Received data type: <class 'bytes'>
b''
Traceback (most recent call last):
File "", line 195, in
File "asyncio/core.py", line 1, in run
File "asyncio/core.py", line 1, in run_until_complete
File "asyncio/core.py", line 1, in run_until_complete
File "", line 173, in main
File "aioble/client.py", line 251, in read
TypeError: can't convert NoneType to int
The receiver initially does not receive any data (as marked by b''), but I figure this is due to a timing issue. To my understanding, this error should still not be happening despite this since the datatype of the received data is 'bytes.'
Any help would be greatly appreciated! I've been stuck on this problem for a couple weeks now and have not found a solution despite scrounging through numerous discussion posts and comparing my code to the original example code multiple times. I originally thought it was because the service and characteristic was not being registered properly, but I added a short delay to ensure that it is and the problem is still occurring. I've also added my transmitter code below just in case.
Thank you!
The text was updated successfully, but these errors were encountered: