了解如何在 Arduino IDE 上使用 WIZnet Pico 构建 SMS 网关,通过 LTE Cat.M1 将消息从 WebServer 发送到手机。
转发: Building an Ethernet to LTE SMS Basic Gateway with WIZnet Pico on Arduino IDE(3GPP)
项目介绍
概述
本指南详细介绍了如何使用 WIZnet Pico 板设置 SMS 网关,在 Arduino IDE 中结合 Raspberry Pi Pico 和 W5500 以太网。 WIZnet Pico 充当 Web 服务器,接受电话号码和消息,并使用 3GPP AT 命令通过 LTE Cat.M1 模块将其作为短信发送。 对于那些对基于 Arduino 的网络和电信感兴趣的人来说,该项目是一个实用示例,提供了物联网和通信技术方面的技术见解和实践经验。
步骤 1. 设置 Arduino IDE 环境
设置环境以通过 Raspberry Pi Pico 使用以太网。
- WIZnet Github: GitHub - Wiznet/arduino-pico: Raspberry Pi Pico Arduino core, for all RP2040 boards with Ethernet from https://github.com/WIZnet-ArduinoEthernet/arduino-pico
- 开始使用Arduino: The Arduino Raspberry Pi Pico/RP2040-Ethernet V2.1.1 - Hackster.io
步骤 2. Raspberry Pi Pico 多串口套件(Serial、Serial2)
该项目需要两个串行通信端口:一个用于标准调试消息,另一个用于连接 LTE Cat.M1 模块。
下面详细介绍了 Earle Philhower 的 Arduino 板包的 Raspberry Pi Pico 的默认串行设置。 在此项目中,使用了 Serial(USB 端口,用于调试)和 Serial2(用于 LTE Cat.M1 模块)。
[板引脚图图像]
[Earle Philhower 串行默认设置]
- 有关 Arduino Multi Serial 使用的更多信息,请参阅以下链接:
步骤 3. 实施 Web 服务器
该项目中的 Web 服务器仅接收并存储电话号码和消息。 使用 ChatGPT 创建了一个 HTML 源,用于在 Raspberry Pi Pico 托管的 Web 服务器上输入这些详细信息。
[HTML 源代码]
[网络服务器]
以下代码在 Arduino IDE 中实现,说明了 WebServer 操作并将电话号码和消息存储在“phone”和“message”变量中。
[Arduino IDE WebServer 源代码]
步骤 4. 实施 SMS(LTE Cat.M1 模块)
为了使用 LTE Cat.M1 模块,使用了 3GPP 定义的 AT 命令。 请注意,每个模块制造商可能支持不同的命令。
对于该项目,使用的命令如下所示,以及数据流图。
[3GPP 命令图像]
[数据流程图]
通过串口通讯输入AT命令会返回结果,可以检查操作是否成功。 建议在连接到 Raspberry Pi Pico 之前使用 PC 在独立模式下测试 LTE Cat.M1 模块。 或者,可以使用串行到串行 2(多串行)连接进行测试:PC -<Serial0>- Raspberry Pi Pico -<Serial2>- LTE Cat.M1 模块。
步骤 5. 将 LTE Cat.M1 SMS 功能添加到 Web 服务器源
根据以上内容,您可以使用 W5500-EVB-Pico(Raspberry Pi Pico+W5500)、Arduino IDE 和 LTE Cat.M1 调制解调器实现一个简单的 WebServer(以太网)到 LTE Cat.M1 短信网关。 下面的代码是 WebServer 到 LTE Cat.M1 SMS 发送功能的基本示例。 它涉及 Raspberry Pi Pico 从连接到 WebServer 的客户端接收电话号码和 SMS 消息,并通过 LTE Cat.M1 调制解调器将这些 SMS 消息发送到手机。 该代码利用 Arduino IDE 的以太网库和 3GPP 定义的 AT 命令。 您可以在下面的视频中查看操作过程。
- [结果视频]
YouTube 视频链接
https://www.youtube.com/shorts/5XyrA-1Fyd0
- 来源
```cpp
#include <SPI.h>
#include <Ethernet.h>
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(<Your IP>);
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
String messages = "";
void setup() {
// You can use Ethernet.init(pin) to configure the CS pin
//Ethernet.init(10); // Most Arduino shields
//Ethernet.init(5); // MKR ETH shield
//Ethernet.init(0); // Teensy 2.0
//Ethernet.init(20); // Teensy++ 2.0
//Ethernet.init(15); // ESP8266 with Adafruit Featherwing Ethernet
//Ethernet.init(33); // ESP32 with Adafruit Featherwing Ethernet
Ethernet.init(17);
// Open serial communications and wait for port to open:
Serial.begin(9600);
//Serial2 = LTE Cat.M1
/*
Serial2.setTX(8);
Serial2.setRX(9); */
Serial2.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("Ethernet WebServer Example");
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected.");
}
// start the server
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
void loop() {
EthernetClient client = server.available();
if (client) {
boolean currentLineIsBlank = true;
String httpMethod, httpPath, postData;
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
if (httpMethod.length() == 0 || httpPath.length() == 0) {
if (c == ' ') {
if (httpMethod.length() == 0) {
httpMethod = postData;
postData = "";
} else if (httpPath.length() == 0) {
httpPath = postData;
postData = "";
}
} else {
postData += c;
}
} else if (c == '\n' && currentLineIsBlank) {
if (httpMethod == "POST") {
Serial.println("POST data received");
int endIndex;
while (client.available()) {
char k = client.read();
postData += k;
if (postData.endsWith("\r\n\r\n")) {
break; // End
}
}
// Phone Number and Message Parsing
String phone = parsePostData(postData, "phone=");
String message = parsePostData(postData, "&message=");
messages += "Phone: " + phone + ", Message: " + message + "<br>";
Serial.println(messages); // Debug Message
//SMS Send
Serial2.print("AT+CMGF=1\r\n");
delay(50);
while (1) {
if (Serial2.available())
{
char RC = Serial2.read();
Serial.write(RC);
if (RC == '\n') break;
}
}
Serial2.print("AT+CSCS=\"GSM\"\r\n");
delay(50);
while (1) {
if (Serial2.available())
{
char RC = Serial2.read();
Serial.write(RC);
if (RC == '\n') break;
}
}
Serial2.print("AT+CMGS=\"");
Serial2.print(phone);
Serial2.print("\"\r\n");
delay(50);
while (1) {
if (Serial2.available())
{
char RC = Serial2.read();
Serial.write(RC);
if (RC == '\n') break;
}
}
Serial2.print(message);
Serial2.println();
delay(50);
while (1) {
if (Serial2.available())
{
char RC = Serial2.read();
Serial.write(RC);
if (RC == '\n') break;
}
}
Serial2.println((char)26);
delay(50);
while (1) {
if (Serial2.available())
{
char RC = Serial2.read();
Serial.write(RC);
if (RC == '\n') break;
}
}
}
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
// Webpage Contents
client.println("<!DOCTYPE html>");
client.println("<html lang=\"en\">");
client.println("<head>");
client.println("<meta charset=\"UTF-8\">");
client.println("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">");
client.println("<title>Raspberry Pi Pico Web to LTE SMS Messenger</title>");
client.println("<style>");
client.println(" body { font-family: 'Arial', sans-serif; margin: 0 auto; max-width: 600px; padding: 1rem; }");
client.println(" h1, h2 { color: #333; }");
client.println(" form { margin-bottom: 2rem; }");
client.println(" input[type=text], input[type=submit] { padding: 0.5rem; margin: 0.5rem 0; }");
client.println(" input[type=submit] { color: white; background-color: #007BFF; border: none; cursor: pointer; }");
client.println(" input[type=submit]:hover { background-color: #0056b3; }");
client.println(" .history { background-color: #f2f2f2; padding: 1rem; border-radius: 0.5rem; }");
client.println("</style>");
client.println("</head>");
client.println("<body>");
client.println("<h1>LTE SMS Messenger</h1>");
client.println("<h2>Raspberry Pi Pico Web to SMS</h2>");
client.println("<form action=\"/\" method=\"POST\">");
client.println(" <label for=\"phone\">Phone Number:</label>");
client.println(" <input type=\"text\" id=\"phone\" name=\"phone\"><br>");
client.println(" <label for=\"message\">Message:</label>");
client.println(" <input type=\"text\" id=\"message\" name=\"message\"><br>");
client.println(" <input type=\"submit\" value=\"Send\">");
client.println("</form>");
client.println("<div class=\"history\">");
client.println(" <h2>Message History:</h2>");
client.println(messages);
client.println("</div>");
client.println("</body>");
client.println("</html>");
client.stop();
Serial.println("Client disconnected");
}
if (c == '\n') {
// New Line
currentLineIsBlank = true;
} else if (c != '\r') {
currentLineIsBlank = false;
}
}
}
}
}
// POST Data Parsing Function
String parsePostData(String data, String field) {
String result = "";
int startIndex = data.indexOf(field);
if (startIndex != -1) {
startIndex += field.length();
int endIndex = data.indexOf('&', startIndex);
if (endIndex == -1) {
endIndex = data.length();
}
result = data.substring(startIndex, endIndex);
result.replace('+', ' '); // Blank
result.replace("%20", " "); // URL Encoding Blank
}
return result;
}
[结果代码]
文件