Clipper LTE with Arduino

The Pimoroni Clipper (A7683E) is a neat LTE board. (The micro-SIM card needs to be inserted with the missing corner first.)

Note that the PowerUp sequence timing as appear to be quite critical, as the board wont respond if you don’t power it up correctly.

Also note that it appears that the “Reset” pin does not need to be used, and may be able to be just connected to a 10k pullup.

The below Sketch demonstrates basic setup in Arduino (I was using a “Seeed XIAO_ESP32S3” to drive it):

#define Rx_to_gsm_Tx D0
#define Tx_to_gsm_Rx D8
#define gsm_ResetPin D9 // It does not appear to be necessaty to use this "Reset" pin, so an extenral 10k pullup might be sufficient
#define gsm_PowerPin D7
#define gsm_NET_Pin  D10

void setup() {
  Serial.begin(115200); delay(3000);
  Serial2.begin(115200, SERIAL_8N1, Rx_to_gsm_Tx, Tx_to_gsm_Rx);

  pinMode(gsm_NET_Pin, INPUT);
  pinMode(gsm_ResetPin, INPUT_PULLUP);
  delay(50); // min 40ms
  pinMode(gsm_PowerPin, OUTPUT);

  Serial.println("\n***** Reset A7683E Modem *****");
  Reset_modem();
  wait_s(10);
 
  Serial.println("\n***** Start test *****");
  boolean net_open=false;
  do {
    Serial.print("*** Modem CCID: "); Serial2.print("AT+GSN\r"); get_reply_ok_5s();
    Serial.print("*** Modem Temperature: "); Serial2.print("AT+CPMUTEMP\r"); get_reply_ok_5s();
    Serial.print("*** SIM IMSI: "); Serial2.print("AT+CIMI\r"); get_reply_ok_5s();
    Serial.print("*** SIM ICCID: "); Serial2.print("AT+CICCID\r"); get_reply_ok_5s();

    Serial.print("*** Network Connection Status: "); if (!send_command_ok("AT+COPS?")) break;
    Serial.print("*** Find Networks (upto 30s): "); send_command_ok_long("AT+COPS=?");
 
    Serial.println("\n***** Setting-up Network *****");
    if (!send_command_ok("AT+CGDCONT=1,\"IP\",\"iot.1nce.net\"")) break;
    wait_s(5); // give it time to connect

    if (!send_command_ok("AT+NETOPEN")) { // Start Socket Service
      Serial.println("***** Re-Try AT+NETOPEN *****");
      wait_s(5); if (!send_command_ok("AT+NETOPEN")) break;
    }
    net_open=true;
    if (!send_command_ok("AT+CIPRXGET=1")) break;
    Serial.print("***** IP Address: "); if (!send_command_ok("AT+IPADDR")) break;         

    if (!send_command_ok("AT+CNTP=\"pool.ntp.org\",4")) break; // time-zone=4 (ie.BST)
    if (!send_command_ok("AT+CNTP")) break; // Update network-time
    Serial.print("*** Network Time: "); if (!send_command_ok("AT+CCLK?")) break;
 
  } while (false);
 
  if (net_open) {if (send_command("AT+NETCLOSE","+NETCLOSE: 0")) Serial.println("***** NET=Closed OK"); else Serial.println("***** Error: NET-Close FAILED");}
  wait_s(5);
  Serial.println("\n***** End test *****\n");
}

void loop() {
  check_net_LED();
}

void Reset_modem() {
  // delay(40); // already done
  digitalWrite(gsm_PowerPin, LOW); // digitalWrite(gsm_ResetPin, LOW);
  delay(100); // min 50ms
  digitalWrite(gsm_PowerPin, HIGH); // digitalWrite(gsm_ResetPin, HIGH);
  delay(20); // min 10ms // probably not necessary
  send_command_ok("AT");
  delay(5);
}

boolean get_reply(char text[], int wait_s, char *buf=nullptr) {
  char *b=buf;
  boolean got=false;
  char *t=text;
  wait_s*=10;
  while (--wait_s) {
    delay(100);
    while (Serial2.available()) {
      char c=Serial2.read(); Serial.write(c); delay(1);
      if (t) {
        if (c!=*t) t=text;
        else {t++; if (*t==0) {t=0; wait_s=5;}}
      } else if (b) {*b=c; b++;}
    }
  }
  if (b) *b=0;
  if (t) Serial.println();
  return (t==0);
}
boolean get_reply_ok_5s() {return get_reply("OK",5);}
boolean send_command_ok(char *text) {Serial2.print(text); Serial2.write('\r'); return get_reply("OK",5);}
boolean send_command_ok_long(char *text) {Serial2.print(text); Serial2.write('\r'); return get_reply("OK",30);}
boolean send_command(char *text, char *reply) {Serial2.print(text); Serial2.write('\r'); return get_reply(reply,5);}
void wait_s(int s) {s*=10; for (int x=0;x<s;x++) {while (Serial2.available()) {Serial.write(Serial2.read()); delay(1);} delay(100);}}

void check_net_LED() { // 155 in 31s so 40 in 8s
  #define REPEAT_MESSAGE_MS 10000 // 10s (should get ~50 on/offs)
  #define FLASHING_COUNT 25
  static boolean led_flashing=false;
  static int count=0;
  static boolean n_old=0;
  boolean n=digitalRead(gsm_NET_Pin);
  if (n_old!=n) {n_old=n; count++;}
  if ((count>=FLASHING_COUNT) and !led_flashing) {led_flashing=true; Serial.println("***** LED is flasing *****");}
  static uint32_t millis_old=0;
  uint32_t millis_now=millis();
  if (millis_old<=millis_now) {millis_old=millis_now+REPEAT_MESSAGE_MS; count=0; led_flashing=false;}
}

1 Like

Re. SIMCOM A7683E in the Clipper LTE 4G Breakout

Although the “A7600_Series_AT_Command_Manual_V1.02.pdf” lists commands like [ATD0123456789] (Mobile Originated Call to Dial A Number) and [AT+CUSD=1,”*#10#”,15], (Unstructured Supplementary Service Data), the SIMCOM A7683E does NOT allow them. (This is also the case for many of the SIMCOM SIM7000 series modules.)

Specifically if connected to a GSM/4G network (using a standard GSM/3G/4G SIM-card), the A7683E resisters with the network but tells the network that is has no voice capabilities. Therefore although you can both send and receive SMS messages fine, you can NOT dial-out (ie. [ATD0123456789]). If you try to phone-in to the A7683E’s number, the network does not allow it (saying the number is not-currently-available, or if setup always diverting to the voice-mailbox). (Although this does have the advantage that SPAM callers won’t keep trying to phone it!)

Similarly, the A7683E will currently not accept [AT+CUSD=1,”*#10#”,15] Unstructured Supplementary Service Data) type commands either (initially returning “+CME ERROR: operation not supported” and subsequently just returning “ERROR”). This is a pity as it means you can’t request sim-balance data using this method.

Compare this with the old SIM800 which had voice capabilities and could do all of the above, but obviously only on the 2G(GSM) network.

(The [AT+GMR] or [AT+CGMR] firmware version of the A7683E I am using is “+CGMR: 22110B03A7683M6A”.)