GPS/GSM Трекер

Тема в разделе "Глядите, что я сделал", создана пользователем alexxx86, 25 фев 2014.

  1. alexxx86

    alexxx86 Гик

    Хочу представить свой первый серьёзный проект)))
    Первый потому что с arduino да и вообще микроконтроллерами познакомился пол года назад.
    Да и в электротехники познаний тоже очень мало. Так что сильно не судите если есть какие то недочёты.
    Ну а теперь к делу)))
    GPS/GSM трекер для автомобиля на базе atmega328(arduino UNO), sim900(GSM-шилд) и gps NEO-6M-0-001 924645513_488.jpg
    Готовое устройство планирую выполнить на печатной плате в одном корпусе, пока в процессе изготовления.
    Функционал трекера:
    Отправка GPS координат по SMS.
    Запрос баланса сим карты.
    Сохранение разрешённого номера в EEPROM.
    Обратный звонок для прослушивания салона автомобиля.
    Смена разрешённого номера.

    Ну а теперь по подробней:
    При звонке с Разрешённого номера в ответ приходит SMS с gps координатами которые
    считываются с gps модуля и переводятся в формат:
    N xx xx.xxxx - широта.
    E xx xx.xxxx - долгота.
    Time xx:xx:xx - время по гринвичу.
    Если после звонка с разрешённого номера приходит sms вида: "no data"
    Значит gps координаты ещё не определены.
    Если во время работы будет потеряна связь с gps спутниками то на звонок с разрешённого номера придет ответ с последними полученными координатами.
    Звонки с остальных номеров просто сбрасываются.

    !!!Sms обрабатываются с любого номера.

    При первом включении необходимо установить разрешённый номер. Для этого нужно отправить sms на номер сим карты установленной в трекере, следующего содержания: $ch.nomber#+7XXXXXXXXXX (где X 10 цифр номера). В ответ придёт SMS c текстом "Changed nomer complete!"
    При необходимости смены разрешённого номера, процедуру повторить.
    Если трекер по каким либо причинам будет выключен то при включении разрешённый номер будет прочтён из EEPROM.

    Для запроса баланса сим карты необходимо отправить sms следующего вида: $balans#
    (тестировалось на сим карте оператора beeline, для других операторов возможно понадобиться правка кода)
    В ответ придёт sms с балансом сим карты.

    Для возможности прослушивания салона автомобиля нужно отправить sms следующего содержания: $callback#
    В ответ будет совершён голосовой вызов.
    Код (Text):
    // GPS/GSM трекер.
    #include <EEPROM.h>
    #include <AltSoftSerial.h>
    AltSoftSerial gpsSerial;
    String currStr = "";//Строка содержит текущую строку, полученую от сим модуля.
    String nomber_Phone = "";//Строка содержит номер телефона на который отправляються GPS координаты, далее Разрешенный номер.
    String dat2 = "no data";//Текст строки отпровляеться если GPS координат ещё нет.
    String dat;//Строка содержит GPS координаты.
    String complete = "Changed nomber complete!";//Текст строки отпровляеться при смене Разрешенного номера.
    char data;//Содержит символ полученый от сим модуля.
    byte char_A = 40;
    boolean gps = true;
    int gps_on = A0;
    void setup()
    {
      pinMode(gps_on, OUTPUT);
      pinMode(led2, OUTPUT);
     
      analogWrite(gps_on, 255);//
      delay(800);              //
      analogWrite(gps_on, 0);  //Включение сим модуля.
      delay(5000);            //
     
      Serial.begin(19200);
      gpsSerial.begin(9600);
     
      for(byte i=0; i<12; i++)  //Чтение Разрешённого номера из EEPROM
        {
          data = EEPROM.read(i);
          nomber_Phone += data;
        }
      delay(100);
      Serial.println("AT");//Устанавливаем связь с сим модулем, для соглосования скорости передачи.
      delay(500);
      Serial.println("AT+CMGDA=\"DEL ALL\"");//Удаляем всё SMS которые могут содержаться на сим карте.
    }

    void loop()
    {
      if(Serial.available()>0)
      {
        read_GSM();.
      }
      read_GPS();
    }
    //Функция данных полученых от сим модуля.
    void read_GSM()
    {
      currStr = "";
      while(Serial.available()>0)
      {
        data = Serial.read();
        delay(10);
        if ('\r' == data)
        {
          if(!currStr.compareTo("RING"))//Если текущая строка RING, значит едёт входящий звонок.
          {
            ring_GSM();  
          }
          else
          {
            if (currStr.startsWith("+CMT")) //Или если строка начинаеться c +CMT, значит пришло SMS
            {
              read_Message();
              Serial.println("AT+CMGDA=\"DEL ALL\"");//Удоляем всё SMS чтоб не накапливать их.
            }
          }
          currStr = "";
        }
        else if ('\n' != data)
        {
          currStr += data;
        }
      }
    }

    //Функция обработки входящего звонка.
    void ring_GSM()
    {
      boolean ring = true;
      currStr = "";
      delay(10);
      while(ring)
      {
        data = Serial.read();
        if (data == '"')
        {
          data = Serial.read();
          while (data != '"')
          {
            currStr += data;
            data = Serial.read();
          }
          if (currStr == nomber_Phone)//Если номер совподает с номером в строке "nomber_Phone"
          {
            delay(1000);
            Serial.println("ATHO");// Тогда сбрасываем звонок
            delay(100);
            send_Message(&dat2);// И вызываем функци отправки SMS и передаём ей адрес строки содержащию GPS координаты.
            return;
          }
          else //Если номер не совподает
          {
            Serial.println("ATHO");// Просто сбрасываем звонок.
            return;
          }
        }
      }
    }
    //Функция отправки SMS.
    void send_Message(String *message) //Функция принимает адрес строки с текстом SMS.
    {
      delay(500);
      Serial.print("AT + CMGS = \"");
      Serial.print(nomber_Phone);
      Serial.println('"');
      delay(500);
      Serial.println(*message);
      delay(500);
      Serial.print((char)26);
    }
    //Функция читает GPS координаты и преобразует в формат:
    //N xx xx.xxxx - широта.
    //E xx xx.xxxx - долгота.
    //Time xx:xx:xx - время по гринвичу.
    void read_GPS()
    {
      gps = true;
      dat = "";
      while (gps)
      {
        if (gpsSerial.available()>0)
        {
          data = gpsSerial.read();
          if (data == 'L')
          {
            while (data != '\r')
            {
              dat += data;
              delay(2);
              data = gpsSerial.read();
            }
            gps = false;
            if (dat.indexOf('A') == char_A)
            {
              delay(5);
              dat2 = "N ";
              for(byte i=3; i<5; i++)
              {
                dat2 += dat.charAt(i);
              }
              dat2 += ' ';
              for(byte i=5; i<13; i++)
              {
                dat2 += dat.charAt(i);
              }
              dat2 += "\nE ";
              for(byte i=17; i<19; i++)
              {
                dat2 += dat.charAt(i);
              }
              dat2 += ' ';
              for(byte i=19; i<27; i++)
              {
                dat2 += dat.charAt(i);
              }
              delay(5);
              dat2 += "\nTime ";
              for(byte i=30; i<32; i++)
              {
                dat2 += dat.charAt(i);
              }
              dat2 += ':';
              for(byte i=32; i<34; i++)
              {
                dat2 += dat.charAt(i);
              }
              dat2 += ':';
              for(byte i=34; i<36; i++)
              {
                dat2 += dat.charAt(i);
              }
            }      
          }
        }
      }
    }
    //Функция чтения SMS.
    void read_Message()
    {
      currStr = "";
      while(Serial.available()>0)
      {
        data = Serial.read();
        if(data == '$')
        {
          while(data != '#')
          {
            data = Serial.read();
            currStr += data;
          }
          if(!currStr.compareTo("balans#"))//Запрос и отправка баланса сим карты
          {
            currStr = "";
            Serial.println("ATD#100#;");//USSD запрос баланса для beeline
            delay(5000);
            while(Serial.available()>0)
            {
              data = Serial.read();
              if(data == '"')
              {
                data = Serial.read();
                while(data != 'B')
                {
                  currStr += data;
                  data = Serial.read();
                }
                send_Message(&currStr);
                return;
              }
            }
          }
          else if(!currStr.compareTo("callback#"))//Звонок на разрешённый номер.
          {
            Serial.print("ATD");
            delay(100);
            Serial.print(nomber_Phone);
            delay(100);
            Serial.println(";");
            return;
          }
          else if(!currStr.compareTo("ch.nomber#"))//Смена Разрешённого номера и сохранение его в EEPROM.
          {
            currStr = "";
            data = Serial.read();
            if(data == '+')
            {
              for(byte i = 0; i < 12; i++)
              {
                EEPROM.write(i, data);
                currStr += data;
                data = Serial.read();
              }
              nomber_Phone = currStr;//Сохранение нового Разрешённого номера.
              send_Message(&complete);//Отправка SMS потверждающая смену Разрешённого номера.
              return;
            }
          }
        }
      }
    }
     
    zsm, BGreen, Вячеслав и 2 другим нравится это.
  2. Ganz7710

    Ganz7710 Нуб

    Доброго времени суток, помогите пожалуйста,пробую включить GY-GPS6MV2 vcc-5v, gnd-0 земля. Светодиод не загорается? или и не должен? Спасибо
     
  3. alexxx86

    alexxx86 Гик

    А на нём один светодиод?
    Если судить по фото то вроде один, он скорей всего мигает когда установлена связь со спутниками. Включите и подождите некоторое время.
     
    Последнее редактирование: 23 мар 2014
  4. alexxx86

    alexxx86 Гик

    Ну вот наконец то я доделал трекер))) Всё разместилось в довольно таки не большом корпусе.
    Пришлось конечно повозится но результат того стоил.
    ramdisk-crop_72706474_eA8uYz.jpg ramdisk-crop_72706587_irtUy.jpg ramdisk-crop_72706629_cjdj1.jpg ramdisk-crop_72706676_Msll1M.jpg ramdisk-crop_72706709_BLprFq.jpg
    И плюс ко всему сделал небольшое приложение для смартфона. При входящем смс с трекера с координатами, открывается браузер с картой и показывает текущие местоположение.
    Screenshot_2014-03-23-09-24-32.png Screenshot_2014-03-23-09-25-11.png Screenshot_2014-03-23-09-25-21.png
    Если кто то решит воспользоваться приложением и будут какие то баги, то пишите. Так как под андроид писал в первый раз.
    Ссылка на приложение:https://drive.google.com/file/d/0B5NlQHFrfyvzbTJ6Q0QxQ3EwR28/edit?usp=sharing
    Чуть позже скину схему всего устройства, вдруг кому пригодиться.
     
    OldKryptos, alp69, Infernium и 6 другим нравится это.
  5. rushaks

    rushaks Нуб

    Интересно было бы схему устройства посмотреть). Вы под gsm сами плату паяли или такая готовая была?
     
  6. alexxx86

    alexxx86 Гик

    К
    Ксожалению схемы не осталось как и разводки платы, винчестер на ноутбуке приказал долго жить (((
    Схему разводки gsm модема брал в основном из документации на него, благо там всё подробно расписано.
    Плату делал сам с нуля.
    Код кстати притерпел большие изменения как и программа для телефона, но пока руки не дошли выложить сюда))))
     
  7. rushaks

    rushaks Нуб

    Буду признателен, если Вы обновите инфу с кодом и программой)
     
  8. alexxx86

    alexxx86 Гик

    Хорошо! Постараюсь в ближайшие время всё выложить.
     
  9. alexxx86

    alexxx86 Гик

    Как обещал обновлённый код и программа для телефона.
    В процессе эксплуатации были замечены не частые спонтанные зависания и выключения модема. Поэтому было решено добавить watchdog и функции опроса модема и его сброса.
    Код правда не очень аккуратный, к сожалению нет времени довести до ума. И ещё надо болие тщательно проверить функцию сброса watchdog. Возможно где то лишние вызовы её.
    Что касаемо программы, карта теперь открывается в самом приложении а не в браузере, входящие сообщения от трекера не отображаються в строке уведомлений и отсутствуют в списке входящих, отображаються только в самом приложение. Все сообщения от трекера сохраняются в приложении, с отметкой о времени и дате прихода. Их можно удалять по отдельности или все сразу. Сохранённые сообщения с координатами также можно просматривать на карте.
    Вообщем и целом трекер и программа работают отлично, но код конечно далёк от идеала))))))

    Приложение: https://drive.google.com/file/d/0B5NlQHFrfyvzeW1ZbTNlNnJLOHM/edit?usp=sharing

    Код (Text):
    // GPS/GSM трекер.
    //Добавлена провекра включения SIM модуля и watchdog.
    //Fuses-- Lock_Byte-3F, High_Byte-D7, Low_Byte-FF, Extended_Byte-05
    #include <avr/wdt.h>
    #include <EEPROM.h>
    #include <AltSoftSerial.h>
    AltSoftSerial gpsSerial;
    String currStr = "";//Строка содержит текущую строку, полученую от сим модуля.
    String nomber_Phone = "";//Строка содержит номер телефона на который отправляються GPS координаты, далее Разрешенный номер.
    String dat2 = "no data";//Текст строки отпровляеться если GPS координат ещё нет.
    String dat;//Строка содержит GPS координаты.
    String complete = "Changed nomber complete!";//Текст строки отпровляеться при смене Разрешенного номера.
    char data;//Содержит символ полученый от сим модуля.
    byte char_A = 40;
    boolean gps = true;
    int gsm_on = A0;
    long previousMillis = 0;
    long interval = 30000;
    int reset = 5;
    void setup()
    {
      wdt_disable();
      wdt_enable(WDTO_8S);
      pinMode(reset, OUTPUT);
      digitalWrite(reset, LOW);
      pinMode(gsm_on, OUTPUT);
      Serial.begin(9600);
      gpsSerial.begin(9600);
     
      if (testGsmOn()==1){ //Если модем выключен, то включаем его.
        gsmOn();
      }
     
      for(byte i=0; i<12; i++){  //Чтение Разрешённого номера из EEPROM
          data = EEPROM.read(i);
          nomber_Phone += data;
        }
      Serial.println("AT+CMGDA=\"DEL ALL\"");//Удаляем всё SMS которые могут содержаться на сим карте.
    }

    void loop()
    {
      wdt_reset();
      unsigned long currentMillis = millis();
      if(currentMillis - previousMillis > interval) { //Каждые пол минуты проверяем состояние модема.
        previousMillis = currentMillis;
        if (testGsmOn()==1){ // Если связи с модемом нет пробуем сначало перезагрузить его, если это не помогло то пытаемся включить его.
          Reset();
          delay(3000);
          if (testGsmOn()==1){
            gsmOn();
          }
        }
      }
      if(Serial.available()>0)
      {
        read_GSM();
      }
      read_GPS();
    }
    //Функция данных полученых от сим модуля.
    void read_GSM()
    {
      currStr = "";
      while(Serial.available()>0)
      {
        data = Serial.read();
        delay(10);
        if ('\r' == data)
        {
          if(!currStr.compareTo("RING"))//Если текущая строка RING, значит едёт входящий звонок.
          {
            ring_GSM();
          }
          else
          {
            if (currStr.startsWith("+CMT")) //Или если строка начинаеться c +CMT, значит пришло SMS
            {
              read_Message();
              Serial.println("AT+CMGDA=\"DEL ALL\"");//Удоляем всё SMS чтоб не накапливать их.
            }
          }
          currStr = "";
        }
        else if ('\n' != data)
        {
          currStr += data;
        }
      }
    }

    //Функция обработки входящего звонка.
    void ring_GSM()
    {
      boolean ring = true;
      currStr = "";
      delay(10);
      while(ring)
      {
        data = Serial.read();
        if (data == '"')
        {
          data = Serial.read();
          while (data != '"')
          {
            currStr += data;
            data = Serial.read();
          }
          if (currStr == nomber_Phone)//Если номер совподает с номером в строке "nomber_Phone"
          {
            delay(1000);
            Serial.println("ATHO");// Тогда сбрасываем звонок
            delay(100);
            send_Message(&dat2);// И вызываем функци отправки SMS и передаём ей адрес строки содержащию GPS координаты.
            return;
          }
          else //Если номер не совподает
          {
            Serial.println("ATHO");// Просто сбрасываем звонок.
            return;
          }
        }
      }
    }
    //Функция отправки SMS.
    void send_Message(String *message) //Функция принимает адрес строки с текстом SMS.
    {
      wdt_reset();
      delay(500);
      Serial.print("AT + CMGS = \"");
      Serial.print(nomber_Phone);
      Serial.println('"');
      delay(500);
      Serial.println(*message);
      delay(500);
      Serial.print((char)26);
      delay(5000);
      wdt_reset();
      delay(5000);
    }

    //Функция чтения SMS.
    void read_Message()
    {
      currStr = "";
      while(Serial.available()>0)
      {
        data = Serial.read();
        if(data == '$')
        {
          while(data != '#')
          {
            data = Serial.read();
            currStr += data;
          }
          wdt_reset();
          if(!currStr.compareTo("balans#"))//Запрос и отправка баланса сим карты
          {
            currStr = "";
            Serial.println("ATD#100#;");//USSD запрос баланса для beeline
            delay(5000);
            wdt_reset();
            while(Serial.available()>0)
            {
              data = Serial.read();
              if(data == '"')
              {
                data = Serial.read();
                while(data != 'B')
                {
                  currStr += data;
                  data = Serial.read();
                }
                send_Message(&currStr);
                return;
              }
            }
          }
          else if(!currStr.compareTo("callback#"))//Звонок на разрешённый номер.
          {
            Serial.print("ATD");
            delay(100);
            Serial.print(nomber_Phone);
            delay(100);
            Serial.println(";");
            return;
          }
          else if(!currStr.compareTo("ch.nomber#"))//Смена Разрешённого номера и сохранение его в EEPROM.
          {
            currStr = "";
            data = Serial.read();
            if(data == '+')
            {
              for(byte i = 0; i < 12; i++)
              {
                EEPROM.write(i, data);
                currStr += data;
                data = Serial.read();
              }
              nomber_Phone = currStr;//Сохранение нового Разрешённого номера.
              send_Message(&complete);//Отправка SMS потверждающая смену Разрешённого номера.
              return;
            }
          }
        }
      }
    }

    void gsmOn(){ //Функция включения модема.
        analogWrite(gsm_on, 255);
        delay(800);
        analogWrite(gsm_on, 0);
    }

    void Reset(){ //Функция сброса модема.
      digitalWrite(reset, HIGH);
      delay(100);
      digitalWrite(reset, LOW);
    }

    int testGsmOn(){ //Функция опроса модема. Возвращает "0" если связь с модемом есть или "1" если нет.
        Serial.println("AT");
        delay(100);
        Serial.println("AT");
        delay(500);
        if(Serial.available()>0){
            return 0;
        } else {
            return 1;
        }
    }

    //Функция читает GPS координаты и преобразует в формат:
    //N xx xx.xxxx - широта.
    //E xx xx.xxxx - долгота.
    //Time xx:xx:xx - время по гринвичу.
    void read_GPS()
    {
      gps = true;
      dat = "";
      while (gps)
      {
        if (gpsSerial.available()>0)
        {
          data = gpsSerial.read();
          if (data == 'L')
          {
            while (data != '\r')
            {
              dat += data;
              delay(2);
              data = gpsSerial.read();
            }
            wdt_reset();
            gps = false;
            if (dat.indexOf('A') == char_A)
            {
              wdt_reset();
              delay(5);
              dat2 = "N ";
              for(byte i=3; i<5; i++)
              {
                dat2 += dat.charAt(i);
              }
              dat2 += ' ';
              for(byte i=5; i<13; i++)
              {
                dat2 += dat.charAt(i);
              }
              dat2 += "\nE ";
              for(byte i=17; i<19; i++)
              {
                dat2 += dat.charAt(i);
              }
              dat2 += ' ';
              for(byte i=19; i<27; i++)
              {
                dat2 += dat.charAt(i);
              }
              delay(5);
              dat2 += "\nTime ";
              for(byte i=30; i<32; i++)
              {
                dat2 += dat.charAt(i);
              }
              dat2 += ':';
              for(byte i=32; i<34; i++)
              {
                dat2 += dat.charAt(i);
              }
              dat2 += ':';
              for(byte i=34; i<36; i++)
              {
                dat2 += dat.charAt(i);
              }
            }    
          }
        }
      }
    }
     
    alp69, Vladis_a, rico и ещё 1-му нравится это.
  10. rushaks

    rushaks Нуб

    Огромное Вам спасибо :)
     
  11. valeraba

    valeraba Нерд

    Здоровский проект, прям настоящий самоделкин. Платы без зелёнки так дешевле?
    А корпус где-то готовый брали? Потребление по току не смотрели? Запитаться от батареек реально?
     
  12. alexxx86

    alexxx86 Гик

    Спасибо!
    Корпус в чип и дипе брал, под него уже и плату подганял.
    От акума можно спокойно запитать, но тогда уже лучше брать другой модем, например SIM908, он со встроенным контролером заряда акб, и GPS приёмником.
    Точных замеров не проводил, где-то в среднем около 80 mA получалось.
     
    Последнее редактирование: 31 окт 2014
  13. Максим B

    Максим B Гуру

  14. Максим B

    Максим B Гуру

    Схему бы проекта =)
     
  15. alexxx86

    alexxx86 Гик

    Вот к сожалению схемы нет ((( Но если будут вопросы, задавайте, помогу с удовольствием.
     
    qMax нравится это.
  16. Спасибо! Классный проект.
     
    alexxx86 нравится это.
  17. Takumi

    Takumi Нуб

    Хм:
    --------
    Уважаемые партнёры! Компания SIMCom Wireless Solutions объявила о намерении снять с производства GSM/GPRS + GPS модуль SIM908.
    Заказы на модуль SIM908 будут приниматься до 15 декабря текущего года, отгрузки будут осуществляться по март 2015 года включительно.
    --------
    Отсюда:
    http://www.mt-system.ru/news/bespro...tie-s-proizvodstva-gsmgprs-gps-modulja-sim908
     
  18. Может это подойдет потом? http://www.electronshik.ru/item/mlg0208-01-293069
     
  19. olegtur77

    olegtur77 Нерд

    Если схемы нет, можно сделать фото покрупнее, с обеих сторон?
     
  20. alexxx86

    alexxx86 Гик

    Фото сложно сделать, так как прибор стоит в автомобиле. Что именно вас интересует?