Best way to access MicroPython over main serial port

My hardware does not have access to the secondary MicroPython serial port. Not something that can be changed at this point.

I want to have MicroPython code running on startup that sends telemetry data to the DRM. Similar to the drm_http_requests sample for the XBC.

This works well using PyCharm when I have direct access to the XBC-V1-UT-001 in the dev kit, but as soon as I do a power cycle I lose access to the serial port. The code is still running, I can see it in DRM, but it does not respond to ctrl-anything or +++ etc on the serial port. Had to put it back in the dev kit and do a recovery process to get it back.

From what I have read so far, seems like there are several ways to do this. Just want some idea of the dangers and advantages of each one so I can pick the best architectural design.

  1. Keep the serial port in Transparent mode and use ATFS commands to place the telemetry data in the file system, timestamp in the file name. Python code would just check for new files. JSON formatted status files. Control program would have to keep track of flash usage and purge old files.

  2. Run the whole system in REPL mode, no programs running at startup, use stdin and stdout for JSON formatted status messages and control. A lot more work in the control micro end.

  3. Run the whole process in REPL mode and simply launch a program with the telemetry data as an argument. The program would send the telemetry packet, log it and exit back into transparent mode. Don’t know if another program can be running concurrently that keeps in touch with DRM, allowing access to the file system and program updates, or if this is necessary. Seems like the DRM can access the file system regardless of other code that may be running. Don’t know if a power cycle will “kill” the REPL session and make the module inaccessible. Or does it just need a reset or DTR pin change to wake it up again? Maybe we have to go back to transparent mode before power cycle, but what about unanticipated power cyles?

  4. Cobble up a MicroPython MODBUS master app that works over a pretend RS485 that is really the main serial port. Probably a ridiculous idea but if someone has already done it…

  5. Configure RTS/CTS or DIO0 bits as GPIO and do a bit-bang I2C over those two bits. Super slow but that won’t matter, there is a new 300 byte telemetry packet every half hour on this system.

Please realize, again, I have no access to the secondary serial port. Whatever we do, it has to be done with DIN/DOUT and /RESET, /DTR/DIO8, /CTS/DIO7, on/Sleep (via transistor, can’t send to XBEE DIO9), AD0/DIO0. Pins 1,2,3,5,9,12,16,20.


I think your only option is to run it from a REPL interface.

Digi Support

1 Like

Thanks. Let me see if I understand how this would be done:
Develop the MicroPython code, maybe in PyCharm
Load into flash
Let it run on startup, set the AP mode to 4 (REPL)
Code sends serial requests using sys.stdout, external processor sends serial replies over REPL, code receives using sys.stdin
When I want to shut down, use an escape sequence +++ to get out of REPL and send AT commands to shut down. Or I could make a special serial command that instructs MicroPython code to shut down modem.

Close. Instead of shutting down the modem, maybe have Micro Python quit the application.

It’s odd that PyCharm caused those serial port problems. I wonder if it changed the baud rate and that’s why it appeared to be broken? If you had a connection to DRM, you could look at the serial port settings (ATBD, ATD6/ATD7 for flow control) to see if they’re what you expected.

If you run the XBee in API mode (ATAP=1), you can make use of the User Data Relay frame type (send 0x2D, receive 0xAD) to pass information between your MicroPython program and the host processor on the serial port, in whatever format you want (just as long as it’s wrapped in an API frame).

MicroPython code runs in the background, even when ATAP!=4.

You can compile your program to flash (CTRL-F), stored as main.mpy, and enable it to automatically run at startup by setting ATPS=1. You could write the bulk of your application into a separate module, and then have a main.mpy that wraps a function call to that code in a try/except block that logs errors and re-launches the application if it crashes.

So you’d have a program watching for User Data Relay frames coming in, and processing them as telemetry data to upload to DRM.

The basic XBee DRM handling (file system access, firmware updates) happens in the XBee firmware, regardless of what you’re doing in your MicroPython application.


And if your host processor is running C code, you can use this code library for API frame handling:

Thanks, TomCollins. Looks like the right approach.

What is DRM?

This is cool, sounds relevant to what I am trying to do as well… running a flashed MicroPython program at start-up, sending/receiving API packets between my Python project that runs the majority of the functionalities, GUI with buttons and whatnot… and the firmware."

My MicroPython upload will do 2 things on each of my remote xbee modules… 1.) at start up: send/ receive API packet reconfig instructions between the coordinator and itself, and 2.) sending input sensor change of state data in API packets to the Python program.

Anyways, whats DRM?

DRM - Digi Remote Manager.

Digi’s way of managing modules including cell contracts for LTE connected devices and data gathering, remote updates etc.

There is a monthly cost per unit but it comes out to not much more than what you would pay for a contract with RevX etc. Probably less than Azure or AWS at scale. And neither AWS nor nor Azure over-the-air updates work with Digi modules out-of-the-box. You can update the RF module part but not the user code. Of course you can roll your own update system, but with DRM it is built-in.

And note that the next Cellular release will include API frames to interface with the file system, and the C Host Library code will soon have support for those frames.