Project Goal: React on receiving a LoRa message and forward it as an SMS.

 

A transmitter will send LoRa messages on demand.

A receiver will listen for messages and when it picks up a communication, sends the payload as SMS.

 

Components:

  • 2 SemTech LoRa MBED shields with Antennas
  • 1 Arduino MKR 1040 GSM with Antenna
  • 1 more Arduino MKR 1xxx or any 3V3 model.
  • 16 jumper wires
  • 1 data enabled active SIM card

 

Scenario

 

There are two Arduinos with a SemTech LoRa shieldSemTech LoRa shield connected.

One Arduino will be the transmitter, the second one the receiver.

When the transmitter receives a request to send (in my example it gets that request via the USB serial port), it creates a package and beams it out as a LoRa radio signal.

 

The other Arduino ( the receiver, has to be a MKR 1040 GSMMKR 1040 GSM or another Arduino with a GSM shield) is continuously polling for LoRa traffic.

When it picks up a payload, it sends that data to a predefined telephone number (my mobile phone).

 

lora semtech gsm scenario

 

You can see the result in the screen captures below.

The right upper monitor shows the transmitter. I typed "from SemTech LoRa: Hello, world!"

The lower monitor shows that the receiver got the message and forwarded it as an SMS.

My mobile phone on the left has received that payload as a text message.

 

I've used 434 MHz, antennas need to be matched and mounted on the LF connector of the shields.

If you prefer to use the 868 or 915 band, you just need to change a few parameters in the sketches and mount a matching antenna on the HF connectors.

 

 

Connections

 

The connections you make are identical for sender and receiver.

The table below shows the required links to be made.

The sender does not have to be a specific Arduino type, as long as it's 3V3 version. Don't use an Arduino UNO.

If you choose a non-MKR Arduino, take care that you pass the pins that nSS (nCS), DIO0 and DIO1 are connected to, as parameters to the constructor.

 

Put antennas on the radios and the GSM board, please.

 

Transmitter sketch

 

/*
   LoRaLib Transmit Example

  This example transmits LoRa packets with one second delays
   between them. Each packet contains up to 256 bytes
   of data, in the form of:
    - Arduino String
    - null-terminated char array (C-string)
    - arbitrary binary data (byte array)

   For more detailed information, see the LoRaLib Wiki
   https://github.com/jgromes/LoRaLib/wiki


   For full API reference, see the GitHub Pages
   https://jgromes.github.io/LoRaLib/
*/

// include the library
#include <LoRaLib.h>

// create instance of LoRa class using SX1278 module
// this pinout corresponds to RadioShield
// https://github.com/jgromes/RadioShield
// NSS pin:   10 (4 on ESP32/ESP8266 boards)
// DIO0 pin:  2
// DIO1 pin:  3
SX1276 lora = new LoRa(7, 2, 3);

void setup() {
  Serial.begin(9600);
  // initialize SX1278 with default settings
  Serial.println(F("Initializing ... \n"));
  // carrier frequency:           434.0 MHz
  // bandwidth:                   125.0 kHz
  // spreading factor:            9
  // coding rate:                 7
  // sync word:                   0x12
  // output power:                17 dBm
  // current limit:               100 mA
  // preamble length:             8 symbols
  // amplifier gain:              0 (automatic gain control)
  int state = lora.begin();
  if (state == ERR_NONE) {
    Serial.println(F("success!"));
  } else {
    Serial.print(F("failed, code "));
    Serial.println(state);
    while (true);
  }
}

void loop() {


  // sms text
  Serial.println("Enter SMS content: ");
  char txtMsg[200];
  readSerial(txtMsg);
  Serial.println("SENDING");
  Serial.println();
  Serial.println("Message:");
  Serial.println(txtMsg);  
  
  Serial.print(F("Sending packet ... "));
  // you can transmit C-string or Arduino string up to
  // 256 characters long
  // NOTE: transmit() is a blocking method!
  //       See example TransmitInterrupt for details
  //       on non-blocking transmission method.
  int state = lora.transmit(txtMsg);
  if (state == ERR_NONE) {
    // the packet was successfully transmitted
    Serial.println(F(" success!"));
    // print measured data rate
    Serial.print(F("Datarate:\t"));
    Serial.print(lora.getDataRate());
    Serial.println(F(" bps"));
  } else if (state == ERR_PACKET_TOO_LONG) {
    // the supplied packet was longer than 256 bytes
    Serial.println(F(" too long!"));
  } else if (state == ERR_TX_TIMEOUT) {
    // timeout occurred while transmitting packet
    Serial.println(F(" timeout!"));
  }
  // wait a second before transmitting again
  delay(1000);
}

/*
  Read input serial
 */
int readSerial(char result[]) {
  int i = 0;
  while (1) {
    while (Serial.available() > 0) {
      char inChar = Serial.read();
      if (inChar == '\n') {
        result[i] = '\0';
        Serial.flush();
        return 0;
      }
      if (inChar != '\r') {
        result[i] = inChar;
        i++;
      }
    }
  }
}

 

Receiver sketch

 

/*
 SMS sender

 This sketch, for the MKR GSM 1400 board,sends an SMS message
 you enter in the serial monitor. Connect your Arduino with the
 GSM shield and SIM card, open the serial monitor, and wait for
 the "READY" message to appear in the monitor. Next, type a
 message to send and press "return". Make sure the serial
 monitor is set to send a newline when you press return.

 Circuit:
 * MKR GSM 1400 board
 * Antenna
 * SIM card that can send SMS

 created 25 Feb 2012
 by Tom Igoe
*/

/*
   LoRaLib Receive Example

   This example listens for LoRa transmissions and tries to
   receive them. To successfully receive data, the following
   settings have to be the same on both transmitter
   and receiver:
    - carrier frequency
    - bandwidth
    - spreading factor
    - coding rate
    - sync word
    - preamble length

   For more detailed information, see the LoRaLib Wiki
   https://github.com/jgromes/LoRaLib/wiki

   For full API reference, see the GitHub Pages
   https://jgromes.github.io/LoRaLib/
*/

// Include the GSM library
#include <MKRGSM.h>
// include the LoRa library
#include <LoRaLib.h>

#include "arduino_secrets.h" 
// Please enter your sensitive data in the Secret tab or arduino_secrets.h
// PIN Number
const char PINNUMBER[] = SECRET_PINNUMBER;

// initialize the library instance
GSM gsmAccess;
GSM_SMS sms;

// create instance of LoRa class using SX1278 module
// this pinout corresponds to RadioShield
// https://github.com/jgromes/RadioShield
// NSS pin:   10 (4 on ESP32/ESP8266 boards)
// DIO0 pin:  2
// DIO1 pin:  3
SX1278 lora = new LoRa(7, 2, 3);
char remoteNum[20];  // telephone number to send sms

void setup() {
  // initialize serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // initialize SX1278 with default settings
  Serial.print(F("Initializing ... "));
  // carrier frequency:           434.0 MHz
  // bandwidth:                   125.0 kHz
  // spreading factor:            9
  // coding rate:                 7
  // sync word:                   0x12
  // output power:                17 dBm
  // current limit:               100 mA
  // preamble length:             8 symbols
  // amplifier gain:              0 (automatic gain control)
  int state = lora.begin();
  if (state == ERR_NONE) {
    Serial.println(F("success!"));
  } else {
    Serial.print(F("failed, code "));
    Serial.println(state);
    while (true);
  }    
  Serial.println("SMS Messages Sender");
  // connection state
  bool connected = false;
  // Start GSM shield
  // If your SIM has PIN, pass it as a parameter of begin() in quotes
  while (!connected) {
    if (gsmAccess.begin(PINNUMBER) == GSM_READY) {
      connected = true;
    } else {
      Serial.println("Not connected");
      delay(1000);
    }
  }
  Serial.println("GSM initialized");

  Serial.print("Enter a mobile number: ");
  readSerial(remoteNum);
  Serial.println(remoteNum);
}


void loop() {
  Serial.print(F("Waiting for incoming transmission ... "));
  String str;
  int state = lora.receive(str);

  if (state == ERR_NONE) {
    // packet was successfully received
    Serial.println(F("success!"));
    // print data of the packet
    Serial.print(F("Data:\t\t\t"));
    Serial.println(str);

    Serial.println("SENDING");
    Serial.println();
    Serial.println("Message:");
    Serial.println(str);
    // send the message
    sms.beginSMS(remoteNum);
    sms.print(str);
    sms.endSMS();
    Serial.println("\nCOMPLETE!\n");
  
    // print RSSI (Received Signal Strength Indicator)
    // of the last received packet
    Serial.print(F("RSSI:\t\t\t"));
    Serial.print(lora.getRSSI());
    Serial.println(F(" dBm"));

    // print SNR (Signal-to-Noise Ratio)
    // of the last received packet
    Serial.print(F("SNR:\t\t\t"));
    Serial.print(lora.getSNR());
    Serial.println(F(" dB"));

    // print frequency error
    // of the last received packet
    Serial.print(F("Frequency error:\t"));
    Serial.print(lora.getFrequencyError());
    Serial.println(F(" Hz"));
  } else if (state == ERR_RX_TIMEOUT) {
    // timeout occurred while waiting for a packet
    Serial.println(F("timeout!"));
  } else if (state == ERR_CRC_MISMATCH) {
    // packet was received, but is malformed
    Serial.println(F("CRC error!"));
  }
}

/*
  Read input serial
 */
int readSerial(char result[]) {
  int i = 0;
  while (1) {
    while (Serial.available() > 0) {
      char inChar = Serial.read();
      if (inChar == '\n') {
        result[i] = '\0';
        Serial.flush();
        return 0;
      }
      if (inChar != '\r') {
        result[i] = inChar;
        i++;
      }
    }
  }
}

 

Both sketches are based on examples from the MKRGSM (SendSMS) and LoRaLib (Transmit and Receive) libraries.

I did only mix, move and match to get the desired functionality.

 

real world scenario:

 

The transmitter has sensors and sends measurements to the receiver over LoRa.

The receiver sends an SMS if the measurements are out of range

 

A panic button in a basement where there is no mobile phone reception.