Please note:
I've tried my best to explain the situation in its fullest with all necessary details. If you do have any questions, feel free to ask and I will try to clarify.
The situation:
So I've been having issues with my project for over two years now, and I'm finally seeking help. I hope I'm in the right category with this.
I own a holiday home in a residential apartment building with an underground parking garage for residents only. This garage has an electric garage door that is controlled with remote controls. Each resident only gets 2 remotes.
Since not only I myself, but also my parents, brothers and aunt/uncle come visit this holiday home, we would need more remotes for every car. I've tried to copy a remote and duplicate it, but the problem is that this system requires remotes to be linked with the central computer and they use a rolling code to secure it so I can only use original remotes.
My solution:
I thought of buying an Arduino MKR GSM 1400 to which I would connect a relay, to which in turn I would connect a remote. This way I could short the remote using a relay which would be controlled by the Arduino.
I programmed the Arduino to connect to the GSM network, and control the relay when specific phone numbers would call the Arduino. By whitelisting certain phone numbers I could prevent the misusage by only allowing certain people's phone number to open the garage door.
The only thing I did have to make sure was that the SIM card I had inserted in the module would send out a text message at least once every 3 months. This is because the SIM card would otherwise get disabled by the provider if not used regularly. I programmed the Arduino to send myself a text message once every 3 months.
Also I programmed it to flush every text message it gets (in case it ever gets one) since it doesn't need it.
The issue:
When I set this up about two years ago, the system worked fine. Only once in a while the board would lose connection and I would restart the board after which it would work again. Then I tried to program the board to reset/restart itself when it would lose connection. That's when the issues started.
I cannot get the board to have a stable connection with the GSM network, nor can I have it reliably restart whenever it loses connection. I have no idea why the board will not remain connected, nor do I know why it cannot simply restart when it loses connection. I've tried so many versions of my code, but none would result in a stable reliable setup.
The board will connect, establish a connection and work as intended for an arbitrary amount of times before it will fail after which it is supposed to restart but it won't or will not re-establish connection. This is the issue.
The hardware:
- Arduino MKR GSM 1400
- Arduino MKR Relay Shield (Please note that the Arduino is properly plugged in the Relay shield as is intended, I just couldn't make that clear on the schematic visual)
- Dipole Pentaband Waterproof Antenna
- Lithium Ion Polymer Battery - 3.7v 2500mAh [KW-1480]
- Hörmann RSM4-433 remote
- Raspberry Pi 12.5W Micro USB Power Supply
Please note that by advice of many on the internet I have supplied the board with a powerful enough power supply (12.5W) and also a LiPo battery to handle any peak-currents caused by the GSM signal.
The setup (schematic):
The code:
Please note I have censored the actual phone numbers of me and my family.
#include <MKRGSM.h>
#include <TimeLib.h>
// GSM and GPRS instances
GSM gsmAccess;
GPRS gprs;
GSMScanner GSMScan;
GSMVoiceCall voiceCall;
GSM_SMS sms;
// Relay and LED pins
const int relayPin = 1;
char PINNUMBER [] = ""; // PIN-Code of the Simcard
const int ledPin = LED_BUILTIN;
// Whitelisted numbers
const char *whitelist[] = {"+00123456789", "+00123456789", "+00123456789", "+00123456789", "+00123456789", "+00123456789", "+00123456789", "+00123456789", "+00123456789"};
const int whitelistSize = sizeof(whitelist) / sizeof(whitelist[0]);
// Phone number to send text message
const char *textMessagePhoneNumber = "+00123456789";
// Pre-composed text message
const char *textMessage = "This is an automated message. I'm online.";
// Variables for text message sending interval
int lastSentMonth = -1;
bool connected = false;
unsigned long lastGSMCheck = 0;
unsigned long checkInterval = 60000; // Check connection every 30 seconds
unsigned long reconnectTimeout = 60000; // 30 seconds timeout
void setup() {
bool connected = false;
pinMode(relayPin, OUTPUT);
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
Serial.println("Booting.");
delay(5000); // Give the GSM module some time to initialize
int retries = 0;
const int maxRetries = 5;
while (!connected && retries < maxRetries) {
if (gsmAccess.begin(PINNUMBER) == GSM_READY) {
connected = true;
} else {
connected = false;
Serial.println("Not connected");
retries++;
delay(1000);
}
}
if (retries >= maxRetries) {
Serial.println("Failed to connect after maximum retries. Restarting the board.");
NVIC_SystemReset();
} else {
digitalWrite(ledPin, HIGH); // Solid: connected
Serial.println("GSM initialized.");
Serial.println("Awaiting Call.");
Serial.println("");
}
}
void loop() {
unsigned long currentTime = millis();
if ((currentTime - lastGSMCheck) >= checkInterval) {
lastGSMCheck = currentTime;
checkGSMConnection();
}
Serial.println(GSMScan.getSignalStrength());
checkForVoiceCall();
checkForTextMessage();
sendTextMessageEveryThreeMonths();
}
void checkGSMConnection() {
if (gsmAccess.isAccessAlive() != GSM_READY) {
connected = false;
Serial.println("Connection lost. Trying to reconnect...");
unsigned long reconnectStartTime = millis();
while (!connected && (millis() - reconnectStartTime) < reconnectTimeout) {
connectToCarrier();
delay(500); // Short delay between reconnection attempts
}
if (!connected) {
Serial.println("Reconnection failed. Restarting device...");
NVIC_SystemReset();
} else {
Serial.println("Reconnected successfully.");
}
}
}
void connectToCarrier() {
digitalWrite(ledPin, LOW); // Turn LED off.
// Start GSM connection
if (gsmAccess.begin(PINNUMBER) == GSM_READY) {
connected = true;
Serial.println("\nConnected to carrier.");
digitalWrite(ledPin, HIGH); // Solid LED: connected
} else {
connected = false;
Serial.println("Not connected");
delay(1000);
}
}
void checkForVoiceCall() {
if (voiceCall.getvoiceCallStatus() == RECEIVINGCALL) {
char phoneNumber[20];
voiceCall.retrieveCallingNumber(phoneNumber, 20);
bool isWhitelisted = false;
for (int i = 0; i < whitelistSize; i++) {
if (strcmp(phoneNumber, whitelist[i]) == 0) {
isWhitelisted = true;
break;
}
}
voiceCall.hangCall();
if (isWhitelisted) { // If whitelisted person calls, activate the relay.
activateRelay();
delay(10000);
NVIC_SystemReset(); // I've tried the code with and without this line. I was trying whether it would be better to just restart the whole setup everytime some had called, it made no difference.
}
}
}
void checkForTextMessage() {
if (sms.available()) {
char phoneNumber[20];
sms.remoteNumber(phoneNumber, 20);
sms.flush(); // Flush the message
}
}
void activateRelay() {
for (int i = 0; i < 4; i++) {
digitalWrite(relayPin, HIGH);
delay(2000);
digitalWrite(relayPin, LOW);
delay(250);
}
}
void sendTextMessageEveryThreeMonths() {
time_t currentTime = gsmAccess.getTime();
int currentMonth = month(currentTime);
int currentDay = day(currentTime);
if ((currentMonth - lastSentMonth) % 3 == 0 && currentDay == 1 && currentMonth != lastSentMonth) {
Serial.print("Send Textmessage. Online.");
sms.beginSMS(textMessagePhoneNumber);
sms.print(textMessage);
sms.endSMS();
Serial.println("\nCOMPLETE!\n");
lastSentMonth = currentMonth;
}
}
Thank you very much for taking the time to read about my project and I hope someone is able to help ![]()
