0

everyone I'm designing a vehicle security system, basically I can already read amd i control all the components (GSM, GPS, Magnetic Sensor, Giroscop, buzzer...) connected to the microcontroller.

But then the functions are basically three main ones (at void loop) that I need to be working in "simultaneous", any idea of how I can do that?

Below the code, half long but that's all I need...

there are some comments in portuguese. i apologize for that, but the important thing is in the code thanks in advance

#include <SoftwareSerial.h>
#include <TinyGPS++.h>
SoftwareSerial sgsm(3,2);
String number = "25884xxxxxxx" ;
unsigned char Buff[250];  
unsigned char BuffIndex;

#include<Wire.h>
int sensorMag = 5;  //SENSOR MAGNETICO

TinyGPSPlus gps;
double latitude, longitude;
String response;
int lastStringLength = response.length();
String link;

const int MPU6050_addr=0x68;
int16_t AccX,AccY,AccZ,Temp,GyroX,GyroY,GyroZ;

#include <IRremote.h>
int RECV_PIN = 4;   //REMOTE
IRrecv irrecv(RECV_PIN);
decode_results results;


int Sirene = 6;     //BUZZER
int Motor = 7;      //MOTOR




/////===================================================================== Inicializacao do sensores =============================================================================================================================
void setup()
{
Serial.begin(9600);
sgsm.begin(9600);
delay (1000);
Wire.begin();
Wire.beginTransmission(MPU6050_addr);
Wire.write(0x6B);
Wire.write(0);
Wire.endTransmission(true);
delay (1000);
pinMode(sensorMag, INPUT); //SENSOR MAGNETICO
pinMode(Sirene, OUTPUT);  //Sirene
pinMode(Motor, OUTPUT);   //MOTOR
irrecv.enableIRIn();
Serial.println("SISTEMA INICIALIZADO");  
}



/////=====================================================================  Inicio do Loop  =============================================================================================================================
void loop()
{
 //GPS();
 remote ();
 ReceberComando();

 }


/////=====================================================================   Remote controle  =============================================================================================================================

void remote (){
 if (irrecv.decode(&results))
{
Serial.println(results.value, HEX);
Serial.println("  ");
if (results.value== 0xFF6897)
{
//while (results.value==0xFF5AA5){
Serial.println("SISTEMA INACTIVO");
digitalWrite(Motor, LOW);
Serial.println("  ");
//Acelerometro();
delay(500);
}    
else
{
 while (results.value==0xFF10EF)
  {
    Serial.println("Sistema Armado");
    digitalWrite(Motor, HIGH);  
    delay(1000);
    Serial.println("  ");
    SensorMagnetico();
    delay(1000);
    Acelerometro();
    delay(1000);
  }
}
}

irrecv.resume(); // Receive the next value
delay(1000);
}



void SensorMagnetico()
{
int EstadosensorMag = digitalRead(sensorMag);
if (EstadosensorMag = digitalRead(sensorMag)== HIGH){
 Serial.println("A porta N. 1 da sua viatura foi aberta!");
 digitalWrite(Sirene, HIGH);
 delay(1000);
 mensagem2();
 delay(1000);
 enviolink();
 delay (1000);
}
else
 Serial.println("Portas Fechadas");
 digitalWrite(Sirene, LOW);
 delay(100);
 //digitalWrite(Motor, HIGH);
}


void Acelerometro(){
Wire.beginTransmission(MPU6050_addr);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU6050_addr,14,true);
AccX=Wire.read()<<8|Wire.read();
AccZ=Wire.read()<<8|Wire.read();
Serial.print("AccX = ");
Serial.print(AccX);
Serial.print(" || AccZ = ");
Serial.println(AccZ);
delay(1000);

if (AccZ > 2000){
digitalWrite(Sirene, HIGH);
delay(2000);
}
else  
digitalWrite(Sirene, LOW);
}

/////====================  coordenadas/ GPS=============================

 void GPS(){
 if(Serial.available()) {
   gps.encode(Serial.read());
 }
 if(gps.location.isUpdated()) {
   Serial.print("latitude:");
   latitude = gps.location.lat();
   Serial.print("longitude:");
   longitude = gps.location.lng();
   link = "www.google.com/maps/place/" + String(latitude, 6) + "," + String(longitude, 6) ;
   Serial.println(link);

 }
}


/////=========  Receber Comandos de texto + localizacao ======================
void ReceberComando()
{
Serial.begin(9600);
sgsm.begin(9600);
Serial.print("Inicializado o GSM e apagando SMS");
clear_SMS_Memory();
delay(3000);
sgsm.println("AT+CMGF=1");    
delay(3000);    
sgsm.println("AT+CNMI=2,2,0,0,0");    
memset(Buff, '\0', 250);// Initialize the string    BuffIndex=5;  }
delay (9000);

pinMode(Motor, OUTPUT); // controle do motor

while(1)
{          
 if(sgsm.available()>0)
 {              
  Buff[BuffIndex] = sgsm.read();                        
  if( (Buff[BuffIndex-2] == 'D') && (Buff[BuffIndex-1] == 'M') && (Buff[BuffIndex] == '1'))// Desativar Motor Agora
  {                    
  digitalWrite(Motor, HIGH);
  send2("Motor da sua viatura desligado! aguarde pelas coordenadas...");
  Serial.println ("Set sgsm Number");
  delay(10000);
  GPS();
  delay(10000);
  enviolink();
  Serial.println(" ");  

  }
  if( (Buff[BuffIndex-2] == 'A') && (Buff[BuffIndex-1] == 'R') && (Buff[BuffIndex] == 'M'))//Ativar Motor Agora
  {                    
  digitalWrite(Motor, LOW);
  digitalWrite (Sirene, LOW);
  send2("Motor Ativo....A viatura esta segura!, Aguarde a localizacao!");
  Serial.println ("Set sgsm Number");
  delay(1000);
  GPS();
  delay(1000);
  enviolink();
  Serial.println(" ");

   }

   if( (Buff[BuffIndex-2] == 'L') && (Buff[BuffIndex-1] == 'O') && (Buff[BuffIndex] == 'C'))//Retorna coordenadas
  {  
  send2("Buscado a localizacao actual!");
  GPS();
  delay(10000);
  enviolink();
  Serial.println(" ");                  
  delay(10000);

   }
       /// Pode se acrescentar mais condicoes
  BuffIndex++;
  if(BuffIndex>250)
   {                  
    BuffIndex=5;              
    }
 }
}
}

/////===============  Mensagens de Texto =======

void send2(String SMS)
 {
 Serial.println ("Sending Message");
 sgsm.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
 delay(1000);
 Serial.println ("Set sgsm Number");
 sgsm.println("AT+CMGS=\"" + number + "\"\r"); //Mobile phone number to send message
 delay(1000);
 sgsm.println(SMS);
 delay(100);
 sgsm.println((char)26);// ASCII code of CTRL+Z
 delay(1000);
 }


void mensagem()// mensagens das variaveis; e inicializacao do carro
{
 Serial.println ("Sending Message");
 sgsm.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
 delay(1000);
 Serial.println ("Set sgsm Number");
 sgsm.println("AT+CMGS=\""+ number + "\"\r"); //Mobile phone number to send message
 delay(1000);
 String SMS = "Sistema de Alarme habilitado";   //sgsm content
 sgsm.println(SMS);
 delay(100);
 sgsm.println((char)26);// ASCII code of CTRL+Z
 delay(1000);
}


void mensagem2()// mensagens das variaveis; e inicializacao do carro
{
 Serial.println ("Sending Message");
 sgsm.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
 delay(1000);
 Serial.println ("Set sgsm Number");
 sgsm.println("AT+CMGS=\""+ number + "\"\r"); //Mobile phone number to send message
 delay(1000);
 String SMS = "Alerta de intrução! Verifique a sua viatura.";   //sgsm content
 sgsm.println(SMS);
 delay(100);
 sgsm.println((char)26);// ASCII code of CTRL+Z
 delay(1000);
}


////=========================   Apaga mensagens no cartao  ===========
void clear_SMS_Memory()
{
unsigned short i = 0;
for (i = 0; i <= 30; i++)
{
sgsm.print("AT+CMGD=");
sgsm.println(i);
delay(100);
}
while (sgsm.available() > 0) sgsm.read();
}


/////=====================  Leitura  de Inputs do GSM ==========

void updateSerial()
{
 delay(500);
 while (Serial.available())
 {
 sgsm.write(Serial.read());//Forward what Serial received to Software Serial Port
 }
 while(sgsm.available())
 {
 Serial.write(sgsm.read());//Forward what Software Serial received to Serial Port
 }
}


/////======= localizacao ========================================
void enviolink()
{
  sgsm.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  sgsm.println("AT+CMGS=\"+25884xxxxxxx\"\r"); // Replace x with mobile number
  delay(1000);
  sgsm.println(link);// The SMS text you want to send
  delay(100);
  sgsm.println((char)26);// ASCII code of CTRL+Z
  delay(1000);  
}
4

Since you put "simultaneous" in quotes, I'm assuming you realize that one MCU can only do one thing at a time, but cleverly programmed, it can do small pieces of several things faster than you and I can perceive the difference. (I state this for completeness, for the benefit of readers who may not have thought this out yet.)

A couple of techniques will help you here.

One is what I call "maybedo" functions - functions you call frequently, that do or do not do something (depending on conditions such as time or input signals) but they do it quickly and return immediately. See my answer here for more explanation of "maybedo" functions.

Another and very important one is to avoid delay() calls. Try a timer library such as SimpleTimer. This lets your loop() function and those it calls, keep short. The SimpleTimer library entry is a "maybedo" for up to 10 timer-driven functions. All you have to do is call mytimers.run() frequently. Mostly it won't do much, but occasionally it will find one or more timers have expired and will call their associated functions for you. You just have to have set up the timers to call some simple - and again, short - functions to do something. And to be clear, we're talking about software-based timers, not the MCU's hardware timers. The library's work is based on the millis() function, but it automates that for you.

| improve this answer | |
  • For my apps, I created a class ArduinoObject. Each ArduinoObject has a setup() function and a loop() function, as well as an active boolean flag. My apps manage an array of ArduinoObjects. If an object's active flag is true, the app's loop calls its loop function on each pass through. If not, it isn't called at all. This makes it very easy to manage a whole bunch of what you call "MaybeDo" tasks dynamically. – Duncan C Dec 20 '19 at 0:29
  • The app uses a fixed-sized C array with enough elements for the max number of ArduinoObjects my app needs. If I need to add another task, I add an ArduinoObject to the array. If I want one of the objects to go to sleep, I set its active flag to false. The code that manages the array of ArduinoObject ignores NULL values, so I can set one of them to NULL if I'm completely done with it. The code that adds a new object searches for the first empty slot in the array. Each ArduinoObject is written to take very little time on each pass through its loop. – Duncan C Dec 20 '19 at 0:31
  • Interesting task structure - thanks! – JRobert Dec 20 '19 at 0:37
1

Without analyzing the complete code, the steps to go are:

  • Remove the delay function calls. These mostly delay the program in such a way that other parts are not executed in time or 'at the same time'.
  • Instead use the millis command and check again time stamps (of unsigned long int type) to reach the delays you need.
  • Create a state machine. This means in simple form that you use an enumeration (enum type) which can have one out of a set of values (like Stopped, Accelerating, Decelerating), for each 'states' you can define in your sketch.
  • Use these state machines and times to move from one state to another, and while changing state (or during a state) you can perform the actions you need.
| improve this answer | |
  • 1
    You have a minor typo in your answer. The function is millis() not milli. A newbie might not know that, and might fail to find the function with that typo in it. – Duncan C Dec 19 '19 at 22:49
  • @DuncanC Thanks for the notification, I updated my answer. I also added a reference to the page. – Michel Keijzers Dec 19 '19 at 22:56
0

As others have said, Arduinos are single-threaded, real mode computers. They only do one thing at a time. However, they do that one thing fast enough that you can make your apps switch between things rapidly enough that they keep multiple tasks running, like a circus clown keeping lots of plates spinning on sticks.

You have to use "roll-your-own" cooperative multitasking, where each time through your app's loop, you look for work to do on each of the tasks you're juggling. You have to make each pass through the loop fast so you don't miss things.

You should avoid the delay() function entirely if at all possible. The delay() and delayMicros() functions bring your app to a complete halt for the entire duration of the delay.

Search on "Arduino blink without delay" and look at the sample app that points to. It shows how to use millis() to manage timed actions without using delay(). You should apply that approach to everything you do.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.