James, you are a wizard! I can follow the logic but there are gaps in my knowledge that I’ll expand on below.
I finally got my code kinda working, but its not fancy and seems VERY susceptible to timing issues and seems slow to react. For completeness, my rubbish code is below and I wont take it any further.
I have tried your code and it is MUCH more snappy in its operation and I like the error checking and trapping. I do have questions though, which I’ll continue with below my rubbish code!
import time
import machine
#print uart info
uart = machine.UART(1, 9600)
print(uart)
data = 1
def read_UART_Ultrasonic(data, timeout = 1.0):
ts = time.ticks_ms()
buf = bytearray(3)
idx = 0
time.sleep(0.1)
while True:
# Option 1, we time out while waiting to get valid data
if time.ticks_diff(time.ticks_ms(), ts) > timeout:
RuntimeError
c = uart.read(1)[0]
if idx == 0 and c == 0xFF:
buf[0] = c
idx = idx + 1
elif 0 < idx < 3:
buf[idx] = c
idx = idx + 1
else:
chksum = sum(buf) & 0xFF
if chksum == c:
return (buf[1] << 8) + buf[2]
idx = 0
return None
while True:
dist = read_UART_Ultrasonic(data)
print("Distance = %d mm" % dist)
Questions about your code to further my understanding:
Q1. I can see from the DFRobot datasheet that the RX pin can be driven high to provide a more steady / consistant measurement. This appears to be done on Pin 2 when avg_pin gets set to as 1, so Im wondering what is the purpose of the led line above the avg_pin line? Is it somewhow required to set the RX high?
led = machine.Pin("LED",machine.Pin.OUT)
Q2:
Using UART0 plays havoc with using the REPL in Thonny via USB (at least whilst coding & de-bugging). Using UART1 on Pins 6 & 7 resolves this issue, hence my question above re driving Pin 2 (UART0 RX) High. I think I can just change Pin 2 to 7 on the avg_pin line and then change the address of uart. So I would have the following to use UART1:
avg_pin = machine.Pin(7, machine.Pin.OUT, value=1) # tell sensor to average data in hardware by driving UART1 RX pin on sensor high
...
# Initialise UART1
uart = UART(1, 9600)
Q3: When cheksum is being defined, the array items in [0], [1], [2] are added togther, what does “& 0xFF” do? I know from the datasheet that 0xFF is the header, so does the checksum end up being some numeric value (the product of adding the 3 array numbers) and appending 0xFF to the end, eg 12340xFF ?
checksum = (data_buff[0] + data_buff[1] + data_buff[2]) & 0xFF
Q4: I understand what the below is doing, what I dont know is where “250”, (-1) and (-2) come from. Are these in a datasheet somewhere that Ive missed, or are (-1) and (-2) micropython error traps of some kind?
if measurement == 250:
return(-1) # return -1 if "250" (invalid measurement) is recieved, consider adding 0 too, as it's usually not accurate
else:
return(measurement)
else:
return(-2) # if checksum fails (normally because minimum range has been exceeded, return -1)
Q5: Finally, your commentry says consider adding 0 too, as its usually not accurate. What would this look like and where would it get added?
Once again, many thanks and sorry for all the questions! Being able to see the working code and then reach out to further my own knowledge is just amazing.
Jon