Помогите объединить два и более скетчей в один

Тема в разделе "Моторы, сервоприводы, робототехника", создана пользователем CasperSimfer, 7 дек 2014.

  1. buktopz

    buktopz Нерд

  2. Alex19

    Alex19 Гуру

    Начнем, первая часть Марлезноского балета

    Код (C++):
    #include <SoftwareSerial.h>
    SoftwareSerial gsm(7, 8); // RX, TX

    // добавляем библиотеку для работы с LCD
    #include <LiquidCrystal.h>

    // определяем наш LCD(числа в скобках это наши пины на Arduino)
    LiquidCrystal lcd(12, 11, 6, 4, 3, 2);

    // определяем наш датчик(A0 - аналоговый вход куда подключен наш датчик)
    #define analogInPin   A0

    // определяем наш сигнальный пин
    #define alertPin      9

    #define pinLED 13
    #define pinBOOT 5    // нога BOOT или K на модеме
    #define pinWakeUp 10 // нога на растяжку

    #define TELLNUMBER "ATD+70001112233;" // номер на который будем звонить

    // Перечесление шагов, кон. автомата.
    enum State
    {
      STATE_BEGIN,
      STATE_GAS_ALERT,
      STATE_GAS_ALERT_WAIT,
      STATE_GAS_ALERT_NEXT_READ,
      STATE_GAS_NORMAL,
      STATE_END_MES,
      STATE_WAIT_NEXT_LOOP
    };

    // Переменная хранящая текущий шаг.
    int progState = STATE_BEGIN;

    //объявляем переменную для работы с датчиком
    int sensorValue = 0; //объявляем переменную для работы с датчиком

    // предыдущие значение millis
    unsigned long previousMillis = 0;

    void setup() {
      //это для работы с Serial. В нашем случае он не обязателен, но пускай будет для вывода ошибок
      Serial.begin(9600);
      gsm.begin(9600);                     /// незабываем указать скорость работы UART модема

      Serial.println("ard_start");

      // определяем наш сигнальный пин
      pinMode(alertPin, OUTPUT);

      pinMode(pinLED, OUTPUT);
      pinMode(pinBOOT, OUTPUT); /// нога BOOT на модеме
      pinMode(pinWakeUp, INPUT_PULLUP); /// нога на растяжку

      digitalWrite(pinBOOT, LOW); /// включаем модем, для проверки.
      /// !!! при подачи питания, нужно надавить на ресет ардуины,
      /// !!! модем при включении может просадить питание и ардуина не стартанет
      while (!gsm.find("+PBREADY")); /// при включении ждем готовность модема

      gsm.println("ATE0"); // выключаем эхо

      Serial.println("modemOFF");

      modemOFF(); /// и выключаем модем

      //наш размер LCD. Мой LCD поддерживает 16 символов и две строки.
      lcd.begin(16, 2);
    }

    void loop()
    {
      switch (progState)
      {
        case STATE_BEGIN:
          // считываем значения с датчика в переменную sensorValue
          sensorValue = analogRead(analogInPin);

          // выводим в Serial значения с датчика на всякий случай если вдруг не заработает LCD
          Serial.println(sensorValue);

          if (sensorValue >= 100)
          {
            progState++;
          }
          else
          {
            progState = STATE_GAS_NORMAL;
          }
          break;
        case STATE_GAS_ALERT:
          lcd.setCursor(0, 0); // ставим курсор на 0 символ и 0 строку. Отсчет идет с нуля.
          lcd.clear(); // очищаем экран LCD
          lcd.print("Gas!"); // если значение с датчика будет свыше чем 500, то на LCD появится надпись "Gas!"
          digitalWrite(alertPin, HIGH); // сигнал тревоги на модем с вывода 9 Ардуино

          previousMillis = millis();

          progState++;
          break;
        case STATE_GAS_ALERT_WAIT:
          if (GetDifferenceULong(previousMillis, millis()) > 1000UL)
          {
            digitalWrite(alertPin, LOW);

            previousMillis = millis();

            progState++;
          }
          break;
        case STATE_GAS_ALERT_NEXT_READ:
          if (GetDifferenceULong(previousMillis, millis()) > 10000UL)
          {
            previousMillis = 0;

            progState = STATE_END_MES;
          }
          break;
        case STATE_GAS_NORMAL:
          lcd.setCursor(0, 0);
          lcd.clear();
          lcd.print("Normal!"); // если датчик выдает меньше 500, то на экран нам показывается "Normal!"

          progState = STATE_END_MES;

          break;
        case STATE_END_MES:
          lcd.setCursor(0, 1); // ставим курсор на вторую строку
          lcd.print("Sensor = "); // на второй строке печатаем "Sensor = "
          lcd.print(sensorValue); // показуем сколько нам выдает датчик
          lcd.setCursor(0, 1);

          previousMillis = millis();

          progState = STATE_WAIT_NEXT_LOOP;
          break;
        case STATE_WAIT_NEXT_LOOP:
          if (GetDifferenceULong(previousMillis, millis()) > 1000)
          {
            previousMillis = 0;

            progState = STATE_BEGIN;
          }
          break;
      }
    }

    void modemOFF(){
      digitalWrite(pinBOOT, HIGH);
      delay(10);
      gsm.println("AT+CPWROFF");
    }

    // Переменные для определения разницы между 2 uint32
    #define unsignedLongMax 4294967295UL
    #define digitalOne 1UL

    // Функция которая возвращает разницу между 2-мя uint32.
    uint32_t GetDifferenceULong(uint32_t BeginTime, uint32_t EndTime)
    {
      // Защита от переполнения
      if (EndTime < BeginTime)
      {
        return unsignedLongMax - BeginTime + EndTime + digitalOne;
      }
      else
      {
        return EndTime - BeginTime;
      }
    }
    И так, первая часть есть, вторая так же определена, осталось добавить только loop со второй части. С библиотекой LowPower, ни когда не работал, поэтому убрал как и этот без полезный код.
    Код (C++):

    digitalWrite(LED, HIGH);                         /// можно закомментировать, показываем что не висим.
    delay(25);          
    digitalWrite(LED, LOW);
     
    Вторую часть когда, попробуйте написать сами, если не получится, подскажу.

    Чтобы написать Вам понадобиться конечный автомат (именно его я использовал), подробнее о нем, тут - http://wiki.amperka.ru/программирование:конечный-автомат.

    И так к примеру, проверяем и если оборвали растяжку. Нам требуется дополнить enum State, вероятно перед задержкой и переход на следующий круг добавляем STATE_CHECK_MODEM и все последующие шаги, шаг это последовательность операций которые выполняться без задержек и/или не делимые, есть задержка значит будет 2 шага. Разумеется, требуется так же проверить переход на STATE_WAIT_NEXT_LOOP. Так же добавляем данный вариант STATE_CHECK_MODEM + остальные в switch
    Код (C++):
    case STATE_CHECK_MODEM :
      if (digitalRead(wakeUpPin) && flag == 0)
      {  
        /// проверяем и если оборвали растяжку
        /// Что-то делаем, возможно переходим к следующему пункту/шагу
      }
      else
      {
        progState = STATE_WAIT_NEXT_LOOP;
      }
      break;
    И так, для каждой логической операции. Впрочем выключать модем, если не используется режим экономии электроэнергии не вижу смысла. Можно в setup вставить функцию modemON().

    UPD.
    Можно объединять команды, которые выполняться с задержками и/или не делимые. Но об этом позже.
     
    Последнее редактирование: 18 авг 2016
    buktopz нравится это.
  3. buktopz

    buktopz Нерд

    Огромное спасибо, буду пробовать завтра, чувствую долго буду мучиться. Сейчас у нас уже 23-40, что то пробовать бесполезно.
     
  4. Alex19

    Alex19 Гуру

    Ок, попробуйте, если что-то не получится, пишите.

    Тут самое важное понять, плюс у Вас появиться 2 вариант реализации кода, пошаговое выполнение.
     
    Последнее редактирование: 18 авг 2016
    buktopz нравится это.
  5. buktopz

    buktopz Нерд

    С кодом разбираюсь, сегодня думаю, выставлю свою "лепню".
    Я дилетант, просто так получилось с этим кодом время поджимает, и сейчас некогда изучать язык. Но я обязательно научусь, самому интересно. Кстати код очень напоминает код стилей файла .css (сайты делаю 6 лет).
    Вот еще хотелось бы выяснить отдельно:
    1. Вы говорили про энергосбережение. Было у автора скетча - #include <LowPower.h>
    Я понял, что это библиотека спящий режим. Но когда начал проверять на нем ошибка - убрал, ошибка ушла. Я подумал, а важно ли это на производстве с источником питания? А ваше мнение?

    2. #define pinWakeUp 10 // нога на растяжку (так говорят о н/з контакте)
    Тут я понял можно подать сигнал с 9 пина, т.е., если привышение нормы по газу, тогда звонок на телефон.
    Судя по "UP" в pinWakeUp туда нужно подавать сигнал высокого уровня?

    3. Третий вопрос, уважаемый гуру. Что бы прописать такое, чтобы с телефона или с кнопок может каких номер телефона поменять, если нужно.
    Сменился телефон к примеру на который сигнал тревоги идет...
     
  6. buktopz

    buktopz Нерд

    Не, гуру, не поднять мне это сейчас, безграмотен. Если не сложно дайте готовый, попробую позже его разобрать со шпаргалками по языку.
     
  7. Alex19

    Alex19 Гуру

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

    Удивлен таким сравнением, сталкивался с .css, и ни когда бы не сравнил его с C\C++. Тут ближе С#, Java и т.д.

    Не смотрел саму библиотеку, просто прочитал описание.

    Сам использую контролеры на производстве с источниками питания, еще ни когда не задумывался о энергопотреблении (у нас вокруг оборудование с потреблением 10-20КВатт):). И не знаю сколько потребляет Ардуино (на AVR) сейчас нашел пару ссылок - http://www.arduino.md/arduino_power_consumption/, http://student-proger.ru/2013/10/energopotreblenie-arduino/, Вам и себе на заметку.

    Нет pinWakeUp, настроен на чтение. А так как на схеме по данной ссылке к 2-ому пину ни чего не подключено, можно только догадываться. Видимо лучше использовать данный код, от тоже автора - http://arduinolab.pw/index.php/2016...iya-dlya-dachi-na-neoway-m590-i-arduino-itog/.

    Всего лишь любитель, меняем define
    Код (C++):

    #define TELLNUMBER "ATD+70001112233;"                 // номен на который будем звонить
    #define SMSNUMBER "AT+CMGS=\"70001112233\""           // номер на который будем отправлять SMS
    #define TELMODE "70001112233"                         // номер для установки на охрану
     
    Если надо динамически меняем их на переменные и заполняем их через клавиатуру, Serial и т.д.
     
    buktopz нравится это.
  8. buktopz

    buktopz Нерд

    Я сказал внешнее сходство с .css - решетка, фигурные скобки (только там не бывает скобки в скобках)
    А я других и не знаю
    По теме: Если Вы считаете, что лучше взять за основу скетч другого автора - Вам видней. Спасибо уже за то, что возитесь со мной...
     
  9. buktopz

    buktopz Нерд

    Ну вот попробовал совместить 2 скетча - ошибок нет, но на индикаторе светятся только сеточки:
    Код (C++):
    #include <LiquidCrystal.h> //  добавляем библиотеку для работы с LCD
    LiquidCrystal lcd(12, 11, 6, 4, 3, 2); // определяем наш LCD(числа в скобках это наши пины на Arduino)
    const int analogInPin = A0; // определяем наш датчик(A0 - аналоговый вход куда подключен наш датчик)
    int sensorValue = 0; //объявляем переменную для работы с датчиком

    #include <EEPROM.h>

    //// как подключен модем?
    //#include <SoftwareSerial.h>                 // если программный
    //SoftwareSerial gsm(7, 8); // RX, TX
    #define gsm Serial                           // если аппаратный в UNO
    //#define gsm Serial1                          // если аппаратный в леонардо

    #define LED 13

    #define TELLNUMBER "ATD+70001112233;"                 // номен на который будем звонить
    #define SMSNUMBER "AT+CMGS=\"70001112233\""           // номер на который будем отправлять SMS
    #define TELMODE "70001112233"                         // номер для установки на охрану

    #define SH1 A2              // шлейыф
    //#define SH2 A3

    #define pinBOOT 5           // нога BOOT или K на модеме

    byte mode = 0;              // 0 - только включили
                                // 1 - установлена охрана
                                // 2 - снята с охраны
                                // при добавлении не забываем посмотреть на 41 строку

    void setup() {
       Serial.begin(9600);  //это для работы с Serial. В нашем случае он не обязателен, но пускай будет для вывода ошибок
       lcd.begin(16, 2); //наш размер LCD. Мой LCD поддерживает 16 символов и две строки.
    delay(1000);                    //// !! чтобы нечего не повисало при включении
     
      gsm.begin(9600);                         /// незабываем указать скорость работы UART модема
    //  Serial.begin(9600);
      pinMode(LED, OUTPUT);
      pinMode(pinBOOT, OUTPUT);                /// нога BOOT на модеме
      pinMode(SH1, INPUT_PULLUP);              /// нога на растяжку
    //  pinMode(SH2, INPUT_PULLUP);              /// нога на растяжку

                                              // читаем режим из еепром
      mode = EEPROM.read(0);
      if (mode > 2) mode = 2;                 // проверяем значение в еепром
                                          // занимаемся модемом      
      delay(1000);                          
      digitalWrite(LED, HIGH);                // на время включаем лед
      digitalWrite(pinBOOT, LOW);             /// включаем модем
          // нужно дождатся включения модема и соединения с сетью
      delay(2000);  
    //  while(gsm.find("STARTUP"));          /// ждем команды от модема
      gsm.println("ATE0");                  // выключаем эхо
     
      while(1){                             // ждем подключение модема к сети
            gsm.println("AT+COPS?");
            if (gsm.find("+COPS: 0")) break;
               digitalWrite(LED, LOW);               // блымаем светодиодом
               delay(50);
               digitalWrite(LED, HIGH);
               delay(500);
        }

    //Serial.println("Modem OK");
       digitalWrite(LED, LOW);               // блымаем светодиодом
       delay(1500);
       digitalWrite(LED, HIGH);
       delay(250);
       digitalWrite(LED, LOW);  
     
    }

    void loop() {
      sensorValue = analogRead(analogInPin);  // считываем значения с датчика в переменную sensorValue
      Serial.println(sensorValue);  // выводим в Serial значения с датчика на всякий случай если вдруг не заработает LCD

      if (sensorValue >= 500) {
        lcd.setCursor(0, 0);          // ставим курсор на 0 символ и 0 строку. Отсчет идет с нуля.
        lcd.clear();           //  очищаем экран LCD
        lcd.print("Gas!");  // если значение с датчика будет свыше чем 500, то на LCD появится надпись "Gas!"
        digitalWrite(9, HIGH); // сигнал тревоги на модем с вывода 9 Ардуино
        delay(1000); // длительность сигнала тревоги
        digitalWrite(9, LOW);
        delay(10000); // длительность паузы сигнала тревоги
       
    }
      else {
        lcd.setCursor(0, 0);    
        lcd.clear();
        lcd.print("Normal!");        //  если датчик выдает меньше 500, то на экран нам показывается "Normal!"

    }
      lcd.setCursor(0, 1);           // ставим курсор на вторую строку
      lcd.print("Sensor = ");      // на второй строке печатаем "Sensor = "
      lcd.print(sensorValue);    // показуем сколько нам выдает датчик
      lcd.setCursor(0, 1);        
      delay(1000);                       // повтор каждые 300 миллисекунд
     
      if (mode == 1){                         // если в режиме охраны
                                              // проверяем датчики
        if (digitalRead(SH1)){                // если обрыв
                                              // отзваниваемся
            gsm.println(TELLNUMBER);
            delay(2500);                      
              if (gsm.find("NO CARRIER")){      // ищим сброс вызова,
                                                // снимаем охранку
                  mode = 2;
                  EEPROM.write(0, mode);
              }
        }
      }

     
      // если охрана снята
      if (mode == 2){
        if (digitalRead(SH1)){  // проверяем датчики, включаем LED
          digitalWrite(LED, HIGH);  
        }
        else digitalWrite(LED, LOW);
      }

     
    // ищим RING
       // если нашли, опрашиваем кто это и ставим на охрану
        if(gsm.find("RING")){                    // если нашли RING
          gsm.println("AT+CLIP=1");              // включаем АОН,
               
          while(1){                              // в цикле
           if (gsm.find(TELMODE)){               // ищим номер телефона, если нашли
             mode = 1;                           // меняем режим
             EEPROM.write(0, mode);              // пишим его в еепром
             break;                              // и выходим
           }
           else{                                 // иначе
             gsm.println("AT+CPAS");             // спрашиваем состояние модема  
             delay(100);
             if (gsm.find("+CPAS: 0")) break;    // и если он в "готовности", выходим из цикла
           }                                     // если звонок в процессе, возвращает +CPAS: 3
          }                                      // и крутимся дальше
         
            gsm.println("AT+CLIP=0");            // выключаем АОН,
            delay(500);
            gsm.println("ATH0");                 // сбрасываем вызов

             digitalWrite(LED, LOW);             // сигнализируем об этом
             delay(500);
             digitalWrite(LED, HIGH);
             delay(250);
             digitalWrite(LED, LOW);  
     
        }
       
    }
     
  10. Alex19

    Alex19 Гуру

    Просто удивило их сравнение, ну да ладно.

    У Вас все впереди, мы все учимся и в какой-то момент чего-то не знаем (как и я, как и большинство на этом форуме).

    Вроде автор, тот же, там просто нет лишнего.

    Индикатор, это монитор LCD.

    И так, тогда прежде чем объединять 2 скетча убедимся, что они работают. Заливаем этот скетч
    Код (C++):
    // добавляем библиотеку для работы с LCD
    #include <LiquidCrystal.h>

    // определяем наш LCD(числа в скобках это наши пины на Arduino)
    LiquidCrystal lcd(12, 11, 6, 4, 3, 2);

    // определяем наш датчик(A0 - аналоговый вход куда подключен наш датчик)
    #define analogInPin   A0

    // определяем наш сигнальный пин
    #define alertPin      9

    // Перечесление шагов, кон. автомата.
    enum State
    {
      STATE_BEGIN,
      STATE_GAS_ALERT,
      STATE_GAS_ALERT_WAIT,
      STATE_GAS_ALERT_NEXT_READ,
      STATE_GAS_NORMAL,
      STATE_END_MES,
      STATE_WAIT_NEXT_LOOP
    };

    // Переменная хранящая текущий шаг.
    int progState = STATE_BEGIN;

    //объявляем переменную для работы с датчиком
    int sensorValue = 0; //объявляем переменную для работы с датчиком

    // предыдущие значение millis
    unsigned long previousMillis = 0;

    void setup() {
      //это для работы с Serial. В нашем случае он не обязателен, но пускай будет для вывода ошибок
      Serial.begin(9600);
      Serial.println("ard_start");

      // определяем наш сигнальный пин
      pinMode(alertPin, OUTPUT);

      //наш размер LCD. Мой LCD поддерживает 16 символов и две строки.
      lcd.begin(16, 2);

      //немного подождем
      delay(1000);
    }

    void loop()
    {
      switch (progState)
      {
        case STATE_BEGIN:
          // считываем значения с датчика в переменную sensorValue
          sensorValue = analogRead(analogInPin);

          // выводим в Serial значения с датчика на всякий случай если вдруг не заработает LCD
          Serial.println(sensorValue);

          if (sensorValue >= 500)
          {
            progState++;
          }
          else
          {
            progState = STATE_GAS_NORMAL;
          }
          break;
        case STATE_GAS_ALERT:
          lcd.clear(); // очищаем экран LCD
          lcd.setCursor(0, 0); // ставим курсор на 0 символ и 0 строку. Отсчет идет с нуля.
          lcd.print("Gas!"); // если значение с датчика будет свыше чем 500, то на LCD появится надпись "Gas!"
          digitalWrite(alertPin, HIGH); // сигнал тревоги на модем с вывода 9 Ардуино

          previousMillis = millis();

          progState++;
          break;
        case STATE_GAS_ALERT_WAIT:
          if (GetDifferenceULong(previousMillis, millis()) > 1000UL)
          {
            digitalWrite(alertPin, LOW);

            previousMillis = millis();

            progState++;
          }
          break;
        case STATE_GAS_ALERT_NEXT_READ:
          if (GetDifferenceULong(previousMillis, millis()) > 10000UL)
          {
            previousMillis = 0;

            progState = STATE_END_MES;
          }
          break;
        case STATE_GAS_NORMAL:
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("Normal!"); // если датчик выдает меньше 500, то на экран нам показывается "Normal!"

          progState = STATE_END_MES;

          break;
        case STATE_END_MES:
          lcd.setCursor(0, 1); // ставим курсор на вторую строку
          lcd.print("Sensor = "); // на второй строке печатаем "Sensor = "
          lcd.print(sensorValue); // показуем сколько нам выдает датчик

          previousMillis = millis();

          progState = STATE_WAIT_NEXT_LOOP;
          break;
        case STATE_WAIT_NEXT_LOOP:
          if (GetDifferenceULong(previousMillis, millis()) > 1000)
          {
            previousMillis = 0;

            progState = STATE_BEGIN;
          }
          break;
      }
    }

    // Переменные для определения разницы между 2 uint32
    #define unsignedLongMax 4294967295UL
    #define digitalOne 1UL

    // Функция которая возвращает разницу между 2-мя uint32.
    uint32_t GetDifferenceULong(uint32_t BeginTime, uint32_t EndTime)
    {
      // Защита от переполнения
      if (EndTime < BeginTime)
      {
        return unsignedLongMax - BeginTime + EndTime + digitalOne;
      }
      else
      {
        return EndTime - BeginTime;
      }
    }
    Почему я не использую Ваш код, огромное кол-во delay в loop, которые сами по себе могут создавать проблемы.

    Если код заработает, можно продолжать, если нет проверяем код для работы с монитором, код для проверки:
    Код (C++):
    // добавляем библиотеку для работы с LCD
    #include <LiquidCrystal.h>

    // определяем наш LCD(числа в скобках это наши пины на Arduino)
    LiquidCrystal lcd(12, 11, 6, 4, 3, 2);

    void setup()
    {
      // устанавливаем размер (количество столбцов и строк) экрана
      lcd.begin(16, 2);
      // печатаем первую строку
      lcd.print("Hello world!");
      // устанавливаем курсор в колонку 0, строку 1. То есть на
      // самом деле это вторая строка, т.к. нумерация начинается с нуля
      lcd.setCursor(0, 1);
      // печатаем вторую строку
      lcd.print("foo bar baz");
    }

    void loop()
    {
    }
    Если данный код не заработает, проверьте свое подключение монитора.
     
    buktopz нравится это.
  11. buktopz

    buktopz Нерд

    Так один код работает, который "Газ", все пишет правильно (в облаке проверял), а когда к нему добавил второй код (GSM) на экране только сеточки. Пришли модули, завтра буду подключать
     
  12. Alex19

    Alex19 Гуру

    Отлично, что монитор работает.

    Теперь опробуем данный код
    Код (C++):
    #include <SoftwareSerial.h>
    SoftwareSerial gsm(7, 8); // RX, TX

    // добавляем библиотеку для работы с LCD
    #include <LiquidCrystal.h>

    // определяем наш LCD(числа в скобках это наши пины на Arduino)
    LiquidCrystal lcd(12, 11, 6, 4, 3, 2);

    // определяем наш датчик(A0 - аналоговый вход куда подключен наш датчик)
    #define analogInPin   A0

    // определяем наш сигнальный пин
    #define alertPin      9

    // Перечесление шагов, кон. автомата.
    enum State
    {
      STATE_BEGIN,
      STATE_GAS_ALERT,
      STATE_GAS_ALERT_WAIT,
      STATE_GAS_ALERT_NEXT_READ,
      STATE_GAS_NORMAL,
      STATE_SEND_MES,
      STATE_END_MES,
      STATE_WAIT_NEXT_LOOP
    };

    // Переменная хранящая текущий шаг.
    int progState = STATE_BEGIN;

    //объявляем переменную для работы с датчиком
    int sensorValue = 0; //объявляем переменную для работы с датчиком

    // предыдущие значение millis
    unsigned long previousMillis = 0;

    #define pinLED 13

    #define TELLNUMBER "ATD+70001112233;"                 // номен на который будем звонить
    #define SMSNUMBER "AT+CMGS=\"70001112233\""           // номер на который будем отправлять SMS
    #define TELMODE "70001112233"                         // номер для установки на охрану

    #define pinBOOT 5           // нога BOOT или K на модеме

    void setup()
    {
      delay(1000);                    //// !! чтобы нечего не повисало при включении

      //это для работы с Serial. В нашем случае он не обязателен, но пускай будет для вывода ошибок
      Serial.begin(9600);
      Serial.println("ard_start");

      // определяем наш сигнальный пин
      pinMode(alertPin, OUTPUT);

      //наш размер LCD. Мой LCD поддерживает 16 символов и две строки.
      lcd.begin(16, 2);

      gsm.begin(9600);                                  /// незабываем указать скорость работы UART модема
      pinMode(pinLED, OUTPUT);
      pinMode(pinBOOT, OUTPUT);                         /// нога BOOT на модеме

      digitalWrite(pinLED, HIGH);                // на время включаем лед
      digitalWrite(pinBOOT, LOW);                /// включаем модем

      // нужно дождатся включения модема и соединения с сетью
      delay(2000);
      //  while(gsm.find("STARTUP"));           /// ждем команды от модема
      gsm.println("ATE0");                      // выключаем эхо

      while (1) {                               // ждем подключение модема к сети
        gsm.println("AT+COPS?");
        if (gsm.find("+COPS: 0")) break;
        digitalWrite(pinLED, LOW);              // блымаем светодиодом
        delay(50);
        digitalWrite(pinLED, HIGH);
        delay(500);
      }

      Serial.println("Modem OK");

      digitalWrite(pinLED, LOW);               // блымаем светодиодом
      delay(1500);
      digitalWrite(pinLED, HIGH);
      delay(250);
      digitalWrite(pinLED, LOW);

      //немного подождем
      delay(1000);
    }

    void loop()
    {
      switch (progState)
      {
        case STATE_BEGIN:
          // считываем значения с датчика в переменную sensorValue
          sensorValue = analogRead(analogInPin);

          // выводим в Serial значения с датчика на всякий случай если вдруг не заработает LCD
          Serial.println(sensorValue);

          if (sensorValue >= 500)
          {
            progState++;
          }
          else
          {
            progState = STATE_GAS_NORMAL;
          }
          break;
        case STATE_GAS_ALERT:
          lcd.clear(); // очищаем экран LCD
          lcd.setCursor(0, 0); // ставим курсор на 0 символ и 0 строку. Отсчет идет с нуля.
          lcd.print("Gas!"); // если значение с датчика будет свыше чем 500, то на LCD появится надпись "Gas!"
          digitalWrite(alertPin, HIGH); // сигнал тревоги на модем с вывода 9 Ардуино

          previousMillis = millis();

          progState++;
          break;
        case STATE_GAS_ALERT_WAIT:
          if (GetDifferenceULong(previousMillis, millis()) > 1000UL)
          {
            digitalWrite(alertPin, LOW);

            previousMillis = millis();

            progState++;
          }
          break;
        case STATE_GAS_ALERT_NEXT_READ:
          if (GetDifferenceULong(previousMillis, millis()) > 10000UL)
          {
            previousMillis = 0;

            progState = STATE_SEND_MES;
          }
          break;
        case STATE_GAS_NORMAL:
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("Normal!"); // если датчик выдает меньше 500, то на экран нам показывается "Normal!"

          progState = STATE_END_MES;

          break;
        case STATE_SEND_MES:
          static byte mode = 0;

          if (mode == 0)
          {
            gsm.println(TELLNUMBER);
            mode = 1;
          }

          if (mode == 1 && (GetDifferenceULong(previousMillis, millis()) > 2500UL))
          {
            if (gsm.find("NO CARRIER")) {     // ищим сброс вызова,
              mode = 2;
            }
          }

          progState = STATE_END_MES;
          mode = 0;
          break;
        case STATE_END_MES:
          lcd.setCursor(0, 1); // ставим курсор на вторую строку
          lcd.print("Sensor = "); // на второй строке печатаем "Sensor = "
          lcd.print(sensorValue); // показуем сколько нам выдает датчик

          previousMillis = millis();

          progState = STATE_WAIT_NEXT_LOOP;
          break;
        case STATE_WAIT_NEXT_LOOP:
          if (GetDifferenceULong(previousMillis, millis()) > 1000)
          {
            previousMillis = 0;

            progState = STATE_BEGIN;
          }
          break;
      }
    }

    // Переменные для определения разницы между 2 uint32
    #define unsignedLongMax 4294967295UL
    #define digitalOne 1UL

    // Функция которая возвращает разницу между 2-мя uint32.
    uint32_t GetDifferenceULong(uint32_t BeginTime, uint32_t EndTime)
    {
      // Защита от переполнения
      if (EndTime < BeginTime)
      {
        return unsignedLongMax - BeginTime + EndTime + digitalOne;
      }
      else
      {
        return EndTime - BeginTime;
      }
    }
    Меняем только телефоны тут

    Код (C++):
    #define TELLNUMBER "ATD+70001112233;"                 // номен на который будем звонить
    #define SMSNUMBER "AT+CMGS=\"70001112233\""           // номер на который будем отправлять SMS
    #define TELMODE "70001112233"                         // номер для установки на охрану
    Если будет Газ, он наберет номер и будет ждать сброса. Вставил первый вариант, для проверки работы с модулем GMS.

    UPD.
    В облаке, это как. Среда Arduino IDE в облаке или что?
     
    buktopz нравится это.
  13. buktopz

    buktopz Нерд

    Нет, все равно сеточки на дисплее. Ладно, завтра если с модулями все в порядке - посмотрим с этим кодом, что происходит на реальных модулях, а не виртуальных. Как что-нибудь задышит - напишу
     
  14. Alex19

    Alex19 Гуру

    Странно, ок.

    Я там немного ошибся, но на экран это не влияет, вот исправленный код.
    Код (C++):
    #include <SoftwareSerial.h>
    SoftwareSerial gsm(7, 8); // RX, TX

    // добавляем библиотеку для работы с LCD
    #include <LiquidCrystal.h>

    // определяем наш LCD(числа в скобках это наши пины на Arduino)
    LiquidCrystal lcd(12, 11, 6, 4, 3, 2);

    // определяем наш датчик(A0 - аналоговый вход куда подключен наш датчик)
    #define analogInPin   A0

    // определяем наш сигнальный пин
    #define alertPin      9

    // Перечесление шагов, кон. автомата.
    enum State
    {
      STATE_BEGIN,
      STATE_GAS_ALERT,
      STATE_GAS_ALERT_WAIT,
      STATE_GAS_ALERT_NEXT_READ,
      STATE_GAS_NORMAL,
      STATE_SEND_MES,
      STATE_END_MES,
      STATE_WAIT_NEXT_LOOP
    };

    // Переменная хранящая текущий шаг.
    int progState = STATE_BEGIN;

    //объявляем переменную для работы с датчиком
    int sensorValue = 0; //объявляем переменную для работы с датчиком

    // предыдущие значение millis
    unsigned long previousMillis = 0;

    #define pinLED 13

    #define TELLNUMBER "ATD+70001112233;"                 // номен на который будем звонить
    #define SMSNUMBER "AT+CMGS=\"70001112233\""           // номер на который будем отправлять SMS
    #define TELMODE "70001112233"                         // номер для установки на охрану

    #define pinBOOT 5           // нога BOOT или K на модеме

    void setup()
    {
      delay(1000);                    //// !! чтобы нечего не повисало при включении

      //это для работы с Serial. В нашем случае он не обязателен, но пускай будет для вывода ошибок
      Serial.begin(9600);
      Serial.println("ard_start");

      // определяем наш сигнальный пин
      pinMode(alertPin, OUTPUT);

      //наш размер LCD. Мой LCD поддерживает 16 символов и две строки.
      lcd.begin(16, 2);

      gsm.begin(9600);                                  /// незабываем указать скорость работы UART модема
      pinMode(pinLED, OUTPUT);
      pinMode(pinBOOT, OUTPUT);                         /// нога BOOT на модеме

      digitalWrite(pinLED, HIGH);                // на время включаем лед
      digitalWrite(pinBOOT, LOW);                /// включаем модем

      // нужно дождатся включения модема и соединения с сетью
      delay(2000);
      //  while(gsm.find("STARTUP"));           /// ждем команды от модема
      gsm.println("ATE0");                      // выключаем эхо

      while (1) {                               // ждем подключение модема к сети
        gsm.println("AT+COPS?");
        if (gsm.find("+COPS: 0")) break;
        digitalWrite(pinLED, LOW);              // блымаем светодиодом
        delay(50);
        digitalWrite(pinLED, HIGH);
        delay(500);
      }

      Serial.println("Modem OK");

      digitalWrite(pinLED, LOW);               // блымаем светодиодом
      delay(1500);
      digitalWrite(pinLED, HIGH);
      delay(250);
      digitalWrite(pinLED, LOW);

      //немного подождем
      delay(1000);
    }

    void loop()
    {
      switch (progState)
      {
        case STATE_BEGIN:
          // считываем значения с датчика в переменную sensorValue
          sensorValue = analogRead(analogInPin);

          // выводим в Serial значения с датчика на всякий случай если вдруг не заработает LCD
          Serial.println(sensorValue);

          if (sensorValue >= 500)
          {
            progState++;
          }
          else
          {
            progState = STATE_GAS_NORMAL;
          }
          break;
        case STATE_GAS_ALERT:
          lcd.clear(); // очищаем экран LCD
          lcd.setCursor(0, 0); // ставим курсор на 0 символ и 0 строку. Отсчет идет с нуля.
          lcd.print("Gas!"); // если значение с датчика будет свыше чем 500, то на LCD появится надпись "Gas!"
          digitalWrite(alertPin, HIGH); // сигнал тревоги на модем с вывода 9 Ардуино

          previousMillis = millis();

          progState++;
          break;
        case STATE_GAS_ALERT_WAIT:
          if (GetDifferenceULong(previousMillis, millis()) > 1000UL)
          {
            digitalWrite(alertPin, LOW);

            previousMillis = millis();

            progState++;
          }
          break;
        case STATE_GAS_ALERT_NEXT_READ:
          if (GetDifferenceULong(previousMillis, millis()) > 10000UL)
          {
            previousMillis = 0;

            progState = STATE_SEND_MES;
          }
          break;
        case STATE_GAS_NORMAL:
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("Normal!"); // если датчик выдает меньше 500, то на экран нам показывается "Normal!"

          progState = STATE_END_MES;

          break;
        case STATE_SEND_MES:
          static byte mode = 0;

          if (mode == 0)
          {
            gsm.println(TELLNUMBER);
            mode = 1;
          }

          if (mode == 1 && (GetDifferenceULong(previousMillis, millis()) > 2500UL))
          {
            if (gsm.find("NO CARRIER")) {     // ищим сброс вызова,
              mode = 2;
            }
          }

          if (mode == 2)
          {
            progState = STATE_END_MES;
            mode = 0;
          }
         
          break;
        case STATE_END_MES:
          lcd.setCursor(0, 1); // ставим курсор на вторую строку
          lcd.print("Sensor = "); // на второй строке печатаем "Sensor = "
          lcd.print(sensorValue); // показуем сколько нам выдает датчик

          previousMillis = millis();

          progState = STATE_WAIT_NEXT_LOOP;
          break;
        case STATE_WAIT_NEXT_LOOP:
          if (GetDifferenceULong(previousMillis, millis()) > 1000)
          {
            previousMillis = 0;

            progState = STATE_BEGIN;
          }
          break;
      }
    }

    // Переменные для определения разницы между 2 uint32
    #define unsignedLongMax 4294967295UL
    #define digitalOne 1UL

    // Функция которая возвращает разницу между 2-мя uint32.
    uint32_t GetDifferenceULong(uint32_t BeginTime, uint32_t EndTime)
    {
      // Защита от переполнения
      if (EndTime < BeginTime)
      {
        return unsignedLongMax - BeginTime + EndTime + digitalOne;
      }
      else
      {
        return EndTime - BeginTime;
      }
    }
     
    buktopz нравится это.
  15. buktopz

    buktopz Нерд

  16. buktopz

    buktopz Нерд

    понял, перезалью
     
  17. Alex19

    Alex19 Гуру

    :), извините был не внимателен.

    Конечно он не заработает, там в setup стоит while он ждет ответа от Вашего модема, он даже не доходит до loop. Проверка возможна - только на реальном железе.
     
    buktopz нравится это.
  18. buktopz

    buktopz Нерд

    ну когда просто скетч датчика загружал и моделировал схему (вместо датчика - резистор), то все норм было, дрезистор кручу, сначала Normal, потом Gas, все пишет.
    Понял, тогда завтра, если все подключу и загружу, сразу напишу. Но это тоже будет в первый раз...
     
  19. buktopz

    buktopz Нерд

    Весь интернет перерыл, где этот чертов вывод boot на модеме?
     

    Вложения:

    • boot.jpg
      boot.jpg
      Размер файла:
      261,9 КБ
      Просмотров:
      560
  20. buktopz

    buktopz Нерд

    Ну вообщем результаты такие:
    1. Сначала загрузил первый код (датчик газа) - подключил к USB - все работает правильно, только буквы еле различимы. Но это потом.
    2. Загрузил Ваш код, подключил контроллер с индикатором к USB, модем к внешнему питанию (жрет много), земля, естественно общая. Симку поставил. На индикаторе только сеточка
    Я не подключил этот чертов boot на модеме. У меня плата отличная от той, которая в описании. А на той не видно куда boot идет, на какой вывод M590. Может boot это ring?