6
votes

I have a Raspberry Pi with a SIM900 GSM add-on board connected. I have managed to establish a GPRS connection with pppd by following this guide. (It's for a different GSM module but the steps are the same)

I would like to periodically send an AT command (AT+CCLK?) to the SIM900 to check the clock. I have managed send ad hoc AT commands using screen but when pppd is up I can't use screen to connect to the serial line. It just exits straight away saying [screen is terminating]. I'm guessing this is because pppd is using it to connect to the internet.

Q: How do I get the clock time without having to close down pppd?

Looking at part of the user manual it says that the SIM900 has a multiplexer designed to the GSM0710 standard. Would this be useful? If so how would I achieve this?

4

4 Answers

5
votes

Okay I have almost solved this but stuck at the very last hurdle. Thought I would show what I have managed to do as it may help someone else.

I found this other post on stack overflow that lists 3 possible ways to achieve this. I didn't want to be controlling the gprs via AT commands when PPP (in my limited experience) handles this well and easily. The RPi only has one serial port so I couldn't multiplex over multiple serial interfaces.

So that left me with multiplexing over a single serial interface, let's hope the SIM900 supports this. I found here the User Manual on the SIM900 multiplexer which uses the GSM07.10 standard.

I couldn't find much information on how to set up multiplexing but eventually after digging around I found this document on an n_gsm module in the linux kernel. I can just about follow what it was talking about but not enough to write my own program to set up a number of virtual serial ports.

Thankfully after some more scouring of google I found that this extraordinary gentleman has created a C program to use the n_gsm module to set up the virtual serial ports for us.

I downloaded, configured and built the program as per the instructions and tried to load the n_gsm module. Unfortunately the RPi doesn't include the n_gsm module as default so I had to go and build a new kernel with n_gsm added as a module. I followed the instruction on the RPi website which are very good.

For the SIM900 I had to change line 322 to remove the &w of the end of the AT+IPR command. It should know look like:

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

I also edited line 128 to sleep(1.5) before trying to read a response as it was sometimes returning an error because it hadn't got a response in time.

So I run the cmux program (with sudo as it needs to create the new /dev/ttyGSM* devices) and it runs through the AT commands, sets the line discipline and creates the new virtual serial devices but when I try and open a serial terminal with screen /dev/ttyGSM1 115200 screen just returns [screen is terminating].

I did sudo fuser /dev/ttyGSM1 which returned nothing so no other process is using it.

I then tried echo AT > /dev/ttyGSM1 which returned -bash: /dev/ttyGSM1: Level 2 halted.

I'm not sure what this is referring to and couldn't find any information on this message. Could it be talking about layer 2 of the OSI model a.k.a the data link layer?

Anyway this is how far I have got. I have decided to put it to one side for now and just use NTP but I hope this helps someone else out. If you do find a solution to this or can suggest something I may have missed please do say. Thanks

3
votes

I will answer this question because it might help someone else too. But I want to start with sharing my experience with multiplexing the UART interface. After I set it all up is seemed like everything was working well. But when I was trying to connect to VPN or transfer some files Raspbian was completely freezing. I'm not sure what is the problem exactly, but it seems to be related to the n_gsm or the cmux components. Low bandwidth applications like ping, telnet or SSH seem to work fine though. The n_gsm module is marked as experimental and should probably not be used in production.


The n_gsm kernel module is not included in Raspbian by default. To start using a CMUX driver we need to update Raspbian and download the kernel source files, then we can compile the n_gsm module.

  1. Make sure your system is up to date, install dependencies and update the kernel
sudo -i
apt update
apt dist-upgrade
apt install bc bison git build-essential flex libssl-dev
rpi-update
sync
reboot
  1. Download kernel sources so we can make our own kernel module
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. Build the kernel module for experimental GSM MUX line discipline support
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

You may want to add the module in your /etc/modules as well if you want to load it automatically on boot.

  1. Download and compile the GSM MUX driver (CMUX)
cd /usr/local/src/
git clone https://github.com/Rtone/cmux.git
cd cmux

Usually you need to edit cmux.c before compiling. Here is the diff that I used for my setup.

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");

After making the changes, we should be ready to compile, install and run the multiplexer.

make
cp cmux /usr/bin/cmux
cmux
  1. Using the new serial interfaces

We should now be able to use the new interfaces. Instead of using /dev/ttyAMA0 we can now use both /dev/ttyGSM1 and /dev/ttyGSM2. I'm using the first one with pppd and the second one to send AT commands simultaneously. For some reason I was unable to keep using wvdial, so I dropped that completely and started using pppd directly. For both cmux and pppd I created a systemd service that runs on boot, after each other, so at startup Raspbian is setting up the multiplexer and connecting with the internet over PPP. When the connection is live I'm sending an SMS message (through the secondary mux) to report that the terminal is now online.


I also wrote this post on the Seeed forum to answer a similar question. I'm curious if anyone shares my experience with stability or if anyone is able to share some improvements.

1
votes

i was trying the same and your post helped me very much, finally i've succeeded in doing it following the guide at: https://github.com/guowenxue/embedded_project/tree/master/program/ldattach_gsm0701

but without the patch of the n_gsm driver, in fact doing it the devices 1 to 3 disappeared. with the standard n_gsm.c, ldattach created 63 devices 1 to 4 are working the others not.

i've played al lot with settings, if you have any problem i can post you the entire ldattach.c, anyway i think it will work as standard.

the only drawback now is that when using ppp the bandwidth is so low that most of at commands takes seconds to reply, i'm also trying to get the pop working well, now is really slow.

i think i should lower the bandwidth of the virtual serials as i've not hw flow control (i've also disabled it in ldattach's serial configuration)

le me know if it works for you.

1
votes

I had the same problem ([screen is terminating], level 2 halted). Take care about the sleep() delay between write() cmux AT command to serial port and setting line discipline via ioctl(). The delay should not be long. Modems have timeout to reset from cmux mode if you don't set line discipline in time. Here are some details and proof.

As for me, I've removed this delay at all.