Arduino Nano+SIM800L+ESP01S+OLED 1306 совместная работа и команды AT

MashukovAntonVictorovich

✩✩✩✩✩✩✩
31 Окт 2021
16
0
39
Всем спасибо кто хоть чем-то поможет, либо даст дельный совет. Администратору просьба не ругать, если пишу не туда, просьба перекинуть в нужную тему либо форум.
Сам вопрос в следующем, перерыв кучу макулатуры, сайтов, а так же сайт "гайвера" ответа на свой вопрос так и не нашел. Закл-ся он в следующем.
Есть плата Arduino Nano к ней подключен модуль SIM800L, дисплей OLED1306 128x32 + ESP01s. Есть первый вопрос, как сделать так, чтобы с ардуино послать команду AT например подключения к сети, а на дисплей вывести например ip адрес и статус подключения. Сразу выкладываю свой скетч, если можно добавьте в него строки как нужно или как должно быть, спасибо большое. Буду далее спрашивать ваших советов и показывать результаты работы, есть глобальная задумка мега умной системы с голосовыми и так далее командами.
rabota1:
#include <SoftwareSerial.h>
#include <Wire.h>
//#include <SPI.h>

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (A4 = SDA, A5 = SCL)
// Reset pin # (or -1 если не имеет pin сброса)
#define OLED_RESET -1 // Если ваш OLED дисплей не имеет pin сброса, вы должны установить переменную OLED_RESET в значение -1, как сделано у меня
//See datasheet for Address
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


#define rxPin 8
#define txPin 9
SoftwareSerial sim800L(rxPin,txPin);


String network, battery;

void setup() {
  //Begin serial communication with Serial Monitor
  Serial.begin(115200);

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }

  // the library initializes this with an Adafruit splash screen.
  display.display();
  delay(2000); // Пауза 2 секунды

  // Очистка буфера дисплея
  display.clearDisplay();

 
  //Устанавливаем связь Arduino и SIM800L
  sim800L.begin(9600);
  sim800L.println("AT");
  delay(1000);
  sim800L.println("AT+CSCS=PCCP936"); // установка кодировки ввода/вывода текста.
  delay(1000);
  sim800L.println("AT+CMGF=1");
  delay(1000);
}

void loop() {

      //показатель сети устанавливаем на 0 network = "0";
      //показатель заряда батареи устанавливаем на 0 battery = "0";

      network = get_network();
      battery = get_battery();
      
      display_battery();
      display_network_battery();

      
}

int get_network()
{
  String buff;
  //buff = "+CSQ: 16,0";
  unsigned int result, index1, index2, timeout=0;

  sim800L.println("AT+CSQ"); 
  for (unsigned long start = millis(); millis() - start < 2000;){
    while(sim800L.available())
    {
      buff = sim800L.readString();
      timeout = 1;
      break;
    }
  }

  if(timeout == 0)
    { return 0; }
    
  Serial.println(buff);
 
  //String network_status;
  //_____________________________________________________
  //Remove sent "AT Command" from the response string.
  index1 = buff.indexOf("\r");
  buff.remove(0, index1+2);
  buff.trim();
  //_____________________________________________________
 
  //_____________________________________________________
 
    index1 = buff.indexOf(":");
    index2 = buff.indexOf(",");
    buff = buff.substring(index1+1, index2);
    buff.trim();
    result = buff.toInt();

    if(result == 99)
    {
      //сигнал неизвестен или не обнаружен
      return 0;
    }
    else if(result >= 2 && result <= 9)
    {
      //Signal Quality = Marginal
      return 20;
    }
    else if(result >= 10 && result <= 14)
    {
      //Signal Quality = OK
      return 40;
    }
    else if(result >= 15 && result <= 19)
    {
      //Signal Quality = Good
      return 60;
    }
    else if(result >= 20 && result <= 31)
    {
      //Signal Quality = Excellent
      return 99;
    }
    
  return 0;
}

int get_battery()
{
  String buff;
  //buff = "+CBC: 0,99,4190";
  unsigned int index1, index2, timeout=0;
    
  sim800L.println("AT+CBC"); 
  for (unsigned long start = millis(); millis() - start < 2000;){
    while(sim800L.available())
    {
      buff = sim800L.readString();
      timeout = 1;
      break;
    }
  }

  if(timeout == 0)
    { return 0; }
    
  Serial.println(buff);
 
  //String network_status;
  //_____________________________________________________
  //Remove sent "AT Command" from the response string.
  index1 = buff.indexOf("\r");
  buff.remove(0, index1+2);
  buff.trim();
  //_____________________________________________________
 
  //_____________________________________________________
 
    //search for first comma (,) = index1
    //search for 2nd comma (,) = index2
    index1 = buff.indexOf(",");
    index2 = buff.indexOf(",", index1+1);
    String result = buff.substring(index1+1, index2);
    result.trim();
    
    Serial.println(result);
    //buff.remove(0, index+2);
  return result.toInt();
}

void display_battery()
{

}

void display_network_battery()
{
  display.clearDisplay();

  display.drawRect(109, 1, 15, 8, WHITE);    //Первый кубик рисования батарейк
  display.drawRect(123, 2, 3, 6, WHITE);     //Второй кубик рисования батарейки
  display.fillRect(111, 3, (int)(1.5 * (battery.toInt()) / 10), 4, WHITE);
 
  display.drawLine(1, 1, 8, 1, WHITE);        //Верхняя палочка значка связи
  display.drawLine(1, 1, 5, 5, WHITE);
  display.drawLine(9, 1, 5, 5, WHITE);
  display.fillRect(5, 1, 1, 8, WHITE);        //Центральная палочка значка связи
  int net = network.toInt() / 20;
  int x1 = 8, y1 = 7, x2 = 2, y2 = 2;
  for (int i = 1; i <= net; i++)
  {
    display.fillRect(x1, y1, x2, y2, WHITE);
    x1 += 3; // Уменьшает или увеличивает расстояние между палочками качества сигнала
    y1 -= 2;
    y2 += 5;
    y2 -= 3;
  }
// display.setTextSize(1);
// display.setTextColor(WHITE);
// display.setCursor(40, 1);
// display.print(network);
// display.setTextSize(1);
// display.setCursor(53, 1);
// display.println("%");
 display.display();
// delay(400);
}
 

Вложения

Старик Похабыч

★★★★★★★
14 Авг 2019
4,263
1,301
Москва
Мой совет. меняйте сразу нану на мегу. Сразу уберете кучу проблем. у меги есть 3 аппаратных UART, 1 на отладку, 1 на SIM , 1 на ESP. Памяти у нее тоже побольше будет.
Остальное не существенно
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,263
1,301
Москва
Ну ок. А "например команда АТ подклчюения к сети" как задается ? Если она прописана в коде, то после успеха надо прочитать IP. А если задается через терминал, то тут сложнее. Нужен будет список команд для распознавания и на каждую запускать свою функцию обработки
 

PiratFox

★★★★★✩✩
13 Фев 2020
1,706
474
@MashukovAntonVictorovich, а не лучше вместо ардуины заюзать какой-нить Wemos или NodeMCU. У них вычислительная мощность-то поболее будет, чем в ардуине, да и необходимость в одном UART отпадёт. Впрочем, Вам виднее. ;)
 

MashukovAntonVictorovich

✩✩✩✩✩✩✩
31 Окт 2021
16
0
39
Либо подскажите как отправить AT команды от Arduino через SoftwareSerial в ESP01 и если она ответила что-то просто печатаем в монитор порта
 

bort707

★★★★★★✩
21 Сен 2020
3,056
910
Либо подскажите как отправить AT команды от Arduino через SoftwareSerial в ESP01 и если она ответила что-то просто печатаем в монитор порта
а в чем проблема? вы сами пробовали? покажите
хочу реализовать простые моменты, прежде чем идти дальше, научиться с малого.
прямо скажем, то, с чего Вы пытаетесь начать - совсем не малое
Мой вам совет - начните с чего-то совсем простого. Работа с модемом через текстовые команды - это задачка совсем не для новичка
 

MashukovAntonVictorovich

✩✩✩✩✩✩✩
31 Окт 2021
16
0
39
@bort707, Огромное спасибо за совет. но тем не менее решил попробовать.
И так вот ниже некий скетч я что смог повыкидывал из него некоторые моменты, но если есть опытные здесь люди помогите выкинуть лишнее из этого кода что только осталось в мониторе порта: 1) идет подключение, 2) то что подключение есть, 3) IP:адрес. Все остальное не требуется т.к. далее в этом скетче не могу понять что откуда, т.к. оригинал автор не озвучил что и зачем, т.е. не оставил комментарий.
команды от Arduino Nano в Esp01:
#include<SoftwareSerial.h>
SoftwareSerial client(2,3); //RX, TX

int i=0,k=0;
String readString;

String IP="";

    

void get_ip()
{
  IP="";
  char ch=0;
  while(1)
  {
    client.println("AT+CIFSR");
    while(client.available()>0)
    {
      if(client.find("STAIP,"))
      {
        delay(1000);
        Serial.print("IP Address:");
        while(client.available()>0)
        {
          ch=client.read();
          if(ch=='+')
          break;
          IP+=ch;
        }
      }
      if(ch=='+')
      break;
    }
    if(ch=='+')
    break;
    delay(1000);
  }
  Serial.print(IP);
 // Serial.print("Port:");
 // Serial.println(80);
}
void connect_wifi(String cmd, int t)
{
  int temp=0,i=0;
  while(1)
  {
    Serial.println(cmd);
    client.println(cmd);
    while(client.available())
    {
      if(client.find("OK"))
      i=8;
    }
    delay(t);
    if(i>5)
    break;
    i++;
  }
  if(i==8)
  Serial.println("OK");
  else
  Serial.println("Error");
}
void wifi_init()
{
      connect_wifi("AT",1000);
      connect_wifi("AT+CWMODE=3",1000);
      connect_wifi("AT+CWQAP",1000); 
      connect_wifi("AT+RST",11000);
      
      
        Serial.println("Connecting Wifi....");
        connect_wifi("AT+CWJAP=\"switch01\",\"f89mn2xK\"",11000);         //provide your WiFi username and password here
    
      Serial.println("Wifi Connected");
      get_ip();
}

void setup()
{
   Serial.begin(115200);
   client.begin(115200);
   wifi_init();
   Serial.println("System Ready..");
}
void loop()
{
 
}

в монитор порта выводится следующее: почему строки 2, 5, 8, 11, 15 выводятся повторно после чего следует ответ я так и не пойму.

монитор порта:
12:15:45.262 -> AT
12:15:46.249 -> AT
12:15:48.254 -> OK
12:15:48.254 -> AT+CWMODE=3
12:15:49.274 -> AT+CWMODE=3
12:15:51.246 -> OK
12:15:51.246 -> AT+CQAP
12:15:52.264 -> AT+CWQAP
12:15:54.270 -> OK
12:15:54.270 -> AT+RST
12:16:05.250 -> AT+RST
12:16:17.267 -> OK
12:16:17.267 -> Connecting Wifi...
12:16:17.267 -> AT+CWJAP="switch01","f89mn2xK"
12:16:29.268 -> AT+CWJAP="switch01","f89mn2xK"
12:16:41.265 -> OK
12:16:41.265 -> Wifi Connected
12:16:42.284 -> IP Address:"192.168.10.233"
12:16:42.284 -> System Ready..
 

bort707

★★★★★★✩
21 Сен 2020
3,056
910

@MashukovAntonVictorovich,
печатается два раза потому что строчки 48 и 49 внутри цикла. Если модуль отвечает быстро - будет одна строчка, а если не сразу - то две и даже больше. Да фиг с ним, что печатает в монитор два раза - хуже что скетч и команды в модем по два раза посылает...
 

MashukovAntonVictorovich

✩✩✩✩✩✩✩
31 Окт 2021
16
0
39
@bort707, согласен что в монитор порта хоть миллион раз не важно, факт как вы и сказали что несколько раз в esp01 шлет команды, как сделать чтоб отсылал команду 1 раз потом ждал до тех пор пока esp01 не ответит OK. Если все гуд тогда посылаем следующую команду, если ответа от какой либо команды нет в течении 1 минуты переходим к следующей, после чего возвращаемся к той команде которая не ответила, если же все ответы ОК то идем дальше. Знаю что запросил много пока думаю как это сделать, жду вашей помощи. Одна голова хорошо, а чем больше тем лучше.
 

bort707

★★★★★★✩
21 Сен 2020
3,056
910
Чтоб отсылал команду 1 раз - вынесите строчки 48 и 49 из цикла while
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,263
1,301
Москва
На самом деле надо поступать по другом.
Отсылается команда 1 раз. Далее в течении какого то времени надо ждать ответ от модуля. скажем 1 секунду. Если в течении этого времени ответа не было, то можно повторить операцию, Сколько раз надо повторить операцию, что бы понять , что модуль отвалился ? может 3-5 раз.
Если ответ пришел - и положительный - можно двигаться дальше. А бомбить командами модуль не самая лучшая идея.
В 39 строке вы выводите (или кто там автор программы) IP адрес в монитор порта. Тут же его можно вывести и на дисплей. Или запомнить где то и выводить позже.
 

MashukovAntonVictorovich

✩✩✩✩✩✩✩
31 Окт 2021
16
0
39
@Старик Похабыч, ты прав ip суну в переменную, а вот с посылом команд по циклу я пока не очень соображаю. Поэтому постараюсь чуть подрихтовать, всунуть все это дело в самый первый скетч , а далее покажу на обозрение возможно возникнут еще проблемы.
 

MashukovAntonVictorovich

✩✩✩✩✩✩✩
31 Окт 2021
16
0
39
Итак, скомпоновал оба кода ESP01 + SIM800L сам код скетча ниже:
WiFi ESP01+SIM800L:
#include<SoftwareSerial.h>
#include<Wire.h>           //#include <SPI.h>

#include <Adafruit_GFX.h>      // Библиотека работы с графикой
#include <Adafruit_SSD1306.h>  // Библиотека работы с OLED дисплеем 1306

#define SCREEN_WIDTH 128       // OLED дисплей ширина, в px
#define SCREEN_HEIGHT 32       // OLED дисплей высота, в px

// Declaration for an SSD1306 display connected to I2C (A4 = SDA, A5 = SCL)
// Reset pin # (or -1 если не имеет pin сброса)
#define OLED_RESET -1 // Если ваш OLED дисплей не имеет pin сброса, вы должны установить переменную OLED_RESET в значение -1, как сделано у меня
//See datasheet for Address
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


#define rxPin 8
#define txPin 9
SoftwareSerial sim800L(rxPin,txPin); // пины SIM800L
SoftwareSerial client(2,3); //RX-2, TX-3

int i=0,k=0;
String readString;
boolean No_IP=false;
String IP;
String network, battery;   // переменные для определения циклов работы с SIM800L





    

void get_ip()
{
  IP;
  char ch=0;
  while(1)
  {
    client.println("AT+CIFSR");
    while(client.available()>0)
    {
      if(client.find("STAIP,"))
      {
        delay(1000);
        Serial.print("IP Address:");
        while(client.available()>0)
        {
          ch=client.read();
          if(ch=='+')
          break;
          IP+=ch;
        }
      }
      if(ch=='+')
      break;
    }
    if(ch=='+')
    break;
    delay(1000);
  }
  Serial.print(IP);
 // Serial.print("Port:");
 // Serial.println(80);
}
void connect_wifi(String cmd, int t)
{
  int temp=0,i=0;
      Serial.println(cmd);
    //  client.println(cmd);
  while(1)
  {
    //Serial.println(cmd);
    client.println(cmd);
    while(client.available())
    {
      if(client.find("OK"))
      i=8;
    }
    delay(t);
    if(i>5)
    break;
    i++;
  }
  if(i==8)
  Serial.println("OK");
  else
  Serial.println("Error");
}


void setup()
{
   //Начните последовательную связь с последовательным монитором
   Serial.begin(115200);
   client.begin(115200);
   wifi_init();

     // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }


    // the library initializes this with an Adafruit splash screen.
  display.display();
  delay(2000); // Пауза 2 секунды

  // Очистка буфера дисплея
  display.clearDisplay();

  //Устанавливаем связь Arduino и SIM800L
  sim800L.begin(9600);
  sim800L.println("AT");
  delay(1000);
  sim800L.println("AT+CSCS=PCCP936"); // установка кодировки ввода/вывода текста.
  delay(1000);
  sim800L.println("AT+CMGF=1");
  delay(1000);

  Serial.println("System Ready..");
}


void wifi_init()
{
      connect_wifi("AT",100);
      connect_wifi("AT+CWMODE=3",100);
      connect_wifi("AT+CWQAP",100); 
      connect_wifi("AT+RST",1000);
      
      
        Serial.println("Connecting Wifi....");
        connect_wifi("AT+CWJAP=\"switch01\",\"f89mn2xK\"",7000);         //provide your WiFi username and password here
    
      Serial.println("Wifi Connected");
      
      get_ip();
}

//-----setup

void loop()
{
  //показатель сети устанавливаем на 0 network = "0";
      //показатель заряда батареи устанавливаем на 0 battery = "0";

      network = get_network();
      battery = get_battery();
      
      display_battery();
      display_network_battery();
     // get_ip();
}

int get_network()
{
  String buff;
  //buff = "+CSQ: 16,0";
  unsigned int result, index1, index2, timeout=0;

  sim800L.println("AT+CSQ"); 
  for (unsigned long start = millis(); millis() - start < 2000;){
    while(sim800L.available())
    {
      buff = sim800L.readString();
      timeout = 1;
      break;
    }
  }

  if(timeout == 0)
    { return 0; }
    
  Serial.println(buff);
 
  //String network_status;
  //_____________________________________________________
  //Remove sent "AT Command" from the response string.
  index1 = buff.indexOf("\r");
  buff.remove(0, index1+2);
  buff.trim();
  //_____________________________________________________
 
  //_____________________________________________________
 
    index1 = buff.indexOf(":");
    index2 = buff.indexOf(",");
    buff = buff.substring(index1+1, index2);
    buff.trim();
    result = buff.toInt();

    if(result == 99)
    {
      //сигнал неизвестен или не обнаружен
      return 0;
    }
    else if(result >= 2 && result <= 9)
    {
      //Signal Quality = Marginal
      return 20;
    }
    else if(result >= 10 && result <= 14)
    {
      //Signal Quality = OK
      return 40;
    }
    else if(result >= 15 && result <= 19)
    {
      //Signal Quality = Good
      return 60;
    }
    else if(result >= 20 && result <= 31)
    {
      //Signal Quality = Excellent
      return 99;
    }
    
  return 0;
}

int get_battery()
{
  String buff;
  //buff = "+CBC: 0,99,4190";
  unsigned int index1, index2, timeout=0;
    
  sim800L.println("AT+CBC"); 
  for (unsigned long start = millis(); millis() - start < 2000;){
    while(sim800L.available())
    {
      buff = sim800L.readString();
      timeout = 1;
      break;
    }
  }

  if(timeout == 0)
    { return 0; }
    
  Serial.println(buff);
 
  //String network_status;
  //_____________________________________________________
  //Remove sent "AT Command" from the response string.
  index1 = buff.indexOf("\r");
  buff.remove(0, index1+2);
  buff.trim();
  //_____________________________________________________
 
  //_____________________________________________________
 
    //search for first comma (,) = index1
    //search for 2nd comma (,) = index2
    index1 = buff.indexOf(",");
    index2 = buff.indexOf(",", index1+1);
    String result = buff.substring(index1+1, index2);
    result.trim();
    
    Serial.println(result);
    //buff.remove(0, index+2);
  return result.toInt();
}

void display_battery()
{

}

void display_network_battery()
{
  display.clearDisplay();

  display.drawRect(109, 1, 15, 8, WHITE);    //Первый кубик рисования батарейк
  display.drawRect(123, 2, 3, 6, WHITE);     //Второй кубик рисования батарейки
  display.fillRect(111, 3, (int)(1.5 * (battery.toInt()) / 10), 4, WHITE);
 
  display.drawLine(1, 1, 8, 1, WHITE);        //Верхняя палочка значка связи
  display.drawLine(1, 1, 5, 5, WHITE);
  display.drawLine(9, 1, 5, 5, WHITE);
  display.fillRect(5, 1, 1, 8, WHITE);        //Центральная палочка значка связи
  int net = network.toInt() / 20;
  int x1 = 8, y1 = 7, x2 = 2, y2 = 2;
  for (int i = 1; i <= net; i++)
  {
    display.fillRect(x1, y1, x2, y2, WHITE);
    x1 += 3; // Уменьшает или увеличивает расстояние между палочками качества сигнала
    y1 -= 2;
    y2 += 5;
    y2 -= 3;
  }
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(24, 1);
display.print(IP);
// display.setTextSize(1);
// display.setCursor(53, 1);
// display.println("%");
 display.display();
// delay(400);
}
Но есть проблемы при открытии окна монитора порта, всё бы ничего, но почему экран инициализируется только после выполнения всех команд модуля esp01, после чего врубается OLED дисплей и начинается работа уже с SIM800L. Но вот ещё беда, почему то иногда хрен пойми почему в порт выдает неверный ip адрес, вместо 192.168.10.233 выдает 192.178.10.233 (т.е. вместо 167, пишет 178) , а иногда скетч просто тормозится на команде вывода ip адреса и все зависает. Кто есть мастера подсобите. заранее спасибо всем.