Портится значение переменной

Тема в разделе "Arduino & Shields", создана пользователем egor2fsys, 13 сен 2015.

  1. egor2fsys

    egor2fsys Нуб

    Добрый день.

    Есть плата Arduino Leonardo ETH.

    Делаю небольшой скетч для посылки определенных данных на веб-сервер.

    Должно работать примерно так:
    1) при старте в процедуры setup() читаю файл с карты памяти и устанавливаю глобальные переменные (ip адрес модуля arduino, mac адрес, ip адрес сервера и порт сервера).
    2) в основной процедуре цикла loop() по задержкам отправляю запрос на веб-сервер.

    Проблема в том, что если определить переменную, например, ip адрес сервера (_serverip) в setup(), то в loop() она уже имеет не то значение, которое было установлено в setup().

    Вывод в терминал, когда переменная _serverip определяется каждый раз в процедуре httpRequest():
    Код (Text):

    server=192.168.200.33
    id=VGL3Et
    ip=192.168.200.177
    mac=90:A2:DA:10:0:E8
    My IP address:192168200177
    Starting ...
    Server IP address:19216820033
     
    Вывод в терминал, когда переменная _serverip определяется один раз в процедуре setup():
    Код (Text):

    server=192.168.200.33
    id=VGL3Et
    ip=192.168.200.177
    mac=90:A2:DA:10:0:E8
    My IP address:192168200177
    Starting ...
    Server IP address:1686140
     
    Почему так может происходить ? Ведь переменная localip вполне нормально присваивается и не изменяется.
    Судя по сообщению компилятора при записи проекта в устройство размера ОЗУ достаточно для работы (занято около 60 %).

    Заранее благодарен за ответы.

    Код скетча:

    Код (Text):

    #include <SPI.h>
    #include <Ethernet2.h>
    #include <SD.h>

    byte mac[] = {
      0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00 //fake MAC
    };

    // initialize the library instance:
    EthernetClient client;

    String ip = "192.168.200.188";
    String server = "192.168.200.44";

    byte localip[] = {};
    byte _serverip[] = {};
    String DeviceId = "NoId";
    String _Date = "12.09.2015";
    String _Time = "08:23:50";
    String _Delimetr = "%20";

    //переменные портов
    int selectEthernet = 10;          // выбор ведомого на шилде - Ethernet
    int selectSd = 4;                // выбор ведомого на шилде - SD

    // включим Ethernet
    #define SWITCH_TO_ETH digitalWrite(selectSd,HIGH); digitalWrite(selectEthernet,LOW);
    // включим SD
    #define SWITCH_TO_SD digitalWrite(selectEthernet,HIGH); digitalWrite(selectSd,LOW);
    // выключим и SD и Ethernet
    #define ALL_OFF digitalWrite(selectEthernet,HIGH); digitalWrite(selectSd,HIGH);

    void setup() {

      // start serial port:
      Serial.begin(9600);
      while (!Serial) {
        ; // wait for serial port to connect. Needed for Leonardo only
      }

      //uncomment for write config
      /*
      writeconfig();
      return;
      */

      // give the ethernet module time to boot up:
      delay(1000);

      // Задаем режим работы портов
      pinMode(selectEthernet, OUTPUT);
      pinMode(selectSd, OUTPUT);

      readconfig();
     
      //IPAddress serverip(strtoint(SplitString(server, '.', 0)), strtoint(SplitString(server, '.', 1)), strtoint(SplitString(server, '.', 2)), strtoint(SplitString(server, '.', 3)));
      //byte localip[] = { strtoint(SplitString(ip, '.', 0)), strtoint(SplitString(ip, '.', 1)), strtoint(SplitString(ip, '.', 2)), strtoint(SplitString(ip, '.', 3)) };
      byte localip[] = { SplitString(ip, '.', 0).toInt(), SplitString(ip, '.', 1).toInt(), SplitString(ip, '.', 2).toInt(), SplitString(ip, '.', 3).toInt() };
      //если раскомментировать здесь, то в loop() массив адреса будет неверный
      //byte _serverip[] = { SplitString(server, '.', 0).toInt(), SplitString(server, '.', 1).toInt(), SplitString(server, '.', 2).toInt(), SplitString(server, '.', 3).toInt() };

      Serial.print("My IP address:");
      Serial.print(localip[0]);
      Serial.print(localip[1]);
      Serial.print(localip[2]);
      Serial.println(localip[3]);

      Ethernet.begin(mac, localip);

      Serial.println("Starting ...");

    }

    void loop() {

      delay(1000);

      httpRequest(_Date + _Delimetr + _Time, String(millis()));

      while (client.available()) {
        char c = client.read();
        Serial.write(c);
      }
      client.stop();

    }

    void httpRequest(String DateTime, String IdCard) {

      //приходится вызывать здесь каждый раз, ибо если вызвать из setup() переменная здесь уже неверная (
      byte _serverip[] = { SplitString(server, '.', 0).toInt(), SplitString(server, '.', 1).toInt(), SplitString(server, '.', 2).toInt(), SplitString(server, '.', 3).toInt() };
      Serial.print("Server IP address:");
      Serial.print(_serverip[0]);
      Serial.print(_serverip[1]);
      Serial.print(_serverip[2]);
      Serial.println(_serverip[3]);

      if (client.connect(_serverip, 8080)) {
        Serial.println("connecting...");
        // send the HTTP GET request:
        client.println("GET /resort/hs/MonitoringVisits/put_data?Date=" + DateTime + "&IdDevice=" + DeviceId + "&IdCard=" + IdCard + " HTTP/1.1");
        client.println("Host: " + server);
        //client.println("User-Agent: arduino");
        client.println("Connection: close");
        client.println();
      }
      else {
        Serial.println("connection failed");
      }
      delay(5000);
    }

    String SplitString(String data, char separator, int index)
    {
      int found = 0;
      int strIndex[] = {0, -1};
      int maxIndex = data.length() - 1;

      for (int i = 0; i <= maxIndex && found <= index; i++) {
        if (data.charAt(i) == separator || i == maxIndex) {
          found++;
          strIndex[0] = strIndex[1] + 1;
          strIndex[1] = (i == maxIndex) ? i + 1 : i;
        }
      }
     
      return found > index ? data.substring(strIndex[0], strIndex[1]) : "";

    }

    void writeconfig() {

      SWITCH_TO_SD;

      Serial.print("Init SD card...");
      if (!SD.begin(selectSd)) {
        Serial.println("init failed!");
        return;
      }
      Serial.println("init done.");
      if (SD.exists("config.txt")) {
        SD.remove("config.txt");
      }
      File ConfigFile;
      ConfigFile = SD.open("config.txt", FILE_WRITE);
      if (ConfigFile) {
        ConfigFile.println("192.168.200.177");
        ConfigFile.println("90A2DA1000E8");
        ConfigFile.println("VGL3Et");
        ConfigFile.println("192.168.200.33");
        ConfigFile.println("8080");
        ConfigFile.close();
      }

      Serial.println("Testing");

      Serial.print(mac[0], HEX);
      Serial.print(mac[1], HEX);
      Serial.print(mac[2], HEX);
      Serial.print(mac[3], HEX);
      Serial.print(mac[4], HEX);
      Serial.println(mac[5], HEX);

      String TempString = "90A2DA1000E8";

      Serial.println(convert2hex(TempString.c_str(), mac));

      //test MAC
      Serial.print(mac[0], HEX);
      Serial.print(mac[1], HEX);
      Serial.print(mac[2], HEX);
      Serial.print(mac[3], HEX);
      Serial.print(mac[4], HEX);
      Serial.println(mac[5], HEX);

      SWITCH_TO_ETH;

    }

    void readconfig() {

      SWITCH_TO_SD;

      if (!SD.begin(selectSd)) {
        Serial.println("init SD card failed!");
        return;
      }
      if (SD.exists("config.txt")) {
        File ConfigFile;
        ConfigFile = SD.open("config.txt");
        if (ConfigFile) {
          String TempString;
          int NumberOfString = 0;
          while (ConfigFile.available()) {
            char TempBuff = ConfigFile.read();
            if (TempBuff == '\n') {
              NumberOfString++;
              if (NumberOfString == 1) { //IP адрес устройства
                ip = TempString;
              } else if (NumberOfString == 2) { //MAC адрес
                convert2hex(TempString.c_str(), mac);
              } else if (NumberOfString == 3) { //ID устройства
                DeviceId = TempString;
              } else if (NumberOfString == 4) { //IP адрес сервера
                server = TempString;
              } else if (NumberOfString == 5) { //порт сервера
                //serverport = TempString.toInt(); //это устанавливаем сразу ...
              }
              TempString = "";
            } else if (TempBuff != '\r') {
              TempString += TempBuff;
            }
          }
          ConfigFile.close();
          Serial.println("server=" + server);
          Serial.println("id=" + DeviceId);
          Serial.println("ip=" + ip);
          Serial.print("mac=");
          Serial.print(mac[0], HEX);
          Serial.print(":");
          Serial.print(mac[1], HEX);
          Serial.print(":");
          Serial.print(mac[2], HEX);
          Serial.print(":");
          Serial.print(mac[3], HEX);
          Serial.print(":");
          Serial.print(mac[4], HEX);
          Serial.print(":");
          Serial.println(mac[5], HEX);
        }
      } else {
        Serial.println("config not found");
      }

      SWITCH_TO_ETH;

    }

    typedef struct {
      char a;
      char b;
    } Btype;

    int convert2hex(const char *str, unsigned char *byte) // первый параметр указывает на массив символов, второй байт, возвращает колл-во байт
    {
      Btype *chp;
      chp = (Btype*)str;
      int i = 0;
      unsigned char c1, b1;
      while (chp[i].a) {
        c1 = (chp[i].a >= 65) ? 55 : 48;
        b1 = (chp[i].a - c1) << 4;
        c1 = (chp[i].b >= 65) ? 55 : 48;
        byte[i] = b1 | (chp[i].b - c1); i++;
      }
      return i;
    }

     
     
    Последнее редактирование: 13 сен 2015
  2. Unixon

    Unixon Оракул Модератор

    Каждая переменная живет только внутри своей области видимости, ограниченной блоком кода { ... }. Если вы определяете внутри блока переменную с таким же именем, как и снаружи, то наружная переменная становится недоступна, пока вы не покинете этот блок кода. Либо работайте с глобальными переменными, либо объявляйте локальные с другими именами и потом копируйте содержимое.
     
  3. AlexU

    AlexU Гуру

    Небольшое дополнение:
    глобальные переменные объявляем следующим образом
    Код (Text):
    byte localip[] = {0,0,0,0};
    byte _serverip[] = {0,0,0,0};
    потом в 'setup' задаем значения
    Код (Text):
    localip[0] = SplitString(ip, '.', 0).toInt();
    localip[1] = SplitString(ip, '.', 1).toInt();
    localip[2] = SplitString(ip, '.', 2).toInt();
    localip[3] = SplitString(ip, '.', 3).toInt();

    _serverip[0] = SplitString(server, '.', 0).toInt();
    _serverip[1] = SplitString(server, '.', 1).toInt();
    _serverip[2] = SplitString(server, '.', 2).toInt();
    _serverip[3] = SplitString(server, '.', 3).toInt();
    В Вашем случае, как отметил Unixon, в 'setup' создаются локальные переменные 'localip' и '_serverip', аналогичные глобальным. И этим локальным переменным задаются значения, которые после выхода из функции 'loop' теряются.
     
  4. egor2fsys

    egor2fsys Нуб

    Огромное спасибо Unixon и AlexU !
    Все получилось !