Как подключить 2 модуля по программному UART на Arduino nano?

Всем привет! Хочу сделать GPS трекер с отправкой данных на сервер через модуль SIM800L.
Столкнулся с проблемой чтения данных с модулей. И GPS модуль и SIM800L работают на скорости 9600 и из-за этого возникают ошибки при чтении и отправке команд.
Пробовал использовать .end(), но не помогает - в ответ ничего не приходит.
Использую Программный UART для обеих модулей, т.к. аппаратный нужен для монитор порта.
Как быть в такой ситуации?
Написал простенький код для чтения “сырых” данных с GPS модуля. Все бы ничего, но когда использую .end(), то ничего в ответ уже не приходит, даже после обратного подключения.
Код:

#include <SoftwareSerial.h>

SoftwareSerial ss(2, 3);

unsigned long timer = millis();


void setup()
{
  Serial.begin(9600);
}

void loop()
{
  if (millis() - timer >= 1000) {
    timer = millis();
    ss.begin(9600);
    
    String nmeaMessage = "";
    char incomingByte = ss.read();
    while (ss.available() > 0 && incomingByte != '\n') {
      nmeaMessage += incomingByte;
      incomingByte = ss.read();
    }
  
    Serial.println(nmeaMessage);

    ss.end();
  }
}

Использовать два разных объекта для GPS и SIM800 не предлагать?

В 17 строчке. Это лишь пример. Думал закрывать соединение после завершения операции, а потом когда надо обратно соединить. Но к сожалению обратно уже не соединяется. Да и при первом запуске ничего не приходит. Я так понял, begin нельзя ставить в loop()

Я и использую два разных объекта, но не работает. Видимо они как-то мешают друг-другу

Так на разных пинах используй их.

Я так и подключил. Код выше это лишь пример, где используется только GPS модуль

Значит покажи код (пример) как ты с двумя объектами работаешь.

Так приведите актуальный код и актуальную схему подключения и прекратите сексуальное насилие над мозгами пытающихся Вам помочь!

1 лайк
#include <SoftwareSerial.h>
#include <TinyGPS.h>

TinyGPS gps;

SoftwareSerial ss(2, 3);
SoftwareSerial sim(4, 5);

unsigned long GPSdata = millis();
unsigned long timeSendData = millis();
String SendData;


void setup()
{
  Serial.begin(9600);
  sim.begin(9600);
  ss.begin(9600);

  sendATCommand("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"");
  sendATCommand("AT+SAPBR=3,1,\"APN\",\"internet\"");
  sendATCommand("AT+SAPBR=1,1");
}

void loop()
{
  if (millis() - GPSdata >= 1000) {
    GPSdata = millis();
    
    bool newData = false;
    unsigned long chars;
    
    for (unsigned long start = millis(); millis() - start < 1000;)
    {
      while (ss.available())
      {
        char c = ss.read();
        if (gps.encode(c)) {
          newData = true;
        }
      }
    }
    
    if (newData)
    {
      String gpslat, gpslon, gpsSats, gpsHdop;
      long flat, flon;
      unsigned long age;
      
      gps.get_position(&flat, &flon, &age);

      SendData += "{";
      
      String _lat = String(flat);
      String lat1 = _lat.substring(0, 2); 
      String lat2 = _lat.substring(2, 8); 
      gpslat = lat1+"."+lat2;
      Serial.print("GPS lat=");
      Serial.print(gpslat);
      SendData += gpslat + ",";

      String _lon = String(flon);
      String lon1 = _lon.substring(0, 2); 
      String lon2 = _lon.substring(2, 8); 
      gpslon = lon1+"."+lon2;
      Serial.print(" lon=");
      Serial.print(gpslon);
      SendData += gpslon + "}";

      Serial.println();
    }
  }


  if (millis() - timeSendData >= 5000) {
    timeSendData = millis();

    sendATCommand("AT+HTTPINIT");
    sendATCommand("AT+HTTPPARA=\"CID\",1"); 
    sendATCommand("AT+HTTPPARA=\"URL\",\"http://site.ru/send.php?data="+ SendData +"\"");
    Serial.println(SendData);
    SendData = "";
    sendATCommand("AT+HTTPACTION=0"); 
    sendATCommand("AT+HTTPREAD");   
    sendATCommand("AT+HTTPTERM"); 
  }
}


String sendATCommand(String cmd) {
  sim.println(cmd);
  Serial.println(cmd);

  while (!sim.available()) {};
  
  if (sim.available()) {
    Serial.println(sim.readString());
  }
}

Так, и в чем проявляются коллизии?
А, вижу. Тебе нужно от циклов избавляться и делать код не блокирующим. Евгений Петрович: если в настроении ( :slight_smile: ) лучше подскажет.

И? Схема где?

А в коде … как Вы переключаетесь с одного софтсериала на другой? Где вызов метода listen?

несовместимые желания, не мучайтесь, смените МК, хотя бы на ESP32.

2 лайка

у меня 328PB на двух хардварных портах и одном софтварном нормально работают, но не с SIM800

Переделал код с применением listen, но все равно не работает:

#include <SoftwareSerial.h>
#include <TinyGPS.h>

TinyGPS gps;

SoftwareSerial ss(2, 3);
SoftwareSerial sim(4, 5);

unsigned long GPSdata = millis();
unsigned long timeSendData = millis();
String SendData;


void setup()
{
  Serial.begin(9600);
  sim.begin(9600);
  ss.begin(9600);

  sendATCommand("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"");
  sendATCommand("AT+SAPBR=3,1,\"APN\",\"internet\"");
  sendATCommand("AT+SAPBR=1,1");
}

void loop()
{
  if (millis() - GPSdata >= 1000) {
    if (!ss.isListening()) {
      Serial.println("--- Listen 'GPS' ---");
      ss.listen();
    }
    GPSdata = millis();
    
    bool newData = false;
    unsigned long chars;
    
    for (unsigned long start = millis(); millis() - start < 1000;)
    {
      while (ss.available())
      {
        char c = ss.read();
        if (gps.encode(c)) {
          newData = true;
        }
      }
    }
    
    if (newData)
    {
      String gpslat, gpslon, gpsSats, gpsHdop;
      long flat, flon;
      unsigned long age;
      
      gps.get_position(&flat, &flon, &age);

      SendData += "{";
      
      String _lat = String(flat);
      String lat1 = _lat.substring(0, 2); 
      String lat2 = _lat.substring(2, 8); 
      gpslat = lat1+"."+lat2;
      Serial.print("GPS lat=");
      Serial.print(gpslat);
      SendData += gpslat + ",";

      String _lon = String(flon);
      String lon1 = _lon.substring(0, 2); 
      String lon2 = _lon.substring(2, 8); 
      gpslon = lon1+"."+lon2;
      Serial.print(" lon=");
      Serial.print(gpslon);
      SendData += gpslon + "}";

      Serial.println();
    }
  }


  if (millis() - timeSendData >= 5000) {
    timeSendData = millis();

    sendATCommand("AT+HTTPINIT");
    sendATCommand("AT+HTTPPARA=\"CID\",1"); 
    sendATCommand("AT+HTTPPARA=\"URL\",\"http://site.ru/send.php?data="+ SendData +"\"");
    Serial.println(SendData);
    SendData = "";
    sendATCommand("AT+HTTPACTION=0"); 
    sendATCommand("AT+HTTPREAD");   
    sendATCommand("AT+HTTPTERM"); 
  }
}


String sendATCommand(String cmd) {
  if (!sim.isListening()) {
    Serial.println("--- Listen 'Sim' ---");
    sim.listen();
  }
  
  sim.println(cmd);

  while (!sim.available()) {};
  
  if (sim.available()) {
    Serial.println(sim.readString());
  }

  delay(100);
}

тебе прямо сказали - И НЕ БУДЕТ, выбирай контроллер под задачу

Да не только в задаче дело, работа с sim800 без анализов ответов на at команды, изначально гиблое дело, нужен подход менять.
ЗЫ. Сейчас как раз в проекте трекера на этом модеме, http unit команда норм работает…раз 20 а потом ошибка, приходиться логику переделывать

Да, неужели?

Мне весьма жаль, но … я Вам написал, что нужен не только код, но и схема подключения. Вы этого не восприняли. Тогда я повторил это во второй раз. Вы опять наплевали не мою просьбу. Ваше право, конечно, но … ничего, если я тоже плюну на Ваши проблемы и займусь своими делами? Или Вы ожидали, что я стану на колени и буду умолять Вас таки сделать то, что нужно для решения Вашей же проблемы?

Всего доброго!

А по коду не понятно?

RX gps → D3
TX gps → D4

RX sim → D5
TX sim → D4

Питание GPS от ардуино:
GND → GND
VCC → 5V

Питание sim от внешнего БП на 2А + конденсатор на 2200

не хами…
нет не понятно, в коде одно, тут другое, в схеме может быть третье.
или опять, так было раньше сейчас по другому?

1 лайк

Мне - нет! А Вам? По просьбе привести схему непонятно, что она для чего-то нужна?

До свиданья.

2 лайка