在 pppd 处于活动状态时向 SIM900 发送 AT 命令

Sending AT commands to SIM900 whilst pppd is active

我有一个 Raspberry Pi 连接了 SIM900 GSM 附加板。我通过关注 this guide 成功地与 pppd 建立了 GPRS 连接。 (它适用于不同的 GSM 模块,但步骤相同)

我想定期向SIM900 发送一个AT 命令(AT+CCLK?) 来检查时钟。我已经设法使用 screen 发送临时 AT 命令,但是当 pppd 启动时,我无法使用 screen 连接到串行线路。它直接退出说 [screen is terminating]。我猜这是因为 pppd 正在使用它连接到互联网。

问:如何在不关闭 pppd 的情况下获取时钟时间?

查看 user manual 的一部分,它说 SIM900 有一个为 GSM0710 标准设计的多路复用器。这会有用吗?如果是这样,我将如何实现这一目标?

好的,我几乎已经解决了这个问题,但卡在了最后一个障碍。我想我会展示我所做的事情,因为它可能会帮助其他人。

我在堆栈溢出中发现 this other post,其中列出了实现此目的的 3 种可能方法。当 PPP(以我​​有限的经验)可以轻松轻松地处理这个问题时,我不想通过 AT 命令控制 gprs。 RPi 只有一个串行端口,所以我无法在多个串行接口上​​进行多路复用。

所以我只能通过单个串行接口进行多路复用,希望 SIM900 支持这一点。我找到了here使用GSM07.10标准的SIM900多路复用器的用户手册

我找不到太多关于如何设置多路复用的信息,但最终在深入研究后,我在 linux 内核的 n_gsm 模块上找到了 this 文档。我可以大致理解它在说什么,但还不足以编写我自己的程序来设置多个虚拟串口。

谢天谢地,经过google的更多搜索,我发现这位非凡的先生created a C program可以使用n_gsm模块为我们设置虚拟串口。

我按照说明下载、配置和构建程序,并尝试加载 n_gsm 模块。不幸的是,RPi 不包含默认的 n_gsm 模块,所以我不得不去构建一个新内核,并将 n_gsm 添加为一个模块。我关注了 RPi 网站上的 instruction,非常好。

对于 SIM900,我必须更改第 322 行以删除 AT+IPR 命令末尾的 &w。它应该知道看起来像:

if (send_at_command(serial_fd, "AT+IPR=115200\r") == -1) errx(EXIT_FAILURE, "AT+IPR=115200: bad response");

在尝试读取响应之前,我还将第 128 行编辑为 sleep(1.5),因为它有时会返回错误,因为它没有及时得到响应。

所以我 运行 cmux 程序(使用 sudo 因为它需要创建新的 /dev/ttyGSM* 设备)并且它 运行s 通过 AT 命令,设置线路规则并创建新的虚拟串行设备,但是当我尝试打开带有 screen /dev/ttyGSM1 115200 屏幕的串行终端时,屏幕只是 returns [screen is terminating]

我做了 sudo fuser /dev/ttyGSM1 没有返回任何东西,所以没有其他进程正在使用它。

然后我尝试了 echo AT > /dev/ttyGSM1,它返回了 -bash: /dev/ttyGSM1: Level 2 halted

我不确定这是指什么,也找不到关于此邮件的任何信息。难道是在谈论 OSI 模型的第 2 层 a.k.a 数据 link 层?

无论如何,这就是我的进展。我决定暂时把它放在一边,只使用 NTP,但我希望这能帮助其他人。如果您确实找到了解决方案或可以提出我可能遗漏的建议,请务必说出来。谢谢

我也在尝试同样的方法,你的 post 对我帮助很大,最后我按照以下指南成功地做到了:https://github.com/guowenxue/embedded_project/tree/master/program/ldattach_gsm0701

但是没有 n_gsm 驱动程序的补丁,事实上,设备 1 到 3 消失了。使用标准 n_gsm.c,ldattach 创建了 63 个设备 1 到 4 正在工作,其他设备没有。

我玩过很多设置,如果你有任何问题我可以 post 你整个 ldattach.c,无论如何我认为它会作为标准工作。

现在唯一的缺点是,当使用 ppp 时,带宽太低,以至于大多数 at 命令需要几秒钟才能回复,我也在努力让 pop 正常工作,现在真的很慢。

我认为我应该降低虚拟串行的带宽,因为我没有硬件流量控制(我也在 ldattach 的串行配置中禁用了它)

告诉我它是否适合你。

我遇到了同样的问题([屏幕正在终止],2 级暂停)。注意 write() cmux AT 命令到串行端口和通过 ioctl() 设置线路规程之间的 sleep() 延迟。延迟应该。如果您没有及时设置线路规则,调制解调器会超时从 cmux 模式重置。 Here 是一些细节和证据。

至于我,我已经完全消除了这个延迟。

我会回答这个问题,因为它也可能对其他人有所帮助。但我想首先分享我在多路复用 UART 接口方面的经验。在我设置好之后,一切似乎都运行良好。但是当我尝试连接到 VPN 或传输一些文件时 Raspbian 完全冻结了。我不确定到底是什么问题,但它似乎与 n_gsmcmux 组件有关。 ping、telnet 或 SSH 等低带宽应用程序似乎工作正常。 n_gsm 模块被标记为实验性的,可能不会在生产中使用。


n_gsm 内核模块默认不包含在 Raspbian 中。要开始使用 CMUX 驱动程序,我们需要更新 Raspbian 并下载内核源文件,然后我们可以编译 n_gsm 模块。

  1. 确保您的系统是最新的,安装依赖项并更新内核
sudo -i
apt update
apt dist-upgrade
apt install bc bison git build-essential flex libssl-dev
rpi-update
sync
reboot
  1. 下载内核源代码,这样我们就可以制作自己的内核模块
wget -O /usr/bin/rpi-source https://raw.githubusercontent.com/notro/rpi-source/master/rpi-source
chmod +x /usr/bin/rpi-source
/usr/bin/rpi-source -q --tag-update
rpi-source
  1. 为实验性 GSM MUX 线路规程支持构建内核模块
cd /root/linux/drivers/tty/
make -C /lib/modules/$(uname -r)/build M=$(pwd) -e CONFIG_N_GSM=m modules
cp /root/linux/drivers/tty/n_gsm.ko /lib/modules/`uname -r`/kernel/drivers/tty/
depmod
modprobe n_gsm

如果您想在启动时自动加载它,您可能还想在 /etc/modules 中添加该模块。

  1. 下载编译GSM MUX驱动(CMUX)
cd /usr/local/src/
git clone https://github.com/Rtone/cmux.git
cd cmux

通常你需要在编译前编辑cmux.c。这是我用于设置的差异。

diff --git a/cmux.c b/cmux.c
index 1af0f50..f13edfe 100644
--- a/cmux.c
+++ b/cmux.c
@@ -29,6 +29,7 @@
 #include <linux/types.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/sysmacros.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <err.h>
@@ -50,13 +51,13 @@
 #endif

 /* serial port of the modem */
-#define SERIAL_PORT    "/dev/ttyS1"
+#define SERIAL_PORT    "/dev/ttyAMA0"

 /* line speed */
 #define LINE_SPEED     B115200

 /* maximum transfert unit (MTU), value in bytes */
-#define MTU    512
+#define MTU    1400

 /**
 * whether or not to create virtual TTYs for the multiplex
@@ -66,7 +67,7 @@
 #define CREATE_NODES   1

 /* number of virtual TTYs to create (most modems can handle up to 4) */
-#define NUM_NODES      4
+#define NUM_NODES      2

 /* name of the virtual TTYs to create */
 #define BASENAME_NODES "/dev/ttyGSM"
@@ -313,15 +314,9 @@ int main(void) {
        *       to fit your modem needs.
        *       The following matches Quectel M95.
        */
-       if (send_at_command(serial_fd, "AT+IFC=2,2\r") == -1)
-               errx(EXIT_FAILURE, "AT+IFC=2,2: bad response"); 
-       if (send_at_command(serial_fd, "AT+GMM\r") == -1)
-               warnx("AT+GMM: bad response");
        if (send_at_command(serial_fd, "AT\r") == -1)
                warnx("AT: bad response");
-       if (send_at_command(serial_fd, "AT+IPR=115200&w\r") == -1)
-               errx(EXIT_FAILURE, "AT+IPR=115200&w: bad response");
-       sprintf(atcommand, "AT+CMUX=0,0,5,%d,10,3,30,10,2\r", MTU);
+       sprintf(atcommand, "AT+CMUX=0,0,0,%d,253,3,254,0,0\r", MTU);
        if (send_at_command(serial_fd, atcommand) == -1)
                errx(EXIT_FAILURE, "Cannot enable modem CMUX");

进行更改后,我们应该准备好编译、安装和 运行 多路复用器。

make
cp cmux /usr/bin/cmux
cmux
  1. 使用新的串行接口

我们现在应该可以使用新界面了。我们现在可以同时使用 /dev/ttyGSM1/dev/ttyGSM2,而不是使用 /dev/ttyAMA0。我正在使用第一个与 pppd 和第二个同时发送 AT 命令。由于某些原因,我无法继续使用 wvdial,所以我完全放弃了它并开始直接使用 pppd。对于 cmuxpppd 我创建了一个系统服务 运行 在启动时,一个接一个,所以在启动时 Raspbian 正在设置多路复用器并连接到互联网通过购买力平价。当连接处于实时状态时,我正在发送一条 SMS 消息(通过辅助多路复用器)以报告终端现在在线。


我也在Seeed forum to answer a similar question上写了这个post。我很好奇是否有人分享我在稳定性方面的经验,或者是否有人能够分享一些改进。