SIM7600 library for micropython #11649
-
Hi. I am using MicroPython on a RP2040 and have a SIM7600 board attached. I have an existing project which monitors some sensors and sets off a buzzer, etc if a sensor is out of range. The project uses asyncio. I would like to add sending and receiving SMS messages to this project. Is there a library available that will let me do that? Thank you! |
Beta Was this translation helpful? Give feedback.
Replies: 13 comments 18 replies
-
use AT commands via UART between rp2040 and module. All AT command you have in product description, so from RP side you have to |
Beta Was this translation helpful? Give feedback.
-
Hi... Thank you for the link and suggestion :-) I am using the class SIM_UART code as a class, and calling it from my main file async def sms_loop(): The first problem I face is I can't seem to find a link to the pyb library (from pyb import UART) - so instead I am using (from machine import UART, Pin) - and this is I think working - and this lets me define the Tx/Rx pins. I am using a RP2040 board. And secondly (and I am sure I am doing something quite wrong here) I need to send the AT command twice to send a SMS - and the format is not as I expected - but it does send a SMS :-) The first time I send res = await sim_uart.send_command('AT+CMGS="+6421123456"\rHello User\x1A') it does not send a SMS, and I see in the log (the ? in black here is actually a square box in the log...):
If I then run the exact same command a second time, I actually receive a SMS and see this in the log:
The SMS when received on my phone looks like this:
I guess I have the format here incorrect? How do I use the number, but only send the actual text message 'Hello User'? Thanks for any help! |
Beta Was this translation helpful? Give feedback.
-
The I have updated it to assume an RP2. The from machine import UART
import uasyncio as asyncio
from primitives import Delay_ms
class SIM_UART():
def __init__(self, timeout=4000):
self.uart = UART(0, 9600, rx=Pin(1, Pin.IN), tx=Pin(0, Pin.OUT))
self.timeout = timeout
self.swriter = asyncio.StreamWriter(self.uart, {})
self.sreader = asyncio.StreamReader(self.uart)
self.delay = Delay_ms()
self.response = []
asyncio.create_task(self.recv())
async def recv(self):
while True:
res = await self.sreader.readline()
self.response.append(res) # Append to list of lines
self.delay.trigger(self.timeout) # Got something, retrigger timer
async def send_command(self, command):
self.response = [] # Discard any pending messages
await self.swriter.awrite("{}\r\n".format(command))
print("<", command)
self.delay.trigger(self.timeout) # Re-initialise timer
await self.delay.wait() # Wait for 4s after last msg received
return b''.join(self.response)
async def test():
res = await sim_uart.send_command('rats')
if res:
print('Result is:' , res)
else:
print('Timed out waiting for result.')
sim_uart = SIM_UART()
try:
asyncio.run(test())
finally:
_ = asyncio.new_event_loop() |
Beta Was this translation helpful? Give feedback.
-
Hi Peter Thank you. Running your latest code - I needed to make two changes for the SIM7600 - baud rate 115200 and a timeout added to the same line, and I am sending: Unfortunately the same issue as previously. First time running no SMS is sent and I get: |
Beta Was this translation helpful? Give feedback.
-
Thank you @peterhinch @2dof (sorry about the formatting below! Trying to sort out) My problem now is although it correctly sends a SMS, it crashes with the error below. I think an issue in async def recv(self) ?
|
Beta Was this translation helpful? Give feedback.
-
Hi Peter |
Beta Was this translation helpful? Give feedback.
-
@andypnz I'm not clear what you're seeing. With my suggested value of 1,000,000 the timeout should be 1,000s or about 16.6 minutes. Please let me know how long it actually takes to fail. FYI I raised #10867 in February as UART timeouts keep causing |
Beta Was this translation helpful? Give feedback.
-
@peterhinch With the 1,000,000 timeout, it delays the 'Timed out waiting for result.' and 'Task exception wasn't retrieved' errors by maybe 10 seconds. With the 1,000,000 timeout, and my code changed to send 2 x SMS's:
|
Beta Was this translation helpful? Give feedback.
-
Taking a step backwards - it I only send 'AT' as the command, this is the result. Each command returns a result, but with errors between - except the first which returns with no error.
|
Beta Was this translation helpful? Give feedback.
-
Sadly the Pico UART isn't working properly, and is timing out far too early. This can be proved by pasting the following (link pins 0 and 1): from machine import UART, Pin
uart = UART(0, 115200, rx=Pin(1, Pin.IN), tx=Pin(0, Pin.OUT), timeout=1000_000, timeout_char=1000_000)
uart.readline() Times out after 15s rather than 16.6mins. I have raised an issue #11678. |
Beta Was this translation helpful? Give feedback.
-
It seems that the timeout variable is 16 bit in each and every port I looked into. So the largest reasonable value is 65535 at the moment. |
Beta Was this translation helpful? Give feedback.
-
@peterhinch Peter - Do you think you would have time to try and solve this for the community if I sent you a SIM7600 (to keep)? I don't have the skills here, and I do think this would be a useful library to have (and be working with uasyncio)? |
Beta Was this translation helpful? Give feedback.
-
One thing you could try is to amend the async def send_command(self, command):
res = b""
uns = b""
async with self.lock: # Don't allow concurrent messages
# Collect and print any unsolicited messages
done = False
while not done:
try:
r = await asyncio.wait_for(self.sreader.readline(), 1)
uns = b"".join((uns, r))
except asyncio.TimeoutError:
done = True # No more data from device
if uns:
print(f"Unsolicited: {uns}")
# UART buffer is now empty: send the command and await the response
await self.swriter.awrite(f"{command}\r\n")
done = False
while not done:
try:
r = await asyncio.wait_for(self.sreader.readline(), 4)
self.delay.trigger()
res = b"".join((res, r))
except asyncio.TimeoutError:
done = True # No more data from device
return res This will report any unsolicited messages or responses to the prior message that occurred after the 4s timeout had elapsed. |
Beta Was this translation helpful? Give feedback.
Thanks for the offer but I'm not in a position to take this on as a project, but I will help with the
uasyncio
and UART code. You'll need to research the AT codes.The following makes use of the timeout feature which is new to
uasyncio
V3. I have tested it with a loopback. It solves the UART timeout problem by periodically (40 sec intervals) sending "AT" to the modem. As I understand it, this will cause it to respond and will keep the UART receiver alive. Thesend_command
method waits 4s to gather any response from the modem.