Какую ошибку я допускаю?

lues
Offline
Зарегистрирован: 10.06.2016

Всем добрый день.

Не первый раз сталкиваюсь с такой ситуацией - из разных кусков кода или работающих примеров собираю свой проект и компилятор стопорится на обьявленной функции void (что то там).

То есть, в работающем примере все компилируется без замечаний - когда переношу работающий код в свой проект - компилятор спотыкается с ругательством "*** was not declared in this scope".

Я не раз уже в справочниках читал как обьявлять функцию, вроде же все так в коде. Но итог один - в примере функция работает нормально - при переносе в мой проект ругается.

Явно что то упускаю.

Вот текущий пример. Кода много и я подозреваю суть не в самом коде а в какой то моей системной ошибке. Но что я делаю не так с обьявлением функции?
 
В этом коде обьявленный функции работают успешно.
    #define ANALOG_PIN A0
    #define CLOSE_WIN_FACTOR 10               // 1/X for narrowing window each side

    int winHi = 0, winLo = 1024;              // store histeresis limits here
    int dataCur;                              // temporary storage of current data
    boolean ledState, ledStateOld;            // current logic state
    float wattage = 0;                        // store current wattage
    float wattage_min = 0;
    float wattage_day = 0;
    float wattage_month = 0;
    int windowLo = 0;                         // bottom line of scale window in Wt
    int windowHi = 1000;                      // top line of scale window in Wt
  
    unsigned long previousMillis=0;
    int min_count = 0;
    float min_power = 0;

    void setup() {
    ESP.wdtDisable();
    Serial.begin(9600);
    Serial.println("start");
    initWindow();                                   // вызов функции вычисления значения порогов вкл и выкл состояния светодиода
    }


    void loop() {
    unsigned long currentMillis = millis();
    dataCur = analogRead(ANALOG_PIN);               // запоминаем значение на сенсоре
    findAnalogWindow(dataCur);                      // расширяем окно, если значение выходит за его пределы
    ledStateOld = ledState;                         // сохраняем в буфер старое значение уровня сенсора
    checkLogic(dataCur);                            // оцениваем состояние сенсора и сохраняем его значение в ledState
   // if (ledState == !ledStateOld) {                 // ИНДикатор только что изменил своё состояние
   // }

    if (ledStateOld && !ledState) {                 // ИНДикатор только что загорелся
    Serial.println("o");
    }

    if (!ledStateOld && ledState) {                 // ИНДикатор только что погас
    Serial.println("*");
    closeAnalogWindow();                          // ужимаем пороги окна сенсора, чтобы они хронически не росли.
    min_count++;
    }
    
    if ((currentMillis - previousMillis) == 60000) {
    Serial.print("blink #=");
    Serial.println(min_count);
    Serial.print("min_power=");
    min_power = min_count*0.3125;
    Serial.println(min_power);
    previousMillis = currentMillis;
    min_count = 0;
    }
    ESP.wdtFeed();
    }


    void initWindow() {
    unsigned long startTimer = millis() + 5000;
    while (millis() < startTimer) {
    dataCur = analogRead(ANALOG_PIN);
    findAnalogWindow(dataCur);
    }
    }

    void findAnalogWindow(int analogData) {
    if (analogData > winHi) winHi = analogData;         // запомнить значение как верхнее, если оно выше него
    if (analogData < winLo) winLo = analogData;         // запомнить значение как нижнее, если оно ниже него
    }

    void closeAnalogWindow() {
    if (winLo < winHi - 30) {
    int winDif = (winHi - winLo) ;                    // вычисляем ширину окна
    winHi = winHi - (winDif / CLOSE_WIN_FACTOR);      // вычитаем 1/10 ширины из верхнего порога
    winLo = winLo + (winDif / CLOSE_WIN_FACTOR);      // прибавляем 1/10 ширины к нижнему порогу
    }
    }

    void checkLogic(int analogData) {
    if (winLo < winHi - 5) {
    int percCur = map(analogData, winLo, winHi, 0, 99); // переводим значение в проценты от шкалы
    if (percCur <= 33) ledState = 0;
    if (percCur >= 66) ledState = 1;
    }
    }

 

Переношу весь код в свой проект - компиляцию не проходит - стопорится на первой же функции "initWindow()"

    #include <ThingSpeak.h>
    #include <FS.h>
    #include <ESP8266WiFi.h>          
    #include <ArduinoJson.h>          
    #include <ESP8266WebServer.h>
    #include <DNSServer.h>
    #include <WiFiManager.h>    
              

    const int PIN_LED = 4; // поменять на другой пин
   
    const char* CONFIG_FILE = "/config.json";
    int led = LOW;             // этой переменной устанавливаем состояние светодиода
    long previousMillis2 = 0;        // храним время последнего переключения светодиода
    long interval = 500;           // интервал между включение/выключением светодиода 
    unsigned long starttime1=0;
    int temp = 5;

    bool initialConfig = false; // Indicates whether ESP has WiFi credentials saved from previous session

    // Default configuration values
    char thingspeakApiKey[17] = "";
 
    // Function Prototypes
    bool readConfigFile();
    bool writeConfigFile();

   unsigned long myChannelNumber;            // Thingspeak channel ID here

    int fieldStart = 1;    
    int updatePeriod = 120;                     

    int status = WL_IDLE_STATUS;
    WiFiClient  client;

    
    #define ANALOG_PIN A0
    #define CLOSE_WIN_FACTOR 10               // 1/X for narrowing window each side

    int winHi = 0, winLo = 1024;              // store histeresis limits here
    int dataCur;                              // temporary storage of current data
    boolean ledState, ledStateOld;            // current logic state
    float wattage = 0;                        // store current wattage
    float wattage_min = 0;
    float wattage_day = 0;
    float wattage_month = 0;
    int windowLo = 0;                         // bottom line of scale window in Wt
    int windowHi = 1000;                      // top line of scale window in Wt
  
    unsigned long previousMillis = 0;
    int min_count = 0;
    float min_power = 0;
         
    void setup() {
    ESP.wdtDisable();
    Serial.begin(115200);
    Serial.println("\n Starting");

    pinMode(PIN_LED, OUTPUT);
   
    bool result = SPIFFS.begin();   // Mount the filesystem
    Serial.println("SPIFFS opened: " + result);

    if (!readConfigFile()) {
    Serial.println("Failed to read configuration file, using default values");
    }

    WiFi.printDiag(Serial); //Remove this line if you do not want to see WiFi password printed

    if (WiFi.SSID() == "") {
    Serial.println("We haven't got any access point credentials, so get them now");
    initialConfig = true;
    } 
    else {
    digitalWrite(PIN_LED, HIGH); // Turn LED off as we are not in configuration mode. 
    WiFi.mode(WIFI_STA); // Force to station mode because if device was switched off while in access point mode it will start up next time in access point mode.
    unsigned long startedAt = millis();
    Serial.print("After waiting ");
    int connRes = WiFi.waitForConnectResult();
    float waited = (millis()- startedAt);
    Serial.print(waited/1000);
    Serial.print(" secs in setup() connection result is ");
    Serial.println(connRes);
    }

    if (WiFi.status()!=WL_CONNECTED){
    Serial.println("Failed to connect, finishing setup anyway");
    }
    else{
    Serial.print("Local ip: ");
    Serial.println(WiFi.localIP());
    }
    
    Serial.println("Configuration portal requested");
    digitalWrite(PIN_LED, LOW); 
    
    WiFiManagerParameter p_thingspeakApiKey("thingspeakapikey", "Введіть ключ сервера статистики:", thingspeakApiKey, 17);
    
    WiFiManager wifiManager;  // Initialize WiFIManager
    wifiManager.setTimeout(180);
    
    if (!wifiManager.startConfigPortal()) {
    Serial.println("Not connected to WiFi but continuing anyway.");
    } 
    else {
    Serial.println("Connected...yeey :)");  // If you get here you have connected to the WiFi
    }

    wifiManager.addParameter(&p_thingspeakApiKey);
     
    // Getting posted form values and overriding local variables parameters
    // Config file is written regardless the connection state
    strcpy(thingspeakApiKey, p_thingspeakApiKey.getValue());
       
    writeConfigFile();  // Writing JSON config file to flash for next boot
    
    digitalWrite(PIN_LED, HIGH); // Turn LED off as we are not in configuration mode.
    delay(5000);
    initWindow();   // вызов функции вычисления значения порогов вкл и выкл состояния светодиода
    }



    void loop() {
    unsigned long currentMillis = millis();
    // is configuration portal requested?
   
    if (WiFi.status()!=WL_CONNECTED){
    if(currentMillis - previousMillis2 > interval) {
    previousMillis2 = currentMillis; // сохраняем время последнего переключения
    // если светодиод не горит, то зажигаем, и наоборот
    if (led == LOW)
    led = HIGH;
    else
    led = LOW;
 
    // устанавливаем состояния выхода, чтобы включить или выключить светодиод
    digitalWrite(PIN_LED, led);
    }
    }
    else{
    digitalWrite(PIN_LED, HIGH);
    }

    dataCur = analogRead(ANALOG_PIN);               // запоминаем значение на сенсоре
    findAnalogWindow(dataCur);                      // расширяем окно, если значение выходит за его пределы
    ledStateOld = ledState;                         // сохраняем в буфер старое значение уровня сенсора
    checkLogic(dataCur);                            // оцениваем состояние сенсора и сохраняем его значение в ledState
   // if (ledState == !ledStateOld) {                 // ИНДикатор только что изменил своё состояние
   // }

    if (ledStateOld && !ledState) {                 // ИНДикатор только что загорелся
    Serial.println("o");
    }

    if (!ledStateOld && ledState) {                 // ИНДикатор только что погас
    Serial.println("*");
    closeAnalogWindow();                          // ужимаем пороги окна сенсора, чтобы они хронически не росли.
    min_count++;
    }
    
    if ((currentMillis - previousMillis) == 60000) {
    Serial.print("blink #=");
    Serial.println(min_count);
    Serial.print("min_power=");
    min_power = min_count*0.3125;
    Serial.println(min_power);
    previousMillis = currentMillis;
    min_count = 0;
    }
    ESP.wdtFeed();

     if (currentMillis >= (starttime1 + 180000)) {
     starttime1 = currentMillis;
     ThingSpeak.setField(fieldStart,temp);
     ThingSpeak.writeFields(myChannelNumber, thingspeakApiKey);  //Write fields to Thingspeak, comment this line out if you wish to test without uploading data.
     Serial.println("Data sent to ThinkSpeak");
     }
     }

     bool readConfigFile() {
     // this opens the config file in read-mode
     File f = SPIFFS.open(CONFIG_FILE, "r");
  
     if (!f) {
     Serial.println("Configuration file not found");
     return false;
     } else {
     // we could open the file
     size_t size = f.size();
     // Allocate a buffer to store contents of the file.
     std::unique_ptr<char[]> buf(new char[size]);

     // Read and store file contents in buf
     f.readBytes(buf.get(), size);
     // Closing file
     f.close();
 
     DynamicJsonBuffer jsonBuffer;
     // Parse JSON string
     JsonObject& json = jsonBuffer.parseObject(buf.get());
     // Test if parsing succeeds.
     if (!json.success()) {
      Serial.println("JSON parseObject() failed");
      return false;
     }
     json.printTo(Serial);

     // Parse all config file parameters, override 
     // local config variables with parsed values
     if (json.containsKey("thingspeakApiKey")) {
     strcpy(thingspeakApiKey, json["thingspeakApiKey"]);      
     }
     }

    
     Serial.println("\nConfig file was successfully parsed");
     return true;
     }

     bool writeConfigFile() {
     Serial.println("Saving config file");
     DynamicJsonBuffer jsonBuffer;
     JsonObject& json = jsonBuffer.createObject();

     // JSONify local configuration parameters
     json["thingspeakApiKey"] = thingspeakApiKey;
   
     // Open file for writing
     File f = SPIFFS.open(CONFIG_FILE, "w");
     if (!f) {
     Serial.println("Failed to open config file for writing");
     return false;
     }

     json.prettyPrintTo(Serial);
     // Write data to file and close it
     json.printTo(f);
     f.close();

     Serial.println("\nConfig file was successfully saved");
     return true;
     }

    void initWindow() {
    unsigned long startTimer = millis() + 5000;
    while (millis() < startTimer) {
    dataCur = analogRead(ANALOG_PIN);
    findAnalogWindow(dataCur);
    }
    }

    void findAnalogWindow(int analogData) {
    if (analogData > winHi) winHi = analogData;         // запомнить значение как верхнее, если оно выше него
    if (analogData < winLo) winLo = analogData;         // запомнить значение как нижнее, если оно ниже него
    }

    void closeAnalogWindow() {
    if (winLo < winHi - 30) {
    int winDif = (winHi - winLo) ;                    // вычисляем ширину окна
    winHi = winHi - (winDif / CLOSE_WIN_FACTOR);      // вычитаем 1/10 ширины из верхнего порога
    winLo = winLo + (winDif / CLOSE_WIN_FACTOR);      // прибавляем 1/10 ширины к нижнему порогу
    }
    }

    void checkLogic(int analogData) {
    if (winLo < winHi - 5) {
    int percCur = map(analogData, winLo, winHi, 0, 99); // переводим значение в проценты от шкалы
    if (percCur <= 33) ledState = 0;
    if (percCur >= 66) ledState = 1;
    }
    }

 

Спасибо за подсказку.

kalapanga
Offline
Зарегистрирован: 23.10.2016

Правильно объявлять функцию ДО её использования. Перенесите Ваши функции наверх.

lues
Offline
Зарегистрирован: 10.06.2016

я не вьехал в структуру происходящего в функции

спасибо за помощь

bwn
Offline
Зарегистрирован: 25.08.2014

И вы уверены, что нигде с фигурными скобками не накосячили?

RA
Offline
Зарегистрирован: 19.12.2017

народ выручайте. не могу понять что не так.

Aduino pro micro M590. суть проблемы в следующем. если отправлять запрос баланса mySerial.println("ATD#100#;")

из функции void loop() то все отлично, приходит OK далее ответ с балансом. Либо через терминал командой money или bal тоже все отлично. Но если отправляю эту комманду из своей функции т.е шлю СМС Money то ERROR и соответственно ничего не приходит.

По поводу команды, то пробовал и так mySerial.println("AT+CUSD=1,\"#100#\"");

Свою функцию вывел из-за разрастания основного тела команды.

RA
Offline
Зарегистрирован: 19.12.2017
#include <Wire.h>               // библиотека для работы с шиной I²C
#include <LiquidCrystal_I2C.h>  // библиотека для работы LCD1602_I²C
#include <SoftwareSerial.h>     // библиотека для работы с Программным последовательным портом
#include <OneWire.h>            // библиотека для работы с шиной 1Wire
#include <DallasTemperature.h>  // библиотека для работы с датчиком темперутуры DS18B20
#include "TroykaRTC.h"          // библиотека для работы с часами реального времени
#include "EEPROM.h"             // библиотека для работы EEPROM

#define cusd "AT+CUSD=1,\"#100#\"" // от безнадеги вставил, один хер не работает
#define ONE_WIRE_BUS 8
#define LEN_TIME 12             // размер массива для времени
#define LEN_DATE 12             // размер массива для даты
#define LEN_DOW 12              // размер массива для дня недели
RTC clock;                      // создаём объект для работы с часами реального времени
char time[LEN_TIME];            // массив для хранения текущего времени
char date[LEN_DATE];            // массив для хранения текущей даты
char weekDay[LEN_DOW];          // массив для хранения текущего дня недели

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress Thermometer1 = {0x28, 0xFF, 0x9E, 0xF4, 0x6E, 0x14, 0x04, 0xC5 };  // адрес датчика DS18B20 28FF9EF46E1404C5
//DeviceAddress Thermometer1 = {0x28, 0xFF, 0xC8, 0x02, 0x6F, 0x14, 0x04, 0x1F };  // адрес датчика DS18B20 28FFC8026F14041F

SoftwareSerial mySerial(2, 3);      // TX, RX
LiquidCrystal_I2C lcd(0x27,16,2);   // Устанавливаем адрес LCD_I²C 0x27 для 16 символов в 2 строки

String Admin = "";
int ch = 0;
byte m = 0;

int Random = 0;              // переменная для генерации случайного числа в диапазоне 0 - 32000
String RanPass = "";
int tempC = 0;
int tempCOld = 0;
String tempCsms = "";
String Status = "";          //переменная для хранения СТАТУСА(используется при формировании СМС)
String val = "";             //переменная для хранения Порт <=> GSM
byte pind4 = 4;              //объявляем переменные портов для реле
byte pind5 = 5;              //объявляем переменные портов для реле
bool pin4 = HIGH;            //объявляем БУЛЕВЫЕ переменные портов для ОТРИСОВКИ
bool pin5 = HIGH;            //объявляем БУЛЕВЫЕ переменные портов для ОТРИСОВКИ
byte nowminute = 14;
byte nowhour = 11;

//String MASTERSMS = "";
//String MASTERRING = "";

byte k1x[8] = {0b00010,0b00110,0b00010,0b00010,0b00111,0b10100,0b01000,0b10100};     // 1й канал ВЫКЛ
byte k1v[8] = {0b00010,0b00110,0b00010,0b00010,0b00111,0b10100,0b10100,0b01000};     // 1й канал ВКЛ
byte k2x[8] = {0b00111,0b00001,0b00010,0b00100,0b00111,0b10100,0b01000,0b10100};     // 2й канал ВЫКЛ
byte k2v[8] = {0b00111,0b00001,0b00010,0b00100,0b00111,0b10100,0b10100,0b01000};     // 2й канал ВКЛ
byte gradusc[8] = {0b11000,0b11000,0b00110,0b01001,0b01000,0b01001,0b00110,0b00000}; // создаем свой символ градус Цельсия





//########################################################################################################
//########################################################################################################
void setup() {
  
  Serial.begin(9600);         //скорость порта
  Wire.begin();
  clock.begin();              // инициализация часов
//метод установки времени и даты в модуль вручную
//clock.set(11,13,45,27,10,2017,FRIDAY);
//метод установки времени и даты автоматически при компиляции
//clock.set(__TIMESTAMP__); 
  mySerial.begin(9600);       // устанавливаем скорость порта модуля GSM
  sensors.begin();
  sensors.setResolution(Thermometer1, 10);

  delay(30);
  pinMode(pind4, OUTPUT);     //конфигурируем порт D4 на выход для реле
  pinMode(pind5, OUTPUT);     //конфигурируем порт D5 на выход для реле
  digitalWrite(pind4, HIGH);  //выключаем все подтягивающие резисторы, чтобы исключить
  digitalWrite(pind5, HIGH);  //не преднамеренное включение реле при старте
  randomSeed(analogRead(0));  //для функции RANDOM чтение A0 
  lcd.init();                 //запускаем lcd
  lcd.backlight();            //включаем подстветку
  lcd.createChar(0, gradusc); //создаем символ "ГРАДУС"
//для 2х каналов
  lcd.createChar(1, k1x);     //создаем символ
  lcd.createChar(2, k1v);     //создаем символ
  lcd.createChar(3, k2x);     //создаем символ
  lcd.createChar(4, k2v);     //создаем символ
    
  lcd.setCursor(0,0);
  lcd.print("***** GSM ******");
  lcd.setCursor(0,1);
  lcd.print("** COMMUTATOR **");
  delay(2000);  // задержка
  
  lcd.clear();
  lcd.setCursor(9,1); 
  lcd.print(char(0));         // печатаем символ на первой строке
  lcd.setCursor(0,1);
  lcd.print(char(1));
  lcd.setCursor(1,1);
  lcd.print(char(3));


  ModemInit();
  
}
//################################################################################
//####################### Функция Инициализации МОДЕМа ###########################
//################################################################################
void ModemInit() {   
//Serial.println("GSM ALARM&COMMUTATION SYSTEM"); // выводим в порn
//Serial.print("Turn off EHO: ");
mySerial.println("ATE0");                // выключаем эхо
delay(600);
     ava();
//Serial.print("Turn on AOH: ");
mySerial.println("AT+CLIP=1");    //включаем АОН
delay(600);
     ava();
         
//Serial.print("Text format sms: "); // текстовый формат SMS
mySerial.println("AT+CMGF=1");    // режим кодировки СМС - обычный (для англ.)
delay(600);
     ava();
        
//Serial.print("Mode GSM:");
mySerial.println("AT+CSCS=\"GSM\"");  //режим кодировки текста
delay(600);
     ava();
       
//Serial.print("SMS to terminal: ");
mySerial.println("AT+CNMI=2,2,0,0,0");     // вывод смс в консоль
//mySerial.print("AT+CNMI=3,2,2,0,1\r"); // вывод смс в консоль
delay(600);
     ava();
       
//Serial.print("Delete All SMS on SIM card: ");
mySerial.println("AT+CMGD=1,4");  // удаление всех SMS с SIM карты
delay(600);
     ava();

//Serial.print("Sofrware control: ");     
//mySerial.print("AT+IFC=1, 1\r"); // устанавливает программный контроль потоком передачи данных 
//delay(600);
//     ava();
       
//Serial.print("Level of signal: ");
mySerial.println("AT+CSQ");  //вывести в терминал уровень сигнала (если 99, то связи нет)
delay(600);
     ava();
}
//################################################################################
//#######################   ___L___O___O___P___   ################################
//################################################################################ 
void loop() { 
masterget();
//sensors.requestTemperatures();
//printTemperature(Thermometer1);
//datetime();
//********************* ОТ SERIAL ************************************  
if(Serial.available())  //если в мониторе порта ввели что-то
  { Serial.print("SERIALtoGSM "); 
     char ch = ' ';
     String val = "";
     while (Serial.available()) 
      { ch = Serial.read();
        val += char(ch); //собираем принятые символы в строку
        delay(3);
      }
      
    Serial.println(val);
    if(val.indexOf("call") > -1)             // своя команда
     { mySerial.println("ATD+70000000000;"); // МАСТЕР_номер, на который нужно позвонить
       //Serial.println("CALL ATD+");
     }
    else if(val.indexOf("reset") > -1)       // своя команда
     { m = 2; masterget(); }
    else if(val.indexOf("balance") > -1 || val.indexOf("money") > -1)
     { //mySerial.println(cusd);}
        mySerial.println("ATD#100#;"); }  
    else mySerial.println(val);  // передача всего, что набрано в терминале в GSM модуль
  }

//********************* ОТ GSM ************************************
if (mySerial.available())
  { Serial.print("GSMtoSERIAL ");  
    char ch = ' ';
    String val = "";
    while(mySerial.available()) 
      { ch = mySerial.read();
        val += char(ch); //собираем принятые символы в строку
        Serial.print(char(ch));
        //Serial.print((char)mySerial.read());
        delay(3);
      }
//******************** RING ***************************************
    if (val.indexOf("RING") > -1)   //если звонок обнаружен, то проверяем номер
     {  if (val.indexOf(Admin) > -1) //если номер звонящего наш без +
             { Serial.println("--- MASTER RING DETECTED ---");
               lcd.setCursor(0,0);
               lcd.print("** MasterRing **");
               mySerial.println("ATH");  //разрываем связь
               delay(600);
               ava();
               lcd.clear();
               smsbuild(pin4, pin5); }
        else { Serial.println("WRONG!NUMBER");  
               mySerial.println("ATH");  //разрываем связь
               lcd.setCursor(0,0);
               lcd.print("** BAD NUMBER **");
               delay(1000);
               ava();
               lcd.clear(); }
     }
//******************** SMS ***************************************
    else if (val.indexOf("+CMT") > -1) // если есть входящее sms
     {   if (val.indexOf(Admin) > -1)  // проверяем МАСТЕР_НОМЕР
            {  smsadmin(val); }
         else {smsunknow(val);  }

     } 
//******************** BALANCE ***************************************
    if(val.indexOf("+CUSD") > -1) // если есть входящее sms
     { Serial.println("+CUSD TRUE");
       if(val.indexOf("Balance") > -1) // смотрим, что за команда
        { Serial.println("BALANCE TRUE"); 
          Status = val.substring(val.indexOf("Balance"),val.indexOf("r")); 
          sms(Status, Admin); 
        }     
     }   
  }
}

//##############################################################################
//####### Функция извлекает из EEPROM МАСТЕР_номер в String_Admin ##############
//##############################################################################
void masterget() {
  if(m == 0)
        { char c[13];       // переменная для хранения массива из 12 символов
          EEPROM.get(0, c); // считываем массив символов по адресу 0 
          String MASTERSMS(c);
          String MASTERRING = (MASTERSMS.substring(1,12));
          Admin = MASTERRING;
          Serial.println(Admin);
          m = 1; }
  else if(m == 2)
        { char r[13] = "+70000000000";
          EEPROM.put(0, r);  // записываем массив в EEPROM
          delay(30);  
          Serial.println("PUT"); 
          m = 0; }
  else if(m == 1)
        {}  
}
//#################################################################################
// В процедуре "smsbuild" происходит сборка сообщения состоящая из "времени,
// состояния каналов и температуры в помещении" и далее вызов функции отправки СМС
// "sms". Вызов данной функции происходит только при соответствии команды или
// звонка с МАСТЕР_НОМЕРА.
//#################################################################################
void smsbuild(bool pin4, bool pin5) {
  Serial.println("smsbuild");
  if (pin4 == LOW && pin5 == LOW) {
      Status = String(time)+" (1on-2on) temperatura= "+String(tempCsms);
      sms(Status, Admin);   //Master_НОМЕР, с которого 
                               //Вы будете звонить на модуль
  }   else if (pin4 == HIGH && pin5 == HIGH) {
          Status = String(time)+" (1off-2off) temperatura= "+String(tempCsms);   
          sms(Status, Admin);     //Master_НОМЕР, с которого            
                                     //Вы будете звонить на модуль        
  }       else if (pin4 == LOW && pin5 == HIGH) {
              Status = String(time)+" (1on-2off) temperatura= "+String(tempCsms);
              sms(Status, Admin);     //Master_НОМЕР, с которого 
                                         //Вы будете звонить на модуль
  }           else if (pin4 == HIGH && pin5 == LOW) {
                  Status = String(time)+" (1off-2on) temperatura= "+String(tempCsms);
                  sms(Status, Admin);     //Master_НОМЕР, с которого 
                                             //Вы будете звонить на модуль
  }
}
//########################################################################################
// Данная функция занимается исключительно отрисовкой состояния каналов. Состояние каналов 
// известно из переменных "pin4 pin5 pin6 pin7" для 4х канальных устройств, значения  
// которым были присвоены в функции LOOP 
//########################################################################################
void lcd1602(bool pin4, bool pin5) {
  Serial.println("lcd1602");
  if (pin4 == LOW && pin5 == LOW) 
      {  //lcd.setCursor(0,1);
         //lcd.print("1V-2V");
         lcd.setCursor(0,1);
         lcd.print(char(2));
         lcd.setCursor(1,1);
         lcd.print(char(4));  }
         else if (pin4 == HIGH && pin5 == HIGH) 
              {  //lcd.setCursor(0,1);
                 //lcd.print("1X-2X");
                 lcd.setCursor(0,1);
                 lcd.print(char(1));
                 lcd.setCursor(1,1);
                 lcd.print(char(3));  }
                 else if (pin4 == LOW && pin5 == HIGH) 
                      {  //lcd.setCursor(0,1);
                         //lcd.print("1V-2X");
                         lcd.setCursor(0,1);
                         lcd.print(char(2));
                         lcd.setCursor(1,1);
                         lcd.print(char(3));  }
                         else if (pin4 == HIGH && pin5 == LOW) 
                              {   //lcd.setCursor(0,1);
                                  //lcd.print("1X-2V");    
                                  lcd.setCursor(0,1);
                                  lcd.print(char(1));
                                  lcd.setCursor(1,1);
                                  lcd.print(char(4));  }
}
//################################################################################
//################# Функция обработки СМС_комманд от МАСТЕРа #####################
//################################################################################
void smsadmin(String val) {
             if (val.indexOf("1on") > -1)         // смотрим, что за команда
                  { digitalWrite(pind4, LOW);
                    pin4 = LOW;
                    lcd1602(pin4, pin5);
                    //delay(30);
                    smsbuild(pin4, pin5); } 
             else if (val.indexOf("2on") > -1) // смотрим, что за команда
                  { digitalWrite(pind5, LOW);
                    pin5 = LOW;
                    lcd1602(pin4, pin5);  
                    //delay(30);
                    smsbuild(pin4, pin5); }
             else if (val.indexOf("1off") > -1) // смотрим, что за команда
                  { digitalWrite(pind4, HIGH);
                    pin4 = HIGH;
                    lcd1602(pin4, pin5); 
                    //delay(30);
                    smsbuild(pin4, pin5); }
             else if (val.indexOf("2off") > -1) // смотрим, что за команда
                  { digitalWrite(pind5, HIGH);
                    pin5 = HIGH;
                    lcd1602(pin4, pin5); 
                    //delay(30);
                    smsbuild(pin4, pin5); } 
             else if (val.indexOf("Master") > -1 || val.indexOf("master") > -1 || val.indexOf("MASTER") > -1) 
                  { lcd.setCursor(0,0);
                    lcd.print("     ERROR      ");
                    lcd.setCursor(0,1);
                    lcd.print("   MASTER IS    ");
                    delay(1000);
                    lcd.clear();
                    Status = String(time)+" ERROR.MASTER Already is";
                    //Serial.println(Status);
                    sms(Status, Admin); }
             else if (val.indexOf("Money") > -1 || val.indexOf("money") > -1 || val.indexOf("MONEY") > -1 || val.indexOf("Bal") > -1) 
                  { Serial.println("MONEY TRUE"); 
                    mySerial.println("ATD#100#;"); }
             else { Status = String(time)+" ERROR.BAD Command";
                    Random = random(10000,30000);
                    RanPass = String(Random);
                    Serial.println(Status);
                    sms(Status, Admin); }
}
//################################################################################
//################# Функция обработки СМС_комманд от НЕИЗВЕСТНОГО  ###############
//################################################################################
void smsunknow(String val) {
         if (val.indexOf("Master") > -1 || val.indexOf("master") > -1 || val.indexOf("MASTER") > -1)
            { Random = random(10000,30000);
              lcd.setCursor(0,0);
              lcd.print("                ");
              lcd.setCursor(4,0);
              lcd.print(Random);
              String number = val.substring(9,21);
              Serial.println(number);
              Serial.println(Random);
              RanPass = String(Random); 
              delay(5000);
              lcd.setCursor(0,0);
              lcd.print(val.substring(10,21));
              delay(1000); }
         else if (val.indexOf(RanPass) > -1)
            { char p[13];
              lcd.setCursor(0,0);
              lcd.print("** NEW MASTER **");
              delay(1000);
              String number = val.substring(9,21);
              number.toCharArray(p, 13);
              Serial.print("** NEW MASTER **");
              Serial.println(p);
              EEPROM.put(0, p);  // записываем массив в EEPROM 
              delay(30);
              lcd.setCursor(0,1);
              lcd.print(number);
              delay(300);
              lcd.clear();
              Random = (random(10000,30000) - 259);
              RanPass = String(Random);
              m = 0; }           
         else 
            { Serial.println("E R R O R");
              lcd.setCursor(0,0);
              lcd.print("** E R R O R **");
              delay(200);
              lcd.clear();
              Random = (random(10000,30000) - 163);
              RanPass = String(Random); }
}

//################################################################################
// Данная функция вызывается при каждом новом цикле VOID LOOP и отрисовывает дату
// на LCD1602
//################################################################################
void datetime() {
  // запрашиваем данные с часов
  clock.read();
  // сохраняем текущее время, дату и день недели в переменные 
  clock.getTimeStamp(time, date, weekDay); 
  lcd.setCursor(4,0);
  lcd.print(time);
} 
//################################################################################
// Функция отправки СМС. В функцию передаются строковые переменные состоящие из
// состояния каналов - STRING Status, мастер телефон - STRING phone 
//################################################################################
void sms(String Status, String ph) { 
  ph = ("+"+String(ph));
  //Serial.println("Start SMS send"+ph);
  mySerial.println("AT+CMGS=\"" + ph + "\"");
  delay(600);
  mySerial.print(Status);
  delay(600); 
  mySerial.print((char)26);
  delay(600);
  lcd.setCursor(0,0);
  lcd.print("SMS send......OK");
  delay(600);
  Serial.print("SMS send......OK>>");
  Serial.println(Status);
  //mySerial.println("AT+CMGD=1");        //стираем память смс
  //delay(300);
  lcd.setCursor(0,0);
  lcd.print("                ");
}
//##############################################################################
// Функция служит лишь для быстрого вывода в SERIAL порт ответа
//##############################################################################
void ava() {
  while(mySerial.available()) 
      { Serial.print((char)mySerial.read());
      }//  delay(); }
}

 

b707
Offline
Зарегистрирован: 26.05.2017

RA пишет:

Свою функцию вывел из-за разрастания основного тела команды.

что-то я не нашел в коде отдельной функции для баланса.

И непонятно. зачем после команды ATD#100# посылать в модем кучу мусора из сериала? - вот наверно на все эти "money" и 'balance' и приходит ЕГГОГ

RA
Offline
Зарегистрирован: 19.12.2017

smsadmin() полностью была в loop'е после 216. 

Для баланса нет. Есть обработчик СМС команд в smsadmin()

RA
Offline
Зарегистрирован: 19.12.2017

какая строка?

b707
Offline
Зарегистрирован: 26.05.2017

RA пишет:

smsadmin() полностью была в loop'е после 216. 

Для баланса нет. Есть обработчик СМС команд в smsadmin()

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

Проблемы скорее всего обьясняются нехваткой памяти, с которой (с памятью) вы образаетесь очень неэкономно. У вас в программе изначально большое количество строк - как констант, так и переменных класса String. И вы даже не пытаетесь уменьшить занимаемый ими обьем памяти- например положить во флеш, или избавиться от многократных сравнений строк в разном регистре. Вместо этого вы добавляете новую функцию, копируя в нее длинную строку val по значению! - это как выстрелить самому себе в ногу.

Что надо сделать в первую очередь

1. - во все функции smsadmin() smsunknown(). в которые передается длинное входящее СМС - его надо передавать по ссылке, а не копировать по значению

2. Все строковые константы уберите во флешпамять

3. Прежде чем искать во входящей строке подстроки, переведите все в верхний или нижний регистр - тогда не нужно будет искать отдельно "Money" "MONEY" b "money". Или воспользуйтесь функциями поиска подстрок без учета регистра.

4. Избавьтесь от переменных типа String (рекомендация)

RA
Offline
Зарегистрирован: 19.12.2017

Спасибо.

Тоже думал о памяти НО компилятор не ругается.

По поводу строковых констант это временно для отладки.

Можно еще "разжевать" по поводу первого пункта. Имееться ввиду *использовать указатель?

RA
Offline
Зарегистрирован: 19.12.2017

Нарооооооооооооооооооод.

ну давайте РЕПУ почешем.

Убрал все что можно.

Скетч использует 16352 байт (53%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 1229 байт (60%) динамической памяти, оставляя 819 байт для локальных переменных.
 
Что происходит непойму.
RA
Offline
Зарегистрирован: 19.12.2017

даже так

Скетч использует 15316 байт (49%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 1107 байт (54%) динамической памяти, оставляя 941 байт для локальных переменных. Максимум: 2048 байт.
b707
Offline
Зарегистрирован: 26.05.2017

RA пишет:

Что происходит непойму.

Я вам написал. что происходит. Вы хоть один из пунктов. что я перечислил - пытались поправить? Пока не исправите - какой смысл вам что-то еще советовать?

Сейчас не поленился. подсчитал - у вас одни строковые константы в кавычках уже отжирают около 650 байтов оперативки! - треть всей доступной памяти!

RA
Offline
Зарегистрирован: 19.12.2017

все пункты выполнил

кроме 4

RA
Offline
Зарегистрирован: 19.12.2017
#include <Wire.h>               // библиотека для работы с шиной I²C
#include <LiquidCrystal_I2C.h>  // библиотека для работы LCD1602_I²C
#include <SoftwareSerial.h>     // библиотека для работы с Программным последовательным портом
#include <OneWire.h>            // библиотека для работы с шиной 1Wire
#include <DallasTemperature.h>  // библиотека для работы с датчиком темперутуры DS18B20
#include "TroykaRTC.h"          // библиотека для работы с часами реального времени
#include "EEPROM.h"             // библиотека для работы EEPROM

//#define cusd "AT+CUSD=1,\"#100#\""
#define ONE_WIRE_BUS 8
#define LEN_TIME 12             // размер массива для времени
#define LEN_DATE 12             // размер массива для даты
#define LEN_DOW 12              // размер массива для дня недели
RTC clock;                      // создаём объект для работы с часами реального времени
char time[LEN_TIME];            // массив для хранения текущего времени
char date[LEN_DATE];            // массив для хранения текущей даты
char weekDay[LEN_DOW];          // массив для хранения текущего дня недели

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress Thermometer1 = {0x28, 0xFF, 0x9E, 0xF4, 0x6E, 0x14, 0x04, 0xC5 };  // адрес датчика DS18B20 28FF9EF46E1404C5
//DeviceAddress Thermometer1 = {0x28, 0xFF, 0xC8, 0x02, 0x6F, 0x14, 0x04, 0x1F };  // адрес датчика DS18B20 28FFC8026F14041F

SoftwareSerial mySerial(2, 3);      // TX, RX
LiquidCrystal_I2C lcd(0x27,16,2);   // Устанавливаем адрес LCD_I²C 0x27 для 16 символов в 2 строки

String Admin = "";
int ch = 0;
byte m = 0;

int Random = 0;              // переменная для генерации случайного числа в диапазоне 0 - 32000
String RanPass = "";
int tempC = 0;
int tempCOld = 0;
String tempCsms = "";
String Status = "";          //переменная для хранения СТАТУСА(используется при формировании СМС)
String val = "";             //переменная для хранения Порт <=> GSM
byte pind4 = 4;              //объявляем переменные портов для реле
byte pind5 = 5;              //объявляем переменные портов для реле
bool pin4 = HIGH;            //объявляем БУЛЕВЫЕ переменные портов для ОТРИСОВКИ
bool pin5 = HIGH;            //объявляем БУЛЕВЫЕ переменные портов для ОТРИСОВКИ
byte nowminute = 14;
byte nowhour = 11;

byte k1x[8] = {0b00010,0b00110,0b00010,0b00010,0b00111,0b10100,0b01000,0b10100};     // 1й канал ВЫКЛ
byte k1v[8] = {0b00010,0b00110,0b00010,0b00010,0b00111,0b10100,0b10100,0b01000};     // 1й канал ВКЛ
byte k2x[8] = {0b00111,0b00001,0b00010,0b00100,0b00111,0b10100,0b01000,0b10100};     // 2й канал ВЫКЛ
byte k2v[8] = {0b00111,0b00001,0b00010,0b00100,0b00111,0b10100,0b10100,0b01000};     // 2й канал ВКЛ
byte gradusc[8] = {0b11000,0b11000,0b00110,0b01001,0b01000,0b01001,0b00110,0b00000}; // создаем свой символ градус Цельсия

//########################################################################################################
//########################################################################################################
void setup() {
  
  Serial.begin(9600);         //скорость порта
  Wire.begin();
  clock.begin();              // инициализация часов
//метод установки времени и даты в модуль вручную
//clock.set(11,13,45,27,10,2017,FRIDAY);
//метод установки времени и даты автоматически при компиляции
//clock.set(__TIMESTAMP__); 
  mySerial.begin(9600);       // устанавливаем скорость порта модуля GSM
  sensors.begin();
  sensors.setResolution(Thermometer1, 10);

  delay(30);
  pinMode(pind4, OUTPUT);     //конфигурируем порт D4 на выход для реле
  pinMode(pind5, OUTPUT);     //конфигурируем порт D5 на выход для реле
  digitalWrite(pind4, HIGH);  //выключаем все подтягивающие резисторы, чтобы исключить
  digitalWrite(pind5, HIGH);  //не преднамеренное включение реле при старте
  randomSeed(analogRead(0));  //для функции RANDOM чтение A0 
  lcd.init();                 //запускаем lcd
  lcd.backlight();            //включаем подстветку
  lcd.createChar(0, gradusc); //создаем символ "ГРАДУС"
//для 2х каналов
  lcd.createChar(1, k1x);     //создаем символ
  lcd.createChar(2, k1v);     //создаем символ
  lcd.createChar(3, k2x);     //создаем символ
  lcd.createChar(4, k2v);     //создаем символ
    
  lcd.setCursor(0,0);
  lcd.print(F("***** GSM ******"));
  lcd.setCursor(0,1);
  lcd.print(F("** COMMUTATOR **"));
  delay(2000);  // задержка
  
  lcd.clear();
  lcd.setCursor(9,1); 
  lcd.print(char(0));         // печатаем символ на первой строке
  lcd.setCursor(0,1);
  lcd.print(char(1));
  lcd.setCursor(1,1);
  lcd.print(char(3));

  Random = random(10000,30000);

  ModemInit();
  
}
//################################################################################
//####################### Функция Инициализации МОДЕМа ###########################
//################################################################################
void ModemInit() {   
//Serial.println(F("GSM ALARM&COMMUTATION SYSTEM")); // выводим в порn
//Serial.print(F("Turn off EHO: "));
mySerial.println("ATE0");                // выключаем эхо
delay(600);
     ava();
//Serial.print(F("Turn on AOH: "));
mySerial.println("AT+CLIP=1");    //включаем АОН
delay(600);
     ava();
         
//Serial.print(F("Text format sms: ")); // текстовый формат SMS
mySerial.println("AT+CMGF=1");    // режим кодировки СМС - обычный (для англ.)
delay(600);
     ava();
        
//Serial.print(F("Mode GSM:"));
mySerial.println("AT+CSCS=\"GSM\"");  //режим кодировки текста
delay(600);
     ava();
       
//Serial.print(F("SMS to terminal: "));
mySerial.println("AT+CNMI=2,2,0,0,0");     // вывод смс в консоль
//mySerial.print("AT+CNMI=3,2,2,0,1\r"); // вывод смс в консоль
delay(600);
     ava();
       
//Serial.print(F("Delete All SMS on SIM card: "));
mySerial.println("AT+CMGD=1,4");  // удаление всех SMS с SIM карты
delay(600);
     ava();

//Serial.print(F("Sofrware control: "));     
//mySerial.print("AT+IFC=1, 1\r"); // устанавливает программный контроль потоком передачи данных 
//delay(600);
//     ava();
       
//Serial.print(F("Level of signal: "));
mySerial.println("AT+CSQ");  //вывести в терминал уровень сигнала (если 99, то связи нет)
delay(600);
     ava();
}
//################################################################################
//#######################   ___L___O___O___P___   ################################
//################################################################################ 
void loop() { 
masterget();
//sensors.requestTemperatures();
//printTemperature(Thermometer1);
//datetime();
//********************* ОТ SERIAL ************************************  
if(Serial.available())  //если в мониторе порта ввели что-то
  {  Serial.print(F("SERIALtoGSM ")); 
     char ch = ' ';
     String val = "";
     while (Serial.available()) 
      { ch = Serial.read();
        val += char(ch); //собираем принятые символы в строку
        delay(3);
      }
      
    Serial.println(val);
    if(val.indexOf("call") > -1)               // своя команда
     { mySerial.println("ATD+70000000000;"); } // МАСТЕР_номер, на который нужно позвонить
    else if(val.indexOf("reset") > -1)         // своя команда
     { m = 2; masterget(); }
    else if(val.indexOf("balance") > -1 || val.indexOf("money") > -1)
     { //mySerial.println(cusd);}
         mySerial.println("ATD#100#;"); }  
    else mySerial.println(val);  // передача всего, что набрано в терминале в GSM модуль
  }

//********************* ОТ GSM ************************************
if (mySerial.available())
  { Serial.print(F("GSMtoSERIAL "));  
    char ch = ' ';
    String val = "";
    while(mySerial.available()) 
      { ch = mySerial.read();
        val += char(ch); //собираем принятые символы в строку
        Serial.print(char(ch));
        delay(3);
      }
//******************** RING ***************************************
    if (val.indexOf("RING") > -1)    //если звонок обнаружен, то проверяем номер
     {  if (val.indexOf(Admin) > -1) //если номер звонящего наш без +
             { Serial.println(F("--- MASTER RING DETECTED ---"));
               lcd.setCursor(0,0);
               lcd.print("** MasterRing **");
               mySerial.println("ATH");  //разрываем связь
               delay(600);
               ava();
               lcd.clear();
               smsbuild(pin4, pin5); }
        else { Serial.println(F("WRONG!NUMBER"));  
               mySerial.println("ATH");  //разрываем связь
               lcd.setCursor(0,0);
               lcd.print(F("** BAD NUMBER **"));
               delay(1000);
               ava();
               lcd.clear(); }
     }
//******************** SMS ***************************************
    else if (val.indexOf("+CMT") > -1) // если есть входящее sms
     {   if (val.indexOf(Admin) > -1)  // проверяем МАСТЕР_НОМЕР
            {  smsadmin(val); }
         else {smsunknow(val);  }

     } 
//******************** BALANCE ***************************************
    if(val.indexOf("+CUSD") > -1)             // если есть входящее sms
     { if(val.indexOf("Balance") > -1)        // смотрим, что за команда
        { Serial.println(F("BALANCE TRUE"));  // Просто МЕТКА
          Status = val.substring(val.indexOf("Balance"),val.indexOf("r")); 
          sms(Status, Admin); 
        }     
     }   
  }
}

//##############################################################################
//####### Функция извлекает из EEPROM МАСТЕР_номер в String_Admin ##############
//##############################################################################
void masterget() {
  if(m == 0)
        { char c[13];       // переменная для хранения массива из 12 символов
          EEPROM.get(0, c); // считываем массив символов по адресу 0 
          String MASTERSMS(c);
          MASTERSMS = (MASTERSMS.substring(1,12));
          Admin = MASTERSMS;
          Serial.println(Admin);
          m = 1; }
  else if(m == 2)
        { char r[13] = "+70000000000";
          EEPROM.put(0, r);  // записываем массив в EEPROM
          delay(30);  
          Serial.println("PUT"); 
          m = 0; }
  else if(m == 1)
        {}  
}
//#################################################################################
// В процедуре "smsbuild" происходит сборка сообщения состоящая из "времени,
// состояния каналов и температуры в помещении" и далее вызов функции отправки СМС
// "sms". Вызов данной функции происходит только при соответствии команды или
// звонка с МАСТЕР_НОМЕРА.
//#################################################################################
void smsbuild(bool pin4, bool pin5) {
  if (pin4 == LOW && pin5 == LOW) {
      Status = String(time)+" (1on-2on) temperatura= "+String(tempCsms);
      sms(Status, Admin);   //Master_НОМЕР, с которого 
                               //Вы будете звонить на модуль
  }   else if (pin4 == HIGH && pin5 == HIGH) {
          Status = String(time)+" (1off-2off) temperatura= "+String(tempCsms);   
          sms(Status, Admin);     //Master_НОМЕР, с которого            
                                     //Вы будете звонить на модуль        
  }       else if (pin4 == LOW && pin5 == HIGH) {
              Status = String(time)+" (1on-2off) temperatura= "+String(tempCsms);
              sms(Status, Admin);     //Master_НОМЕР, с которого 
                                         //Вы будете звонить на модуль
  }           else if (pin4 == HIGH && pin5 == LOW) {
                  Status = String(time)+" (1off-2on) temperatura= "+String(tempCsms);
                  sms(Status, Admin);     //Master_НОМЕР, с которого 
                                             //Вы будете звонить на модуль
  }
}
//########################################################################################
// Данная функция занимается исключительно отрисовкой состояния каналов. Состояние каналов 
// известно из переменных "pin4 pin5 pin6 pin7" для 4х канальных устройств, значения  
// которым были присвоены в функции LOOP 
//########################################################################################
void lcd1602(bool pin4, bool pin5) {
  if (pin4 == LOW && pin5 == LOW) 
      {  //lcd.setCursor(0,1);
         //lcd.print("1V-2V");
         lcd.setCursor(0,1);
         lcd.print(char(2));
         lcd.setCursor(1,1);
         lcd.print(char(4));  }
         else if (pin4 == HIGH && pin5 == HIGH) 
              {  //lcd.setCursor(0,1);
                 //lcd.print("1X-2X");
                 lcd.setCursor(0,1);
                 lcd.print(char(1));
                 lcd.setCursor(1,1);
                 lcd.print(char(3));  }
                 else if (pin4 == LOW && pin5 == HIGH) 
                      {  //lcd.setCursor(0,1);
                         //lcd.print("1V-2X");
                         lcd.setCursor(0,1);
                         lcd.print(char(2));
                         lcd.setCursor(1,1);
                         lcd.print(char(3));  }
                         else if (pin4 == HIGH && pin5 == LOW) 
                              {   //lcd.setCursor(0,1);
                                  //lcd.print("1X-2V");    
                                  lcd.setCursor(0,1);
                                  lcd.print(char(1));
                                  lcd.setCursor(1,1);
                                  lcd.print(char(4));  }
}
//################################################################################
//################# Функция обработки СМС_комманд от МАСТЕРа #####################
//################################################################################
void smsadmin(String v) {
             if (v.indexOf("1on") > -1)         // смотрим, что за команда
                  { digitalWrite(pind4, LOW);
                    pin4 = LOW;
                    lcd1602(pin4, pin5);
                    //delay(30);
                    smsbuild(pin4, pin5); } 
             else if (v.indexOf("2on") > -1) // смотрим, что за команда
                  { digitalWrite(pind5, LOW);
                    pin5 = LOW;
                    lcd1602(pin4, pin5);  
                    //delay(30);
                    smsbuild(pin4, pin5); }
             else if (v.indexOf("1off") > -1) // смотрим, что за команда
                  { digitalWrite(pind4, HIGH);
                    pin4 = HIGH;
                    lcd1602(pin4, pin5); 
                    //delay(30);
                    smsbuild(pin4, pin5); }
             else if (v.indexOf("2off") > -1) // смотрим, что за команда
                  { digitalWrite(pind5, HIGH);
                    pin5 = HIGH;
                    lcd1602(pin4, pin5); 
                    //delay(30);
                    smsbuild(pin4, pin5); } 
             else if (v.indexOf("Master") > -1)// || v.indexOf("master") > -1 || v.indexOf("MASTER") > -1) 
                  { lcd.setCursor(0,0);
                    lcd.print("     ERROR      ");
                    lcd.setCursor(0,1);
                    lcd.print("   MASTER IS    ");
                    delay(1000);
                    lcd.clear();
                    Status = String(time)+" ERROR.MASTER Already is";
                    //Serial.println(Status);
                    sms(Status, Admin); }
             else if (v.indexOf("Money") > -1) // || val.indexOf("money") > -1 || val.indexOf("MONEY") > -1 || val.indexOf("Bal") > -1) 
                  { Serial.println(F("MONEY TRUE")); 
                    mySerial.println("ATD#100#;"); }
             else { Status = String(time)+" ERROR.BAD Command";
                    Random = random(10000,30000);
                    RanPass = String(Random);
                    //Serial.println(Status);
                    sms(Status, Admin); }
}
//################################################################################
//################# Функция обработки СМС_комманд от НЕИЗВЕСТНОГО  ###############
//################################################################################
void smsunknow(String v) {
         if (v.indexOf("Master") > -1 || v.indexOf("master") > -1 || v.indexOf("MASTER") > -1)
            { Random = random(10000,30000);
              lcd.setCursor(0,0);
              lcd.print("                ");
              lcd.setCursor(4,0);
              lcd.print(Random);
              String number = v.substring(9,21);
              Serial.println(number);
              Serial.println(Random);
              RanPass = String(Random); 
              delay(5000);
              lcd.setCursor(0,0);
              lcd.print(v.substring(10,21));
              delay(1000); }
         else if (v.indexOf(RanPass) > -1)
            { char p[13];
              lcd.setCursor(0,0);
              lcd.print(F("** NEW MASTER **"));
              delay(1000);
              String number = v.substring(9,21);
              number.toCharArray(p, 13);
              Serial.print(F("** NEW MASTER **"));
              Serial.println(p);
              EEPROM.put(0, p);  // записываем массив в EEPROM 
              delay(30);
              lcd.setCursor(0,1);
              lcd.print(number);
              delay(300);
              lcd.clear();
              Random = (random(10000,30000) - 259);
              RanPass = String(Random);
              m = 0; }           
         else 
            { Serial.println(F("E R R O R"));
              lcd.setCursor(0,0);
              lcd.print(F("** E R R O R **"));
              delay(200);
              lcd.clear();
              Random = (random(10000,30000) - 163);
              RanPass = String(Random); }
}

//################################################################################
// Данная функция вызывается при каждом новом цикле VOID LOOP и отрисовывает дату
// на LCD1602
//################################################################################
void datetime() {
  // запрашиваем данные с часов
  clock.read();
  // сохраняем текущее время, дату и день недели в переменные 
  clock.getTimeStamp(time, date, weekDay); 
  lcd.setCursor(4,0);
  lcd.print(time);
} 
//################################################################################
// Функция отправки СМС. В функцию передаются строковые переменные состоящие из
// состояния каналов - STRING Status, мастер телефон - STRING phone 
//################################################################################
void sms(String Status, String ph) { 
  ph = ("+"+String(ph));
  //Serial.println("Start SMS send"+ph);
  //mySerial.println("AT+CMGS=\"" + ph + "\"");
  delay(600);
  //mySerial.print(Status);
  delay(600); 
  //mySerial.print((char)26);
  delay(600);
  lcd.setCursor(0,0);
  lcd.print("SMS send......OK");
  delay(600);
  Serial.print(F("SMS send......OK>>"));
  Serial.println(Status);
  //mySerial.println("AT+CMGD=1");        //стираем память смс
  //delay(300);
  lcd.setCursor(0,0);
  lcd.print(F("                "));
}
//##############################################################################
// Функция служит лишь для быстрого вывода в SERIAL порт ответа
//##############################################################################
void ava() {
  while(mySerial.available()) 
      { Serial.print((char)mySerial.read());
      }//  delay(); }
}

 

b707
Offline
Зарегистрирован: 26.05.2017

RA пишет:

все пункты выполнил

кроме 4

пункт 1 - не выполнен

пункт 2 - процентов на 10%, не больше

пункт 3 - сделано совсем не то. что я писал... ну фиг с вами

пункт 4 - 0%

Я не пойму - вы как двоечник на экзамене, пытаетесь у учителя "выпросить" тройку? - да фиг с вами, не делайте совсем...

RA
Offline
Зарегистрирован: 19.12.2017
//##############################################################################
//####### Функция извлекает из EEPROM МАСТЕР_номер в String_Admin ##############
//##############################################################################
void masterget() {
  if(m == 0)
        { char c[13];       // переменная для хранения массива из 12 символов
          EEPROM.get(0, c); // считываем массив символов по адресу 0 
          String Admin(c);
          Admin = (Admin.substring(1,12));
          Serial.println(Admin);
          m = 1; }
  else if(m == 2)
        { char r[13] = "+70000000000";
          EEPROM.put(0, r);  // записываем массив в EEPROM
          delay(30);  
          Serial.println("PUT"); 
          m = 0; }
  else if(m == 1)
        {}  
}

 

RA
Offline
Зарегистрирован: 19.12.2017

Избавился от ДВУХ строк

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Неужели ТАК СЛОЖНО каждую строку завернуть в F(), и не тупить?

RA
Offline
Зарегистрирован: 19.12.2017
//################################################################################
//####################### Функция Инициализации МОДЕМа ###########################
//################################################################################
void ModemInit() {   
//Serial.println(F("GSM ALARM&COMMUTATION SYSTEM")); // выводим в порn
//Serial.print(F("Turn off EHO: "));
mySerial.println(F("ATE0"));                // выключаем эхо
delay(600);
     ava();
//Serial.print(F("Turn on AOH: "));
mySerial.println(F("AT+CLIP=1"));    //включаем АОН
delay(600);
     ava();
         
//Serial.print(F("Text format sms: ")); // текстовый формат SMS
mySerial.println(F("AT+CMGF=1"));    // режим кодировки СМС - обычный (для англ.)
delay(600);
     ava();
        
//Serial.print(F("Mode GSM:"));
mySerial.println(F("AT+CSCS=\"GSM\""));  //режим кодировки текста
delay(600);
     ava();
       
//Serial.print(F("SMS to terminal: "));
mySerial.println(F("AT+CNMI=2,2,0,0,0"));     // вывод смс в консоль
//mySerial.print("AT+CNMI=3,2,2,0,1\r"); // вывод смс в консоль
delay(600);
     ava();
       
//Serial.print(F("Delete All SMS on SIM card: "));
mySerial.println(F("AT+CMGD=1,4"));  // удаление всех SMS с SIM карты
delay(600);
     ava();

//Serial.print(F("Sofrware control: "));     
//mySerial.print("AT+IFC=1, 1\r"); // устанавливает программный контроль потоком передачи данных 
//delay(600);
//     ava();
       
//Serial.print(F("Level of signal: "));
mySerial.println(F("AT+CSQ"));  //вывести в терминал уровень сигнала (если 99, то связи нет)
delay(600);
     ava();
}
Скетч использует 15268 байт (49%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 1031 байт (50%) динамической памяти, оставляя 1017 байт для локальных переменных. Максимум: 2048 байт.
RA
Offline
Зарегистрирован: 19.12.2017

еще один умник

RA
Offline
Зарегистрирован: 19.12.2017

По поводу первого пункта я ЗАДАЛ ВОПРОС

НО вроде сам себе

b707
Offline
Зарегистрирован: 26.05.2017

RA пишет:

еще один умник

давай-давай - обидься на нас и уйди. Зачем тебе выслушивать ехидные замечания каких-то умников? - Сделай все сам.

b707
Offline
Зарегистрирован: 26.05.2017

RA пишет:

По поводу первого пункта я ЗАДАЛ ВОПРОС

НО вроде сам себе

самому себе задавать вопросы полезно, но не всегда продуктивно. Проще было пойти в гугль и написать что-нибудь типа "передача по ссылке vs передача по значению"

ты думаешь мы тут только и ждем, кому лекцию по Си прочитать?

RA
Offline
Зарегистрирован: 19.12.2017

я думаю если "Учитель" не может обьяснить то он сам плохо понимает.

А зачем вы здесь

RA
Offline
Зарегистрирован: 19.12.2017

к чему был это коментарий.

b707
Offline
Зарегистрирован: 26.05.2017

RA пишет:

я думаю если "Учитель" не может обьяснить то он сам плохо понимает.

Вполне возможно, даже наверняка, что я многие аспекты языка знаю нетвердо. Однако у меня хватает смекалки, чтобы найти недостающее в гугле и разобраться в конкретном вопросе максимум за час-полтора, а не отвисать на форуме днями. выпрашивая ответы на вопросы, которые отлично разобраны в учебнике.

bwn
Offline
Зарегистрирован: 25.08.2014

RA пишет:

А зачем вы здесь

Такая специальная группа, доставлять удовольствие неофитам. И форум исключительно для этого придумали.

RA
Offline
Зарегистрирован: 19.12.2017

Ну, что то пока плохо получается. Удовольствия 0

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

bwn пишет:

RA пишет:

А зачем вы здесь

Такая специальная группа, доставлять удовольствие неофитам. И форум исключительно для этого придумали.

+5

RA
Offline
Зарегистрирован: 19.12.2017

Глобальные переменные используют 1003 байт (48%) динамической памяти, оставляя 1045 байт для локальных переменных.

Думаю проблема не связана с памятью.

засунул в ФЛЭШ все что можно. 

b707
Offline
Зарегистрирован: 26.05.2017

RA пишет:

засунул в ФЛЭШ все что можно. 

наверняка вранье....  как и раньше, про "выполненные все 4 пункта"

Было 1200 байт занято, я  насчитал более 600 байт строк - значит после "всовывания во флеш всего" должно остаться примерно 600 байт занятых, а не 1000.

Ну и главное - п.1

RA
Offline
Зарегистрирован: 19.12.2017

ну вам виднее

RA
Offline
Зарегистрирован: 19.12.2017
#include <Wire.h>               // библиотека для работы с шиной I²C
#include <LiquidCrystal_I2C.h>  // библиотека для работы LCD1602_I²C
#include <SoftwareSerial.h>     // библиотека для работы с Программным последовательным портом
#include <OneWire.h>            // библиотека для работы с шиной 1Wire
#include <DallasTemperature.h>  // библиотека для работы с датчиком темперутуры DS18B20
#include "TroykaRTC.h"          // библиотека для работы с часами реального времени
#include "EEPROM.h"             // библиотека для работы EEPROM

//#define cusd "AT+CUSD=1,\"#100#\""
#define ONE_WIRE_BUS 8
#define LEN_TIME 12             // размер массива для времени
#define LEN_DATE 12             // размер массива для даты
#define LEN_DOW 12              // размер массива для дня недели
RTC clock;                      // создаём объект для работы с часами реального времени
char time[LEN_TIME];            // массив для хранения текущего времени
char date[LEN_DATE];            // массив для хранения текущей даты
char weekDay[LEN_DOW];          // массив для хранения текущего дня недели

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress Thermometer1 = {0x28, 0xFF, 0x9E, 0xF4, 0x6E, 0x14, 0x04, 0xC5 };  // адрес датчика DS18B20 28FF9EF46E1404C5
//DeviceAddress Thermometer1 = {0x28, 0xFF, 0xC8, 0x02, 0x6F, 0x14, 0x04, 0x1F };  // адрес датчика DS18B20 28FFC8026F14041F

SoftwareSerial mySerial(2, 3);      // TX, RX
LiquidCrystal_I2C lcd(0x27,16,2);   // Устанавливаем адрес LCD_I²C 0x27 для 16 символов в 2 строки

String Admin = "";
int ch = 0;
byte m = 0;

int Random = 0;              // переменная для генерации случайного числа в диапазоне 0 - 32000
String RanPass = "";
int tempC = 0;
int tempCOld = 0;
String tempCsms = "";
String Status = "";          //переменная для хранения СТАТУСА(используется при формировании СМС)
String val = "";             //переменная для хранения Порт <=> GSM
byte pind4 = 4;              //объявляем переменные портов для реле
byte pind5 = 5;              //объявляем переменные портов для реле
bool pin4 = HIGH;            //объявляем БУЛЕВЫЕ переменные портов для ОТРИСОВКИ
bool pin5 = HIGH;            //объявляем БУЛЕВЫЕ переменные портов для ОТРИСОВКИ
byte nowminute = 14;
byte nowhour = 11;

byte k1x[8] = {0b00010,0b00110,0b00010,0b00010,0b00111,0b10100,0b01000,0b10100};     // 1й канал ВЫКЛ
byte k1v[8] = {0b00010,0b00110,0b00010,0b00010,0b00111,0b10100,0b10100,0b01000};     // 1й канал ВКЛ
byte k2x[8] = {0b00111,0b00001,0b00010,0b00100,0b00111,0b10100,0b01000,0b10100};     // 2й канал ВЫКЛ
byte k2v[8] = {0b00111,0b00001,0b00010,0b00100,0b00111,0b10100,0b10100,0b01000};     // 2й канал ВКЛ
byte gradusc[8] = {0b11000,0b11000,0b00110,0b01001,0b01000,0b01001,0b00110,0b00000}; // создаем свой символ градус Цельсия

//########################################################################################################
//########################################################################################################
void setup() {
  
  Serial.begin(9600);         //скорость порта
  Wire.begin();
  clock.begin();              // инициализация часов
//метод установки времени и даты в модуль вручную
//clock.set(11,13,45,27,10,2017,FRIDAY);
//метод установки времени и даты автоматически при компиляции
//clock.set(__TIMESTAMP__); 
  mySerial.begin(9600);       // устанавливаем скорость порта модуля GSM
  sensors.begin();
  sensors.setResolution(Thermometer1, 10);

  delay(30);
  pinMode(pind4, OUTPUT);     //конфигурируем порт D4 на выход для реле
  pinMode(pind5, OUTPUT);     //конфигурируем порт D5 на выход для реле
  digitalWrite(pind4, HIGH);  //выключаем все подтягивающие резисторы, чтобы исключить
  digitalWrite(pind5, HIGH);  //не преднамеренное включение реле при старте
  randomSeed(analogRead(0));  //для функции RANDOM чтение A0 
  lcd.init();                 //запускаем lcd
  lcd.backlight();            //включаем подстветку
  lcd.createChar(0, gradusc); //создаем символ "ГРАДУС"
//для 2х каналов
  lcd.createChar(1, k1x);     //создаем символ
  lcd.createChar(2, k1v);     //создаем символ
  lcd.createChar(3, k2x);     //создаем символ
  lcd.createChar(4, k2v);     //создаем символ
    
  lcd.setCursor(0,0);
  lcd.print(F("***** GSM ******"));
  lcd.setCursor(0,1);
  lcd.print(F("** COMMUTATOR **"));
  delay(2000);  // задержка
  
  lcd.clear();
  lcd.setCursor(9,1); 
  lcd.print(char(0));         // печатаем символ на первой строке
  lcd.setCursor(0,1);
  lcd.print(char(1));
  lcd.setCursor(1,1);
  lcd.print(char(3));

  Random = random(10000,30000);
  RanPass = String(Random);
  ModemInit();
  
}
//################################################################################
//####################### Функция Инициализации МОДЕМа ###########################
//################################################################################
void ModemInit() {   
//Serial.println(F("GSM ALARM&COMMUTATION SYSTEM")); // выводим в порn
//Serial.print(F("Turn off EHO: "));
mySerial.println(F("ATE0"));                // выключаем эхо
delay(600);
     ava();
//Serial.print(F("Turn on AOH: "));
mySerial.println(F("AT+CLIP=1"));    //включаем АОН
delay(600);
     ava();
         
//Serial.print(F("Text format sms: ")); // текстовый формат SMS
mySerial.println(F("AT+CMGF=1"));    // режим кодировки СМС - обычный (для англ.)
delay(600);
     ava();
        
//Serial.print(F("Mode GSM:"));
mySerial.println(F("AT+CSCS=\"GSM\""));  //режим кодировки текста
delay(600);
     ava();
       
//Serial.print(F("SMS to terminal: "));
mySerial.println(F("AT+CNMI=2,2,0,0,0"));     // вывод смс в консоль
//mySerial.print("AT+CNMI=3,2,2,0,1\r"); // вывод смс в консоль
delay(600);
     ava();
       
//Serial.print(F("Delete All SMS on SIM card: "));
mySerial.println(F("AT+CMGD=1,4"));  // удаление всех SMS с SIM карты
delay(600);
     ava();

//Serial.print(F("Sofrware control: "));     
//mySerial.print("AT+IFC=1, 1\r"); // устанавливает программный контроль потоком передачи данных 
//delay(600);
//     ava();
       
//Serial.print(F("Level of signal: "));
mySerial.println(F("AT+CSQ"));  //вывести в терминал уровень сигнала (если 99, то связи нет)
delay(600);
     ava();
}
//################################################################################
//#######################   ___L___O___O___P___   ################################
//################################################################################ 
void loop() { 
masterget();
//sensors.requestTemperatures();
//printTemperature(Thermometer1);
//datetime();
//********************* ОТ SERIAL ************************************  
if(Serial.available())  //если в мониторе порта ввели что-то
  {  Serial.print(F("SERIALtoGSM ")); 
     char ch = ' ';
     String val = "";
     while (Serial.available()) 
      { ch = Serial.read();
        val += char(ch); //собираем принятые символы в строку
        delay(3);
      }
      
    Serial.println(val);
    if(val.indexOf("call") > -1)               // своя команда
     { mySerial.println("ATD+70000000000;"); } // МАСТЕР_номер, на который нужно позвонить
    else if(val.indexOf("reset") > -1)         // своя команда
     { m = 2; masterget(); }
    else if(val.indexOf("balance") > -1 || val.indexOf("money") > -1)
     { //mySerial.println(cusd);}
         mySerial.println(F("ATD#100#;")); }  
    else mySerial.println(val);  // передача всего, что набрано в терминале в GSM модуль
  }

//********************* ОТ GSM ************************************
if (mySerial.available())
  { Serial.print(F("GSMtoSERIAL "));  
    char ch = ' ';
    String val = "";
    while(mySerial.available()) 
      { ch = mySerial.read();
        val += char(ch); //собираем принятые символы в строку
        Serial.print(char(ch));
        delay(3);
      }
//******************** RING ***************************************
    if (val.indexOf("RING") > -1)    //если звонок обнаружен, то проверяем номер
     {  if (val.indexOf(Admin) > -1) //если номер звонящего наш без +
             { Serial.println(F("--- MASTER RING DETECTED ---"));
               lcd.setCursor(0,0);
               lcd.print(F("** MasterRing **"));
               mySerial.println(F("ATH"));  //разрываем связь
               delay(600);
               ava();
               lcd.clear();
               smsbuild(pin4, pin5); }
        else { Serial.println(F("WRONG!NUMBER"));  
               mySerial.println(F("ATH"));  //разрываем связь
               lcd.setCursor(0,0);
               lcd.print(F("** BAD NUMBER **"));
               delay(1000);
               ava();
               lcd.clear(); }
     }
//******************** SMS ***************************************
    else if (val.indexOf("+CMT") > -1) // если есть входящее sms
     {   if (val.indexOf(Admin) > -1)  // проверяем МАСТЕР_НОМЕР
            {  if (val.indexOf("1on") > -1)         // смотрим, что за команда
                  { digitalWrite(pind4, LOW);
                    pin4 = LOW;
                    lcd1602(pin4, pin5);
                    //delay(30);
                    smsbuild(pin4, pin5); } 
             else if (val.indexOf("2on") > -1) // смотрим, что за команда
                  { digitalWrite(pind5, LOW);
                    pin5 = LOW;
                    lcd1602(pin4, pin5);  
                    //delay(30);
                    smsbuild(pin4, pin5); }
             else if (val.indexOf("1off") > -1) // смотрим, что за команда
                  { digitalWrite(pind4, HIGH);
                    pin4 = HIGH;
                    lcd1602(pin4, pin5); 
                    //delay(30);
                    smsbuild(pin4, pin5); }
             else if (val.indexOf("2off") > -1) // смотрим, что за команда
                  { digitalWrite(pind5, HIGH);
                    pin5 = HIGH;
                    lcd1602(pin4, pin5); 
                    //delay(30);
                    smsbuild(pin4, pin5); } 
             else if (val.indexOf("Master") > -1)// || v.indexOf("master") > -1 || v.indexOf("MASTER") > -1) 
                  { lcd.setCursor(0,0);
                    lcd.print(F("     ERROR      "));
                    lcd.setCursor(0,1);
                    lcd.print(F("   MASTER IS    "));
                    delay(1000);
                    lcd.clear();
                    Status = String(time)+" ERROR.MASTER Already is";
                    //Serial.println(Status);
                    sms(Status, Admin); }
             else if (val.indexOf("Money") > -1) // || val.indexOf("money") > -1 || val.indexOf("MONEY") > -1 || val.indexOf("Bal") > -1) 
                  { Serial.println(F("MONEY TRUE")); 
                    mySerial.println(F("AT+CUSD=1,\"#100#\"")); delay(100); }
             else { Status = String(time)+" ERROR.BAD Command";
                    Random = random(10000,30000);
                    RanPass = String(Random);
                    //Serial.println(Status);
                    sms(Status, Admin);  }}
         else { smsunknow(val);  }

     } 
//******************** BALANCE ***************************************
    if(val.indexOf("+CUSD") > -1)             // если есть входящее sms
     { if(val.indexOf("Balance") > -1)        // смотрим, что за команда
        { Serial.println(F("BALANCE TRUE"));  // Просто МЕТКА
          Status = val.substring(val.indexOf("Balance"),val.indexOf("r")); 
          sms(Status, Admin); 
        }     
     }   
  }
}

//##############################################################################
//####### Функция извлекает из EEPROM МАСТЕР_номер в String_Admin ##############
//##############################################################################
void masterget() {
  if(m == 0)
        { char c[13];       // переменная для хранения массива из 12 символов
          EEPROM.get(0, c); // считываем массив символов по адресу 0 
          String Admin(c);
          Admin = (Admin.substring(1,12));
          Serial.println(Admin);
          m = 1; }
  else if(m == 2)
        { char r[13] = "+70000000000";
          EEPROM.put(0, r);  // записываем массив в EEPROM
          delay(30);  
          Serial.println(F("PUT")); 
          m = 0; }
  else if(m == 1)
        {}  
}
//#################################################################################
// В процедуре "smsbuild" происходит сборка сообщения состоящая из "времени,
// состояния каналов и температуры в помещении" и далее вызов функции отправки СМС
// "sms". Вызов данной функции происходит только при соответствии команды или
// звонка с МАСТЕР_НОМЕРА.
//#################################################################################
void smsbuild(bool pin4, bool pin5) {
  if (pin4 == LOW && pin5 == LOW) {
      Status = String(time)+" (1on-2on) temperatura= "+String(tempCsms);
      sms(Status, Admin);   //Master_НОМЕР, с которого 
                               //Вы будете звонить на модуль
  }   else if (pin4 == HIGH && pin5 == HIGH) {
          Status = String(time)+" (1off-2off) temperatura= "+String(tempCsms);   
          sms(Status, Admin);     //Master_НОМЕР, с которого            
                                     //Вы будете звонить на модуль        
  }       else if (pin4 == LOW && pin5 == HIGH) {
              Status = String(time)+" (1on-2off) temperatura= "+String(tempCsms);
              sms(Status, Admin);     //Master_НОМЕР, с которого 
                                         //Вы будете звонить на модуль
  }           else if (pin4 == HIGH && pin5 == LOW) {
                  Status = String(time)+" (1off-2on) temperatura= "+String(tempCsms);
                  sms(Status, Admin);     //Master_НОМЕР, с которого 
                                             //Вы будете звонить на модуль
  }
}
//########################################################################################
// Данная функция занимается исключительно отрисовкой состояния каналов. Состояние каналов 
// известно из переменных "pin4 pin5 pin6 pin7" для 4х канальных устройств, значения  
// которым были присвоены в функции LOOP 
//########################################################################################
void lcd1602(bool pin4, bool pin5) {
  if (pin4 == LOW && pin5 == LOW) 
      {  //lcd.setCursor(0,1);
         //lcd.print("1V-2V");
         lcd.setCursor(0,1);
         lcd.print(char(2));
         lcd.setCursor(1,1);
         lcd.print(char(4));  }
         else if (pin4 == HIGH && pin5 == HIGH) 
              {  //lcd.setCursor(0,1);
                 //lcd.print("1X-2X");
                 lcd.setCursor(0,1);
                 lcd.print(char(1));
                 lcd.setCursor(1,1);
                 lcd.print(char(3));  }
                 else if (pin4 == LOW && pin5 == HIGH) 
                      {  //lcd.setCursor(0,1);
                         //lcd.print("1V-2X");
                         lcd.setCursor(0,1);
                         lcd.print(char(2));
                         lcd.setCursor(1,1);
                         lcd.print(char(3));  }
                         else if (pin4 == HIGH && pin5 == LOW) 
                              {   //lcd.setCursor(0,1);
                                  //lcd.print("1X-2V");    
                                  lcd.setCursor(0,1);
                                  lcd.print(char(1));
                                  lcd.setCursor(1,1);
                                  lcd.print(char(4));  }
}
//################################################################################
//################# Функция обработки СМС_комманд от МАСТЕРа #####################
//################################################################################
void smsadmin(String &val) {
             
}
//################################################################################
//################# Функция обработки СМС_комманд от НЕИЗВЕСТНОГО  ###############
//################################################################################
void smsunknow(String v) {
         if (v.indexOf("Master") > -1)// || v.indexOf("master") > -1 || v.indexOf("MASTER") > -1)
            { Random = random(10000,30000);
              lcd.setCursor(0,0);
              lcd.print("                ");
              lcd.setCursor(4,0);
              lcd.print(Random);
              String number = v.substring(9,21);
              Serial.println(number);
              Serial.println(Random);
              RanPass = String(Random); 
              delay(5000);
              lcd.setCursor(0,0);
              lcd.print(v.substring(10,21));
              delay(1000); }
         else if (v.indexOf(RanPass) > -1)
            { char p[13];
              lcd.setCursor(0,0);
              lcd.print(F("** NEW MASTER **"));
              delay(1000);
              String number = v.substring(9,21);
              number.toCharArray(p, 13);
              Serial.print(F("** NEW MASTER **"));
              Serial.println(p);
              EEPROM.put(0, p);  // записываем массив в EEPROM 
              delay(30);
              lcd.setCursor(0,1);
              lcd.print(number);
              delay(300);
              lcd.clear();
              Random = (random(10000,30000) - 259);
              RanPass = String(Random);
              m = 0; }           
         else 
            { Serial.println(F("E R R O R"));
              lcd.setCursor(0,0);
              lcd.print(F("** E R R O R **"));
              delay(200);
              lcd.clear();
              Random = (random(10000,30000) - 163);
              RanPass = String(Random); }
}

//################################################################################
// Данная функция вызывается при каждом новом цикле VOID LOOP и отрисовывает дату
// на LCD1602
//################################################################################
void datetime() {
  // запрашиваем данные с часов
  clock.read();
  // сохраняем текущее время, дату и день недели в переменные 
  clock.getTimeStamp(time, date, weekDay); 
  lcd.setCursor(4,0);
  lcd.print(time);
} 
//################################################################################
// Функция отправки СМС. В функцию передаются строковые переменные состоящие из
// состояния каналов - STRING Status, мастер телефон - STRING phone 
//################################################################################
void sms(String Status, String ph) { 
  ph = ("+"+String(ph));
  //Serial.println("Start SMS send"+ph);
  //mySerial.println("AT+CMGS=\"" + ph + "\"");
  delay(600);
  //mySerial.print(Status);
  delay(600); 
  //mySerial.print((char)26);
  delay(600);
  lcd.setCursor(0,0);
  lcd.print("SMS send......OK");
  delay(600);
  Serial.print(F("SMS send......OK>>"));
  Serial.println(Status);
  //mySerial.println("AT+CMGD=1");        //стираем память смс
  //delay(300);
  lcd.setCursor(0,0);
  lcd.print(F("                "));
}
//##############################################################################
// Функция служит лишь для быстрого вывода в SERIAL порт ответа
//##############################################################################
void ava() {
  while(mySerial.available()) 
      { Serial.print((char)mySerial.read());
      }//  delay(); }
}

 

b707
Offline
Зарегистрирован: 26.05.2017

ну так и есть - строки 165, 166, 167 и тд...

А вот эти вообще круть - 292, 296, 300, 304 - в одних этих  сразу 100 байт

Все, надоело.  Я тебе указал, ЧТО надо поправить. Это, без ложной скромности, самая ценная помощь. А КАК это сделать - ищи сам. Для этого есть учебники и интернет.

 

RA
Offline
Зарегистрирован: 19.12.2017
#include <Wire.h>               // библиотека для работы с шиной I²C
#include <LiquidCrystal_I2C.h>  // библиотека для работы LCD1602_I²C
#include <SoftwareSerial.h>     // библиотека для работы с Программным последовательным портом
#include <OneWire.h>            // библиотека для работы с шиной 1Wire
#include <DallasTemperature.h>  // библиотека для работы с датчиком темперутуры DS18B20
#include "TroykaRTC.h"          // библиотека для работы с часами реального времени
#include "EEPROM.h"             // библиотека для работы EEPROM



SoftwareSerial mySerial(2, 3);      // TX, RX
LiquidCrystal_I2C lcd(0x27,16,2);   // Устанавливаем адрес LCD_I²C 0x27 для 16 символов в 2 строки

String Admin = "";
int ch = 0;
byte m = 0;

int Random = 0;              // переменная для генерации случайного числа в диапазоне 0 - 32000
String RanPass = "";
int tim = 0;
String Status = "";          //переменная для хранения СТАТУСА(используется при формировании СМС)
String val = "";             //переменная для хранения Порт <=> GSM
byte pind4 = 4;              //объявляем переменные портов для реле
byte pind5 = 5;              //объявляем переменные портов для реле
bool pin4 = HIGH;            //объявляем БУЛЕВЫЕ переменные портов для ОТРИСОВКИ
bool pin5 = HIGH;            //объявляем БУЛЕВЫЕ переменные портов для ОТРИСОВКИ


//########################################################################################################
//########################################################################################################
void setup() {
  
  Serial.begin(9600);         //скорость порта

//метод установки времени и даты в модуль вручную
//clock.set(11,13,45,27,10,2017,FRIDAY);
//метод установки времени и даты автоматически при компиляции
//clock.set(__TIMESTAMP__); 
  mySerial.begin(9600);       // устанавливаем скорость порта модуля GSM

  delay(30);
  pinMode(pind4, OUTPUT);     //конфигурируем порт D4 на выход для реле
  pinMode(pind5, OUTPUT);     //конфигурируем порт D5 на выход для реле
  digitalWrite(pind4, HIGH);  //выключаем все подтягивающие резисторы, чтобы исключить
  digitalWrite(pind5, HIGH);  //не преднамеренное включение реле при старте
  randomSeed(analogRead(0));  //для функции RANDOM чтение A0 
  lcd.init();                 //запускаем lcd
  lcd.backlight();            //включаем подстветку
  

  Random = random(10000,30000);
  RanPass = String(Random);
  ModemInit();
  
}
//################################################################################
//####################### Функция Инициализации МОДЕМа ###########################
//################################################################################
void ModemInit() {   
//Serial.println(F("GSM ALARM&COMMUTATION SYSTEM")); // выводим в порn
//Serial.print(F("Turn off EHO: "));
mySerial.println(F("ATE0"));                // выключаем эхо
delay(600);
     ava();
//Serial.print(F("Turn on AOH: "));
mySerial.println(F("AT+CLIP=1"));    //включаем АОН
delay(600);
     ava();
         
//Serial.print(F("Text format sms: ")); // текстовый формат SMS
mySerial.println(F("AT+CMGF=1"));    // режим кодировки СМС - обычный (для англ.)
delay(600);
     ava();
        
//Serial.print(F("Mode GSM:"));
mySerial.println(F("AT+CSCS=\"GSM\""));  //режим кодировки текста
delay(600);
     ava();
       
//Serial.print(F("SMS to terminal: "));
mySerial.println(F("AT+CNMI=2,2,0,0,0"));     // вывод смс в консоль
//mySerial.print("AT+CNMI=3,2,2,0,1\r"); // вывод смс в консоль
delay(600);
     ava();
       
//Serial.print(F("Delete All SMS on SIM card: "));
mySerial.println(F("AT+CMGD=1,4"));  // удаление всех SMS с SIM карты
delay(600);
     ava();

//Serial.print(F("Sofrware control: "));     
//mySerial.print("AT+IFC=1, 1\r"); // устанавливает программный контроль потоком передачи данных 
//delay(600);
//     ava();
       
//Serial.print(F("Level of signal: "));
mySerial.println(F("AT+CSQ"));  //вывести в терминал уровень сигнала (если 99, то связи нет)
delay(600);
     ava();
}
//################################################################################
//#######################   ___L___O___O___P___   ################################
//################################################################################ 
void loop() { 
masterget();
//sensors.requestTemperatures();
//printTemperature(Thermometer1);
//datetime();
//********************* ОТ SERIAL ************************************  
if(Serial.available())  //если в мониторе порта ввели что-то
  {  Serial.print(F("SERIALtoGSM ")); 
     char ch = ' ';
     String val = "";
     while (Serial.available()) 
      { ch = Serial.read();
        val += char(ch); //собираем принятые символы в строку
        delay(3);
      }
      
    Serial.println(val);
    if(val.indexOf("call") > -1)               // своя команда
     { mySerial.println("ATD+70000000000;"); } // МАСТЕР_номер, на который нужно позвонить
    else if(val.indexOf("reset") > -1)         // своя команда
     { m = 2; masterget(); }
    else if(val.indexOf("balance") > -1 || val.indexOf("money") > -1)
     { //mySerial.println(cusd);}
         mySerial.println(F("ATD#100#;")); }  
    else mySerial.println(val);  // передача всего, что набрано в терминале в GSM модуль
  }

//********************* ОТ GSM ************************************
if (mySerial.available())
  { Serial.print(F("GSMtoSERIAL "));  
    char ch = ' ';
    String val = "";
    while(mySerial.available()) 
      { ch = mySerial.read();
        val += char(ch); //собираем принятые символы в строку
        Serial.print(char(ch));
        delay(3);
      }
//******************** RING ***************************************
    if (val.indexOf("RING") > -1)    //если звонок обнаружен, то проверяем номер
     {  if (val.indexOf(Admin) > -1) //если номер звонящего наш без +
             { Serial.println(F("--- MASTER RING DETECTED ---"));
               lcd.setCursor(0,0);
               lcd.print(F("** MasterRing **"));
               mySerial.println(F("ATH"));  //разрываем связь
               delay(600);
               ava();
               lcd.clear();
               smsbuild(pin4, pin5); }
        else { Serial.println(F("WRONG!NUMBER"));  
               mySerial.println(F("ATH"));  //разрываем связь
               lcd.setCursor(0,0);
               lcd.print(F("** BAD NUMBER **"));
               delay(1000);
               ava();
               lcd.clear(); }
     }
//******************** SMS ***************************************
    else if (val.indexOf("+CMT") > -1) // если есть входящее sms
     {   if (val.indexOf(Admin) > -1)  // проверяем МАСТЕР_НОМЕР
            {  if (val.indexOf("1on") > -1)         // смотрим, что за команда
                  { digitalWrite(pind4, LOW);
                    pin4 = LOW;
                    lcd1602(pin4, pin5);
                    //delay(30);
                    smsbuild(pin4, pin5); } 
             else if (val.indexOf("2on") > -1) // смотрим, что за команда
                  { digitalWrite(pind5, LOW);
                    pin5 = LOW;
                    lcd1602(pin4, pin5);  
                    //delay(30);
                    smsbuild(pin4, pin5); }
             else if (val.indexOf("1off") > -1) // смотрим, что за команда
                  { digitalWrite(pind4, HIGH);
                    pin4 = HIGH;
                    lcd1602(pin4, pin5); 
                    //delay(30);
                    smsbuild(pin4, pin5); }
             else if (val.indexOf("2off") > -1) // смотрим, что за команда
                  { digitalWrite(pind5, HIGH);
                    pin5 = HIGH;
                    lcd1602(pin4, pin5); 
                    //delay(30);
                    smsbuild(pin4, pin5); } 
             else if (val.indexOf("Master") > -1)// || v.indexOf("master") > -1 || v.indexOf("MASTER") > -1) 
                  { lcd.setCursor(0,0);
                    lcd.print(F("     ERROR      "));
                    lcd.setCursor(0,1);
                    lcd.print(F("   MASTER IS    "));
                    delay(1000);
                    lcd.clear();
                    Status = String(tim)+" ERROR.MASTER Already is";
                    //Serial.println(Status);
                    sms(Status, Admin); }
             else if (val.indexOf("Money") > -1) // || val.indexOf("money") > -1 || val.indexOf("MONEY") > -1 || val.indexOf("Bal") > -1) 
                  { Serial.println(F("MONEY TRUE")); 
                    mySerial.println(F("AT+CUSD=1,\"#100#\"")); delay(100); }
             else { Status = String(tim)+" ERROR.BAD Command";
                    Random = random(10000,30000);
                    RanPass = String(Random);
                    //Serial.println(Status);
                    sms(Status, Admin);  }}
         else { smsunknow(val);  }

     } 
//******************** BALANCE ***************************************
    if(val.indexOf("+CUSD") > -1)             // если есть входящее sms
     { if(val.indexOf("Balance") > -1)        // смотрим, что за команда
        { Serial.println(F("BALANCE TRUE"));  // Просто МЕТКА
          Status = val.substring(val.indexOf("Balance"),val.indexOf("r")); 
          sms(Status, Admin); 
        }     
     }   
  }
}

//##############################################################################
//####### Функция извлекает из EEPROM МАСТЕР_номер в String_Admin ##############
//##############################################################################
void masterget() {
  if(m == 0)
        { char c[13];       // переменная для хранения массива из 12 символов
          EEPROM.get(0, c); // считываем массив символов по адресу 0 
          String Admin(c);
          Admin = (Admin.substring(1,12));
          Serial.println(Admin);
          m = 1; }
  else if(m == 2)
        { char r[13] = "+70000000000";
          EEPROM.put(0, r);  // записываем массив в EEPROM
          delay(30);  
          Serial.println(F("PUT")); 
          m = 0; }
  else if(m == 1)
        {}  
}
//#################################################################################
// В процедуре "smsbuild" происходит сборка сообщения состоящая из "времени,
// состояния каналов и температуры в помещении" и далее вызов функции отправки СМС
// "sms". Вызов данной функции происходит только при соответствии команды или
// звонка с МАСТЕР_НОМЕРА.
//#################################################################################
void smsbuild(bool pin4, bool pin5) {
  if (pin4 == LOW && pin5 == LOW) {
      Status = String(tim);
      sms(Status, Admin);   //Master_НОМЕР, с которого 
                               //Вы будете звонить на модуль
  }   else if (pin4 == HIGH && pin5 == HIGH) {
          Status = String(tim);   
          sms(Status, Admin);     //Master_НОМЕР, с которого            
                                     //Вы будете звонить на модуль        
  }       else if (pin4 == LOW && pin5 == HIGH) {
              Status = String(tim);
              sms(Status, Admin);     //Master_НОМЕР, с которого 
                                         //Вы будете звонить на модуль
  }           else if (pin4 == HIGH && pin5 == LOW) {
                  Status = String(tim);
                  sms(Status, Admin);     //Master_НОМЕР, с которого 
                                             //Вы будете звонить на модуль
  }
}
//########################################################################################
// Данная функция занимается исключительно отрисовкой состояния каналов. Состояние каналов 
// известно из переменных "pin4 pin5 pin6 pin7" для 4х канальных устройств, значения  
// которым были присвоены в функции LOOP 
//########################################################################################
void lcd1602(bool pin4, bool pin5) {
  if (pin4 == LOW && pin5 == LOW) 
      {  //lcd.setCursor(0,1);
         //lcd.print("1V-2V");
           }
         else if (pin4 == HIGH && pin5 == HIGH) 
              {  //lcd.setCursor(0,1);
                 //lcd.print("1X-2X");
                   }
                 else if (pin4 == LOW && pin5 == HIGH) 
                      {  //lcd.setCursor(0,1);
                         //lcd.print("1V-2X");
                           }
                         else if (pin4 == HIGH && pin5 == LOW) 
                              {   //lcd.setCursor(0,1);
                                  //lcd.print("1X-2V");    
                                    }
}
//################################################################################
//################# Функция обработки СМС_комманд от МАСТЕРа #####################
//################################################################################
void smsadmin(String &val) {
             
}
//################################################################################
//################# Функция обработки СМС_комманд от НЕИЗВЕСТНОГО  ###############
//################################################################################
void smsunknow(String v) {
         if (v.indexOf("Master") > -1)// || v.indexOf("master") > -1 || v.indexOf("MASTER") > -1)
            { Random = random(10000,30000);
              lcd.setCursor(0,0);
              lcd.print("                ");
              lcd.setCursor(4,0);
              lcd.print(Random);
              String number = v.substring(9,21);
              Serial.println(number);
              Serial.println(Random);
              RanPass = String(Random); 
              delay(5000);
              lcd.setCursor(0,0);
              lcd.print(v.substring(10,21));
              delay(1000); }
         else if (v.indexOf(RanPass) > -1)
            { char p[13];
              lcd.setCursor(0,0);
              lcd.print(F("** NEW MASTER **"));
              delay(1000);
              String number = v.substring(9,21);
              number.toCharArray(p, 13);
              Serial.print(F("** NEW MASTER **"));
              Serial.println(p);
              EEPROM.put(0, p);  // записываем массив в EEPROM 
              delay(30);
              lcd.setCursor(0,1);
              lcd.print(number);
              delay(300);
              lcd.clear();
              Random = (random(10000,30000) - 259);
              RanPass = String(Random);
              m = 0; }           
         else 
            { Serial.println(F("E R R O R"));
              lcd.setCursor(0,0);
              lcd.print(F("** E R R O R **"));
              delay(200);
              lcd.clear();
              Random = (random(10000,30000) - 163);
              RanPass = String(Random); }
}


//################################################################################
// Функция отправки СМС. В функцию передаются строковые переменные состоящие из
// состояния каналов - STRING Status, мастер телефон - STRING phone 
//################################################################################
void sms(String Status, String ph) { 
  ph = ("+"+String(ph));
  //Serial.println("Start SMS send"+ph);
  //mySerial.println("AT+CMGS=\"" + ph + "\"");
  delay(600);
  //mySerial.print(Status);
  delay(600); 
  //mySerial.print((char)26);
  delay(600);
  lcd.setCursor(0,0);
  lcd.print("SMS send......OK");
  delay(600);
  Serial.print(F("SMS send......OK>>"));
  Serial.println(Status);
  //mySerial.println("AT+CMGD=1");        //стираем память смс
  //delay(300);
  lcd.setCursor(0,0);
  lcd.print(F("                "));
}
//##############################################################################
// Функция служит лишь для быстрого вывода в SERIAL порт ответа
//##############################################################################
void ava() {
  while(mySerial.available()) 
      { Serial.print((char)mySerial.read());
      }//  delay(); }
}

 

RA
Offline
Зарегистрирован: 19.12.2017

сколько еще мне памяти почистить????

Скетч использует 12418 байт (40%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 738 байт (36%) динамической памяти, оставляя 1310 байт для локальных переменных.
DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

На, болезный, поработал за тебя корректором:

#include <Wire.h>               // библиотека для работы с шиной I²C
#include <LiquidCrystal_I2C.h>  // библиотека для работы LCD1602_I²C
#include <SoftwareSerial.h>     // библиотека для работы с Программным последовательным портом
#include <OneWire.h>            // библиотека для работы с шиной 1Wire
#include <DallasTemperature.h>  // библиотека для работы с датчиком темперутуры DS18B20
#include "TroykaRTC.h"          // библиотека для работы с часами реального времени
#include "EEPROM.h"             // библиотека для работы EEPROM

//#define cusd "AT+CUSD=1,\"#100#\""
#define ONE_WIRE_BUS 8
#define LEN_TIME 12             // размер массива для времени
#define LEN_DATE 12             // размер массива для даты
#define LEN_DOW 12              // размер массива для дня недели
RTC clock;                      // создаём объект для работы с часами реального времени
char time[LEN_TIME];            // массив для хранения текущего времени
char date[LEN_DATE];            // массив для хранения текущей даты
char weekDay[LEN_DOW];          // массив для хранения текущего дня недели

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress Thermometer1 = {0x28, 0xFF, 0x9E, 0xF4, 0x6E, 0x14, 0x04, 0xC5 };  // адрес датчика DS18B20 28FF9EF46E1404C5
//DeviceAddress Thermometer1 = {0x28, 0xFF, 0xC8, 0x02, 0x6F, 0x14, 0x04, 0x1F };  // адрес датчика DS18B20 28FFC8026F14041F

SoftwareSerial mySerial(2, 3);      // TX, RX
LiquidCrystal_I2C lcd(0x27,16,2);   // Устанавливаем адрес LCD_I²C 0x27 для 16 символов в 2 строки

String Admin = "";
int ch = 0;
byte m = 0;

int Random = 0;              // переменная для генерации случайного числа в диапазоне 0 - 32000
String RanPass = "";
int tempC = 0;
int tempCOld = 0;
String tempCsms = "";
String Status = "";          //переменная для хранения СТАТУСА(используется при формировании СМС)
String val = "";             //переменная для хранения Порт <=> GSM
byte pind4 = 4;              //объявляем переменные портов для реле
byte pind5 = 5;              //объявляем переменные портов для реле
bool pin4 = HIGH;            //объявляем БУЛЕВЫЕ переменные портов для ОТРИСОВКИ
bool pin5 = HIGH;            //объявляем БУЛЕВЫЕ переменные портов для ОТРИСОВКИ
byte nowminute = 14;
byte nowhour = 11;

byte k1x[8] = {0b00010,0b00110,0b00010,0b00010,0b00111,0b10100,0b01000,0b10100};     // 1й канал ВЫКЛ
byte k1v[8] = {0b00010,0b00110,0b00010,0b00010,0b00111,0b10100,0b10100,0b01000};     // 1й канал ВКЛ
byte k2x[8] = {0b00111,0b00001,0b00010,0b00100,0b00111,0b10100,0b01000,0b10100};     // 2й канал ВЫКЛ
byte k2v[8] = {0b00111,0b00001,0b00010,0b00100,0b00111,0b10100,0b10100,0b01000};     // 2й канал ВКЛ
byte gradusc[8] = {0b11000,0b11000,0b00110,0b01001,0b01000,0b01001,0b00110,0b00000}; // создаем свой символ градус Цельсия

//########################################################################################################
//########################################################################################################
void setup() {
  
  Serial.begin(9600);         //скорость порта
  Wire.begin();
  clock.begin();              // инициализация часов
//метод установки времени и даты в модуль вручную
//clock.set(11,13,45,27,10,2017,FRIDAY);
//метод установки времени и даты автоматически при компиляции
//clock.set(__TIMESTAMP__); 
  mySerial.begin(9600);       // устанавливаем скорость порта модуля GSM
  sensors.begin();
  sensors.setResolution(Thermometer1, 10);

  delay(30);
  pinMode(pind4, OUTPUT);     //конфигурируем порт D4 на выход для реле
  pinMode(pind5, OUTPUT);     //конфигурируем порт D5 на выход для реле
  digitalWrite(pind4, HIGH);  //выключаем все подтягивающие резисторы, чтобы исключить
  digitalWrite(pind5, HIGH);  //не преднамеренное включение реле при старте
  randomSeed(analogRead(0));  //для функции RANDOM чтение A0 
  lcd.init();                 //запускаем lcd
  lcd.backlight();            //включаем подстветку
  lcd.createChar(0, gradusc); //создаем символ "ГРАДУС"
//для 2х каналов
  lcd.createChar(1, k1x);     //создаем символ
  lcd.createChar(2, k1v);     //создаем символ
  lcd.createChar(3, k2x);     //создаем символ
  lcd.createChar(4, k2v);     //создаем символ
    
  lcd.setCursor(0,0);
  lcd.print(F("***** GSM ******"));
  lcd.setCursor(0,1);
  lcd.print(F("** COMMUTATOR **"));
  delay(2000);  // задержка
  
  lcd.clear();
  lcd.setCursor(9,1); 
  lcd.print(char(0));         // печатаем символ на первой строке
  lcd.setCursor(0,1);
  lcd.print(char(1));
  lcd.setCursor(1,1);
  lcd.print(char(3));

  Random = random(10000,30000);
  RanPass = String(Random);
  ModemInit();
  
}
//################################################################################
//####################### Функция Инициализации МОДЕМа ###########################
//################################################################################
void ModemInit() {   
//Serial.println(F("GSM ALARM&COMMUTATION SYSTEM")); // выводим в порn
//Serial.print(F("Turn off EHO: "));
mySerial.println(F("ATE0"));                // выключаем эхо
delay(600);
     ava();
//Serial.print(F("Turn on AOH: "));
mySerial.println(F("AT+CLIP=1"));    //включаем АОН
delay(600);
     ava();
         
//Serial.print(F("Text format sms: ")); // текстовый формат SMS
mySerial.println(F("AT+CMGF=1"));    // режим кодировки СМС - обычный (для англ.)
delay(600);
     ava();
        
//Serial.print(F("Mode GSM:"));
mySerial.println(F("AT+CSCS=\"GSM\""));  //режим кодировки текста
delay(600);
     ava();
       
//Serial.print(F("SMS to terminal: "));
mySerial.println(F("AT+CNMI=2,2,0,0,0"));     // вывод смс в консоль
//mySerial.print("AT+CNMI=3,2,2,0,1\r"); // вывод смс в консоль
delay(600);
     ava();
       
//Serial.print(F("Delete All SMS on SIM card: "));
mySerial.println(F("AT+CMGD=1,4"));  // удаление всех SMS с SIM карты
delay(600);
     ava();

//Serial.print(F("Sofrware control: "));     
//mySerial.print("AT+IFC=1, 1\r"); // устанавливает программный контроль потоком передачи данных 
//delay(600);
//     ava();
       
//Serial.print(F("Level of signal: "));
mySerial.println(F("AT+CSQ"));  //вывести в терминал уровень сигнала (если 99, то связи нет)
delay(600);
     ava();
}
//################################################################################
//#######################   ___L___O___O___P___   ################################
//################################################################################ 
void loop() { 
masterget();
//sensors.requestTemperatures();
//printTemperature(Thermometer1);
//datetime();
//********************* ОТ SERIAL ************************************  
if(Serial.available())  //если в мониторе порта ввели что-то
  {  Serial.print(F("SERIALtoGSM ")); 
     char ch = ' ';
     String val = "";
     while (Serial.available()) 
      { ch = Serial.read();
        val += char(ch); //собираем принятые символы в строку
        ////////delay(3);  НАХЕР
      }
      
    Serial.println(val);
    if(val.indexOf(F("call")) > -1)               // своя команда
     { mySerial.println(F("ATD+70000000000;")); } // МАСТЕР_номер, на который нужно позвонить
    else if(val.indexOf(F("reset")) > -1)         // своя команда
     { m = 2; masterget(); }
    else if(val.indexOf(F("balance")) > -1 || val.indexOf(F("money")) > -1)
     { //mySerial.println(cusd);}
         mySerial.println(F("ATD#100#;")); }  
    else mySerial.println(val);  // передача всего, что набрано в терминале в GSM модуль
  }

//********************* ОТ GSM ************************************
if (mySerial.available())
  { Serial.print(F("GSMtoSERIAL "));  
    char ch = ' ';
    String val = "";
    while(mySerial.available()) 
      { ch = mySerial.read();
        val += char(ch); //собираем принятые символы в строку
        Serial.print(char(ch));
        ///////////////////////delay(3); НАХЕР
      }
//******************** RING ***************************************
    if (val.indexOf(F("RING")) > -1)    //если звонок обнаружен, то проверяем номер
     {  if (val.indexOf(Admin) > -1) //если номер звонящего наш без +
             { Serial.println(F("--- MASTER RING DETECTED ---"));
               lcd.setCursor(0,0);
               lcd.print(F("** MasterRing **"));
               mySerial.println(F("ATH"));  //разрываем связь
               delay(600);
               ava();
               lcd.clear();
               smsbuild(pin4, pin5); }
        else { Serial.println(F("WRONG!NUMBER"));  
               mySerial.println(F("ATH"));  //разрываем связь
               lcd.setCursor(0,0);
               lcd.print(F("** BAD NUMBER **"));
               delay(1000);
               ava();
               lcd.clear(); }
     }
//******************** SMS ***************************************
    else if (val.indexOf(F("+CMT")) > -1) // если есть входящее sms
     {   if (val.indexOf(Admin) > -1)  // проверяем МАСТЕР_НОМЕР
            {  if (val.indexOf(F("1on")) > -1)         // смотрим, что за команда
                  { digitalWrite(pind4, LOW);
                    pin4 = LOW;
                    lcd1602(pin4, pin5);
                    //delay(30);
                    smsbuild(pin4, pin5); } 
             else if (val.indexOf(F("2on")) > -1) // смотрим, что за команда
                  { digitalWrite(pind5, LOW);
                    pin5 = LOW;
                    lcd1602(pin4, pin5);  
                    //delay(30);
                    smsbuild(pin4, pin5); }
             else if (val.indexOf(F("1off")) > -1) // смотрим, что за команда
                  { digitalWrite(pind4, HIGH);
                    pin4 = HIGH;
                    lcd1602(pin4, pin5); 
                    //delay(30);
                    smsbuild(pin4, pin5); }
             else if (val.indexOf(F("2off")) > -1) // смотрим, что за команда
                  { digitalWrite(pind5, HIGH);
                    pin5 = HIGH;
                    lcd1602(pin4, pin5); 
                    //delay(30);
                    smsbuild(pin4, pin5); } 
             else if (val.indexOf(F("Master")) > -1)// || v.indexOf("master") > -1 || v.indexOf("MASTER") > -1) 
                  { lcd.setCursor(0,0);
                    lcd.print(F("     ERROR      "));
                    lcd.setCursor(0,1);
                    lcd.print(F("   MASTER IS    "));
                    delay(1000);
                    lcd.clear();
                    Status = String(time);
					Status += F(" ERROR.MASTER Already is");
                    //Serial.println(Status);
                    sms(Status, Admin); }
             else if (val.indexOf(F("Money")) > -1) // || val.indexOf("money") > -1 || val.indexOf("MONEY") > -1 || val.indexOf("Bal") > -1) 
                  { Serial.println(F("MONEY TRUE")); 
                    mySerial.println(F("AT+CUSD=1,\"#100#\"")); delay(100); }
             else { Status = String(time);
					Status += F(" ERROR.BAD Command");
                    Random = random(10000,30000);
                    RanPass = String(Random);
                    //Serial.println(Status);
                    sms(Status, Admin);  }}
         else { smsunknow(val);  }

     } 
//******************** BALANCE ***************************************
    if(val.indexOf(F("+CUSD")) > -1)             // если есть входящее sms
     { if(val.indexOf(F("Balance")) > -1)        // смотрим, что за команда
        { Serial.println(F("BALANCE TRUE"));  // Просто МЕТКА
          Status = val.substring(val.indexOf(F("Balance")),val.indexOf(F("r"))); 
          sms(Status, Admin); 
        }     
     }   
  }
}

//##############################################################################
//####### Функция извлекает из EEPROM МАСТЕР_номер в String_Admin ##############
//##############################################################################
void masterget() {
  if(m == 0)
        { char c[13];       // переменная для хранения массива из 12 символов
          EEPROM.get(0, c); // считываем массив символов по адресу 0 
          String Admin(c);
          Admin = (Admin.substring(1,12));
          Serial.println(Admin);
          m = 1; }
  else if(m == 2)
        { char r[13] = "+70000000000";
          EEPROM.put(0, r);  // записываем массив в EEPROM
          delay(30);  
          Serial.println(F("PUT")); 
          m = 0; }
  else if(m == 1)
        {}  
}
//#################################################################################
// В процедуре "smsbuild" происходит сборка сообщения состоящая из "времени,
// состояния каналов и температуры в помещении" и далее вызов функции отправки СМС
// "sms". Вызов данной функции происходит только при соответствии команды или
// звонка с МАСТЕР_НОМЕРА.
//#################################################################################
void smsbuild(bool pin4, bool pin5) {
  if (pin4 == LOW && pin5 == LOW) {
      Status = String(time);
	  Status += F(" (1on-2on) temperatura= ");
	  Status += String(tempCsms);
      sms(Status, Admin);   //Master_НОМЕР, с которого 
                               //Вы будете звонить на модуль
  }   else if (pin4 == HIGH && pin5 == HIGH) {
          Status = String(time);
		  Status += F(" (1off-2off) temperatura= ");
		  Status +=String(tempCsms);   
          sms(Status, Admin);     //Master_НОМЕР, с которого            
                                     //Вы будете звонить на модуль        
  }       else if (pin4 == LOW && pin5 == HIGH) {
              Status = String(time);
			  Status +=F(" (1on-2off) temperatura= ");
			  Status +=String(tempCsms);
              sms(Status, Admin);     //Master_НОМЕР, с которого 
                                         //Вы будете звонить на модуль
  }           else if (pin4 == HIGH && pin5 == LOW) {
                  Status = String(time);
				  Status +=F(" (1off-2on) temperatura= ");
				  Status +=String(tempCsms);
                  sms(Status, Admin);     //Master_НОМЕР, с которого 
                                             //Вы будете звонить на модуль
  }
}
//########################################################################################
// Данная функция занимается исключительно отрисовкой состояния каналов. Состояние каналов 
// известно из переменных "pin4 pin5 pin6 pin7" для 4х канальных устройств, значения  
// которым были присвоены в функции LOOP 
//########################################################################################
void lcd1602(bool pin4, bool pin5) {
  if (pin4 == LOW && pin5 == LOW) 
      {  //lcd.setCursor(0,1);
         //lcd.print("1V-2V");
         lcd.setCursor(0,1);
         lcd.print(char(2));
         lcd.setCursor(1,1);
         lcd.print(char(4));  }
         else if (pin4 == HIGH && pin5 == HIGH) 
              {  //lcd.setCursor(0,1);
                 //lcd.print("1X-2X");
                 lcd.setCursor(0,1);
                 lcd.print(char(1));
                 lcd.setCursor(1,1);
                 lcd.print(char(3));  }
                 else if (pin4 == LOW && pin5 == HIGH) 
                      {  //lcd.setCursor(0,1);
                         //lcd.print("1V-2X");
                         lcd.setCursor(0,1);
                         lcd.print(char(2));
                         lcd.setCursor(1,1);
                         lcd.print(char(3));  }
                         else if (pin4 == HIGH && pin5 == LOW) 
                              {   //lcd.setCursor(0,1);
                                  //lcd.print("1X-2V");    
                                  lcd.setCursor(0,1);
                                  lcd.print(char(1));
                                  lcd.setCursor(1,1);
                                  lcd.print(char(4));  }
}
//################################################################################
//################# Функция обработки СМС_комманд от МАСТЕРа #####################
//################################################################################
void smsadmin(String &val) {
             
}
//################################################################################
//################# Функция обработки СМС_комманд от НЕИЗВЕСТНОГО  ###############
//################################################################################
void smsunknow(String& v) {
         if (v.indexOf(F("Master")) > -1)// || v.indexOf("master") > -1 || v.indexOf("MASTER") > -1)
            { Random = random(10000,30000);
              lcd.setCursor(0,0);
              lcd.print("                ");
              lcd.setCursor(4,0);
              lcd.print(Random);
              String number = v.substring(9,21);
              Serial.println(number);
              Serial.println(Random);
              RanPass = String(Random); 
              delay(5000);
              lcd.setCursor(0,0);
              lcd.print(v.substring(10,21));
              delay(1000); }
         else if (v.indexOf(RanPass) > -1)
            { char p[13];
              lcd.setCursor(0,0);
              lcd.print(F("** NEW MASTER **"));
              delay(1000);
              String number = v.substring(9,21);
              number.toCharArray(p, 13);
              Serial.print(F("** NEW MASTER **"));
              Serial.println(p);
              EEPROM.put(0, p);  // записываем массив в EEPROM 
              delay(30);
              lcd.setCursor(0,1);
              lcd.print(number);
              delay(300);
              lcd.clear();
              Random = (random(10000,30000) - 259);
              RanPass = String(Random);
              m = 0; }           
         else 
            { Serial.println(F("E R R O R"));
              lcd.setCursor(0,0);
              lcd.print(F("** E R R O R **"));
              delay(200);
              lcd.clear();
              Random = (random(10000,30000) - 163);
              RanPass = String(Random); }
}

//################################################################################
// Данная функция вызывается при каждом новом цикле VOID LOOP и отрисовывает дату
// на LCD1602
//################################################################################
void datetime() {
  // запрашиваем данные с часов
  clock.read();
  // сохраняем текущее время, дату и день недели в переменные 
  clock.getTimeStamp(time, date, weekDay); 
  lcd.setCursor(4,0);
  lcd.print(time);
} 
//################################################################################
// Функция отправки СМС. В функцию передаются строковые переменные состоящие из
// состояния каналов - STRING Status, мастер телефон - STRING phone 
//################################################################################
void sms(String& Status, String& ph) { 
  ph = ("+"+String(ph));
  //Serial.println("Start SMS send"+ph);
  //mySerial.println("AT+CMGS=\"" + ph + "\"");
  delay(600);
  //mySerial.print(Status);
  delay(600); 
  //mySerial.print((char)26);
  delay(600);
  lcd.setCursor(0,0);
  lcd.print((const char*)F("SMS send......OK"));
  delay(600);
  Serial.print(F("SMS send......OK>>"));
  Serial.println(Status);
  //mySerial.println("AT+CMGD=1");        //стираем память смс
  //delay(300);
  lcd.setCursor(0,0);
  lcd.print(F("                "));
}
//##############################################################################
// Функция служит лишь для быстрого вывода в SERIAL порт ответа
//##############################################################################
void ava() {
  while(mySerial.available()) 
      { Serial.print((char)mySerial.read());
      }//  delay(); }
}

 

RA
Offline
Зарегистрирован: 19.12.2017

Спасибо за 100 байт. НО вопрос ОСТАЛСЯ.

Не туда копаем.

RA
Offline
Зарегистрирован: 19.12.2017

По поводу НАХЕР. строка 161 и 184.

если их убрать то ответы приходят с ошибками.

b707
Offline
Зарегистрирован: 26.05.2017

RA пишет:

По поводу НАХЕР. строка 161 и 184.

если их убрать то ответы приходят с ошибками.

потому что строки из Сериала собираешь неправильно. Нужно ждать конца строки, а не просто перерыва в 3 мс, как у тебя в коде.

Я так и не понял - п.1 ты победил или нет? Какой сейчас размер скетча и памяти? Главный вопрос решился?

 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

RA пишет:

По поводу НАХЕР. строка 161 и 184.

если их убрать то ответы приходят с ошибками.

Там это реально нахер, т.к. смысла ждать в delay, когда в приёмном буфере уже есть данные - онанизм. Если при комментировании этих строчек работает неправильно - проблема не в этих строчках, а в другом месте. Да там весь код - одна большая проблема, если честно.

RA
Offline
Зарегистрирован: 19.12.2017
Скетч использует 15172 байт (49%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 675 байт (32%) динамической памяти, оставляя 1373 байт для локальных переменных.
 
ВОПРОС не решен!!
RA
Offline
Зарегистрирован: 19.12.2017

b707 пишет:

RA пишет:

По поводу НАХЕР. строка 161 и 184.

если их убрать то ответы приходят с ошибками.

потому что строки из Сериала собираешь неправильно. Нужно ждать конца строки, а не просто перерыва в 3 мс, как у тебя в коде.

Я так и не понял - п.1 ты победил или нет? Какой сейчас размер скетча и памяти? Главный вопрос решился?

 

//################################################################################
//################# Функция обработки СМС_комманд от МАСТЕРа #####################
//################################################################################
void smsadmin(String &val) {
             if (val.indexOf(F("1on")) > -1)         // смотрим, что за команда
Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Сильно не вникал, но сразу бросается в глаза indexOf, она регистрозависимая. Лучше подстраховаться и сделать toLowerCase() toUpperCase().

Пишите что через терминал все работает, а из вашей функции нет и при этом при использовании через терминал вы баланс через дозвон используете (ATD) а из "своей функции" через USSD команды. Может надо в этой стороне покопать.

У меня, например, МТС на USSD вообще через раз отвечает, приходит сообщение об ошибке а потом через пару минут смс с балансом.

З.Ы. Ну это так мысли не больше.

RA
Offline
Зарегистрирован: 19.12.2017

Penni пишет:

Сильно не вникал, но сразу бросается в глаза indexOf, она регистрозависимая. Лучше подстраховаться и сделать toLowerCase() toUpperCase().

Пишите что через терминал все работает, а из вашей функции нет и при этом при использовании через терминал вы баланс через дозвон используете (ATD) а из "своей функции" через USSD команды. Может надо в этой стороне покопать.

У меня, например, МТС на USSD вообще через раз отвечает, приходит сообщение об ошибке а потом через пару минут смс с балансом.

З.Ы. Ну это так мысли не больше.

indexOf согласен исправляю.

Пробовал и так "ATD#100#;" и так "AT+CUSD=1,\"#100#\"" В любом случае если командой balance вызывать из терминала все проходит и ни разу ошибки не было. А через СМС никак. Причем через СМС программа доходит до

нужного куска кода. А в ответ ERROR

else if (val.indexOf(F("Money")) > -1) 
                  { Serial.println(F("MONEY TRUE")); 
                    mySerial.println(F("ATD#100#;")); }
По поводу регистра я думаю equalsIgnoreCase. Отлично работает.
Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Т.е. в сериале вы видите "MONEY TRUE" и следом "ERROR" именно "ERROR" а не "E R R O R"?

RA
Offline
Зарегистрирован: 19.12.2017

Penni пишет:

Т.е. в сериале вы видите "MONEY TRUE" и следом "ERROR" именно "ERROR" а не "E R R O R"?

ТТ

RA
Offline
Зарегистрирован: 19.12.2017

Вообще сей гаджет с сентября работает в гараже, можно сказать в экстриме. температура в гараже -15. ни разу электроника и софт не дали сбоя. Хотя и СПАМИЛИ СМСками и тд. Просто решил добавить Функцию "узнать баланс" . НУУУУ очень нужна.

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

А лога с терминала нет? Посмотреть что выдает если запрашивать баланс через смс. А то то что вы говорите с кодом не сходится.