Skip to content

Add SIM800L GSM/GPRS cellular driver#49

Open
floitsch wants to merge 1 commit intomainfrom
floitsch/sim800l
Open

Add SIM800L GSM/GPRS cellular driver#49
floitsch wants to merge 1 commit intomainfrom
floitsch/sim800l

Conversation

@floitsch
Copy link
Member

Add support for the SIMCom SIM800L 2G module, following the existing driver architecture (Quectel, Sequans, u-blox).

Key implementation details:

  • GSM/GPRS only: uses +CGREG instead of +CEREG for registration
  • SIMCom TCP/IP stack: AT+CSTT/CIICR/CIFSR for GPRS bearer, AT+CIPSTART/CIPSEND/CIPRXGET for sockets
  • Manual data receive mode (AT+CIPRXGET=1) for clean AT parsing
  • Async DNS via AT+CDNSGIP
  • Multi-connection mode (up to 6 simultaneous sockets)

Also extends the AT session to support prefixed terminations (e.g. "0, SEND OK") used by SIM800L in multi-connection mode.

Add support for the SIMCom SIM800L 2G module, following the existing
driver architecture (Quectel, Sequans, u-blox).

Key implementation details:
- GSM/GPRS only: uses +CGREG instead of +CEREG for registration
- SIMCom TCP/IP stack: AT+CSTT/CIICR/CIFSR for GPRS bearer,
  AT+CIPSTART/CIPSEND/CIPRXGET for sockets
- Manual data receive mode (AT+CIPRXGET=1) for clean AT parsing
- Async DNS via AT+CDNSGIP
- Multi-connection mode (up to 6 simultaneous sockets)

Also extends the AT session to support prefixed terminations
(e.g. "0, SEND OK") used by SIM800L in multi-connection mode.

main:
// Enable the board's power management IC.
power-control := gpio.Pin --output 23
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to have this happen when something connects to the network.
That would require subclassing the existing class.
Investigate.

If you find a solution, don't forget to update the README.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following the Olimex PoE Ethernet pattern, the power IC is now managed at the service provider level. Sim800lTCallService overrides open-network/close-network to enable/disable GPIO 23. Tested with two concurrent clients — power IC stays on while any client is connected, shuts off when the last disconnects.

done

The SIM800L operates at **3.7-4.2V** and can draw up to **2A** during
transmission bursts. Make sure your power supply can handle this.

- Do **not** power the module from the ESP32's 3.3V pin.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More importantly: don't power it with the 5V.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

- Do **not** power the module from the ESP32's 3.3V pin.
- A LiPo battery (3.7V, 1200mAh+) or a 2A-capable DC-DC converter is recommended.
- Some boards (like the LilyGO T-Call) include a power management IC.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also add a note that the 3.3V can't go directly to the module for the RX.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

## Limitations

- 2G (GSM/GPRS) only — no LTE support.
- Maximum 6 simultaneous TCP/UDP connections.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does our driver handle things when there are more connections?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The driver throws ResourceExhaustedException when all 6 slots are in use (tested on hardware). Updated README.

done


- 2G (GSM/GPRS) only — no LTE support.
- Maximum 6 simultaneous TCP/UDP connections.
- Maximum ~1460 bytes per send operation.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question: what happens if we try to send something bigger? Do we chunk correctly?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TCP try-write_ chunks automatically (if to - from > MAX-SIZE_: to = from + MAX-SIZE_). UDP throws if over MTU. Updated README.

done

connect_:
// On SIM800L, the connection is established after CIPSTART returns OK.
// The "<id>, CONNECT OK" notification is not a standard URC and is
// handled by the sleep in the constructor.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a fan of this. Is there no way to wait for this? We can change the 'at.toit' if necessary.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed together with the comment above.

done

if to - from > MAX-SIZE_: to = from + MAX-SIZE_
data = data.byte-slice from to

e := catch --unwind=(: it is not UnavailableException):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to assign to a local if we don't do anything with it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

cellular_.sockets_.remove id

mtu -> int:
return 1500
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this related to the MAX-SIZE?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are related but distinct: MTU (1500) is the IP-level maximum, MAX-SIZE_ (1460) is the SIM800L per-AT-command data limit (≈ MTU minus TCP/IP headers). Added a clarifying comment.

done

"$address.port",
]
// Wait for CONNECT OK.
sleep --ms=3000
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as for the tcp socket. Can we monitor the TX somehow?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed together with comment on simcom.toit:94.

done

else:
parts

// CCID response parser (ICCID is too large for int).
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this mean?
ints in Toit are 64 bit.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reworded: ICCIDs are 19-20 digits. A 64-bit signed int holds up to ~9.2×10^18 (19 digits), so 20-digit ICCIDs overflow. The custom parser reads the value as a string to avoid inconsistent behavior from the default int-parsing fallback.

done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant