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