Прошу помочь со скетчем, перевод значений в строку

Тема в разделе "Arduino & Shields", создана пользователем ExGen, 6 окт 2019.

  1. ExGen

    ExGen Нуб

    Ardiuno IDE 1.8.2
    Arduino Nano 328p 16 MHz
    Есть полный скетч:
    Код (C++):
    // Include the libraries we need
    //#include <OneWire.h>
    #include <DallasTemperature.h>
    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>
    LiquidCrystal_I2C lcd(0x27,16,2);
    //#include "DHT.h"
    #include "RTClib.h"

    #include <SPI.h>
    #include <SD.h>
    const int chipSelect = 4;

    #define ONE_WIRE_BUS 9 //подключение DS18B20 в будущем
    #define RELE 7
    #define BUZZER 6

    #define UPTR 5 //темпер выключения реле 9
    #define DOWNTR 3 //темпер включения реле 2
    #define TBUZZ 0 //темпер включения реле 0 град

    #define DHTPIN 10 //контакт датчика
    float tempCH, tempC;

    int h;
    boolean vkl;
    byte simvol[8]   = {B11100,B10100,B11100,B00000,B00000,B00000,B00000,B00000,};
    //DHT dht(DHTPIN, DHT11);

    DS1307 rtc;
    char daysOfTheWeek[7][9] = {"SU", "MO", "TU", "WE", "TH", "FR", "SA"};
    unsigned long time1,time2,time3;
    //String namefile;

    OneWire oneWire(ONE_WIRE_BUS);
    DallasTemperature sensors(&oneWire);
    DeviceAddress insideThermometer;

    void lcdZeroPaddedPrint(long i, byte len, bool decimal = false) {
      if (i < 0) { // negate value
        i = i * -1;
        lcd.print("-");
      }

      switch (len)
      {
        case 6:
          lcd.print(i / 100000);
          i %= 100000;
        case 5:
          lcd.print(i / 10000);
          i %= 10000;
        case 4:
          lcd.print(i / 1000);
          i %= 1000;
        case 3:
          lcd.print(i / 100);
          i %= 100;
        case 2:
          lcd.print(i / 10);
          i %= 10;
          if (decimal) lcd.print(".");
        default:
          lcd.print(i);
      }
    }

    unsigned long deltamills(unsigned long t_old, unsigned long t_new) {
      unsigned long delta;
      if ( t_old <= t_new ) {
        delta = t_new - t_old;
      } else {
        delta = (4294967295 - t_old) + t_new;
      }
      return delta;
    }



    void setup(void)
    {
      vkl=false;
      lcd.init();                
      lcd.backlight();// Включаем подсветку дисплея
      pinMode(RELE, OUTPUT);
      pinMode(BUZZER, OUTPUT);
      Serial.begin(9600);
    // dht.begin();

      sensors.begin();
      Serial.print(sensors.getDeviceCount(), DEC);
      Serial.print("Parasite power is: ");
      if (sensors.isParasitePowerMode()) Serial.println("ON");
      else Serial.println("OFF");
      if (!sensors.getAddress(insideThermometer, 0)) Serial.println("Unable to find address for Device 0");

      printAddress(insideThermometer);
      sensors.setResolution(insideThermometer, 9);
      Serial.print(sensors.getResolution(insideThermometer), DEC);

      rtc.begin();
        if (! rtc.isrunning()) {
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("RTC NO!");
        rtc.adjust(DateTime(__DATE__, __TIME__)); //тянем время в ПК
      }
      time2=millis();
        Serial.print("Initializing SD card...");
      // see if the card is present and can be initialized:
      if (!SD.begin(chipSelect)) {
        Serial.println("Card failed, or not present");
        // don't do anything more:
        return;
      }
      Serial.println("card initialized.");
    }
    void loop(void)
    {
        DateTime now = rtc.now();

        char buf[100];
        char buf2[100];
        //strncpy(buf,"DD.MM.YYYY  hh:mm:ss",100);
        strncpy(buf,"hh:mm:ss DD-MM",100);
        strncpy(buf2,"DD.MM.YYYY hh:mm:ss",100);
        if (deltamills(time1,millis())>1000) {
        time1=millis();
        lcd.setCursor(0,0);
        lcd.print(now.format(buf));
        lcd.setCursor(9,0);
        lcd.setCursor(14,0);
        lcd.print(daysOfTheWeek[now.dayOfWeek()]); lcd.print(" ");
        lcd.createChar(1, simvol);
        lcd.setCursor(12, 0);
        lcd.setCursor(0, 1);
        lcdZeroPaddedPrint(tempC*10, 3, true); lcd.print("\1 ");  lcd.print(h); lcd.print("% ");  lcd.print(DOWNTR); lcd.print("-"); lcd.print(UPTR);  if (vkl) lcd.print(" E"); else lcd.print(" D");
        }

      if (deltamills(time3,millis())>2000) {
      time3=millis();
      Serial.print(now.format(buf2)); Serial.print("  ");
      sensors.requestTemperatures(); // Send the command to get temperatures
      tempC = sensors.getTempC(insideThermometer);
      Serial.print("DST: ");  Serial.print(tempC); Serial.println(" ");
    // h = round(dht.readHumidity());
    //  tempCH = dht.readTemperature();
    //  Serial.print("В ");Serial.print(h); Serial.print(" T ");Serial.println(tempCH);
    //  if (isnan(h) || isnan(tempCH)) {
    //  return;
    //  }
      }

      if (millis() > 5000) {
      if (tempC <= DOWNTR) {digitalWrite(RELE, HIGH); vkl=true;}
      else if (tempC >= UPTR) {digitalWrite(RELE, LOW); vkl=false;}

      if (tempC <= TBUZZ) {digitalWrite(BUZZER, HIGH);}
      else if (tempC > TBUZZ) {digitalWrite(BUZZER, LOW);}
      }

      if (deltamills(time2,millis())>10000) {
      time2=millis();

      String dataString = "";
      dataString += String(now.format(buf2));
      dataString += " DST: ";
      dataString += String(tempC);
      File dataFile = SD.open("log2.txt", FILE_WRITE);
      if (dataFile) {
      dataFile.println(dataString);
      dataFile.close();
        // print to the serial port too:
      Serial.println("WRITE: ");
      Serial.println(dataString);
      }
      // if the file isn't open, pop up an error:
      else {
      Serial.println("error opening datalog.txt");
      Serial.println(dataString);
      }
      }


    }

    //DS18B20
    void printAddress(DeviceAddress deviceAddress)
    {
      for (uint8_t i = 0; i < 8; i++)
      {
        if (deviceAddress[i] < 16) Serial.print("0");
        Serial.print(deviceAddress[i], HEX);
      }
      Serial.println(" ");
    }

    Все работает, за исключением участка:
    Код (C++):
      String dataString = "";
      dataString += String(now.format(buf2));
      dataString += " DST: ";
      dataString += String(tempC);
      File dataFile = SD.open("log2.txt", FILE_WRITE);
      if (dataFile) {
      dataFile.println(dataString);
      dataFile.close();
        // print to the serial port too:
      Serial.println("WRITE: ");
      Serial.println(dataString);
    dataString формировал и просто как dataString = String(now.format(buf2)) + " DST: " + String(tempC);
    Но значения в строку не переводит.
    Либо часть значений переводит в строку. Формат типа:
    Код (C++):
    String dataString = "";
      dataString += "DST: ";
      dataString += String(tempC);
    нормально работает.

    в логе вижу:
    Код (C++):
    1Parasite power is: OFF
    28757E4592020289
    9Initializing SD card...card initialized.
    06.10.2019 15:54:45  DST: 15.50
    06.10.2019 15:54:47  DST: 15.50
    06.10.2019 15:54:49  DST: 15.50
    06.10.2019 15:54:51  DST: 15.50
    06.10.2019 15:54:53  DST: 15.50
    WRITE:
    DST:
    06.10.2019 15:54:55  DST: 15.50
    06.10.2019 15:54:57  DST: 15.50
    06.10.2019 15:54:59  DST: 15.50
    06.10.2019 15:55:01  DST: 15.50
    06.10.2019 15:55:03  DST: 15.50
    WRITE:
    DST:
    06.10.2019 15:55:05  DST: 15.50
    06.10.2019 15:55:07  DST: 15.50
     
    Дату добавлял также частями, типа год + месяц + день и т.д.... и только год показывает, вместо остальных значений - ничего...
    Тестовые скетчи для SD карты отрабатывают отлично, на основе одного из них и сделан этот код.
    Ничего не понимаю. Подскажите куда копать? Или чего я не учитываю?
     
    Последнее редактирование: 6 окт 2019
  2. Asper Daffy

    Asper Daffy Гуру

    Код переполнен всякими чудесатостями. Особенно доставляет функция deltamills - мало того, что нафиг не нужна, так она ещё и врёт безбожно.

    Что касается проблемы с формированием строки, поставь печать текущего значения dataString после каждой строки, начиная с "String dataString ="";" и заканчивая "File dataFile = ...". Увидишь, что происходит. Заодно убери пока печать из под "if (deltamills(time3, millis()) > 2000)" или сделай. чтобы эти печати отличались, а то у тебя хрен поймёшь что печатается.
     
    Последнее редактирование: 6 окт 2019
    DetSimen нравится это.
  3. ExGen

    ExGen Нуб

    Если есть иной путь не тормозя выполнение программы выполнять действия с определенным промежутком времени - прошу подсказать. Функция не моя, взял с рабочей программы одной.

    Сделал, да и делал ранее... Иногда что-то убирая на печать, получаю что начинает выводить и записывать температуру.. И год выводит и записывает, если дату по частям собирать и год самый первый в формировании строки ' dataString += String(now.year(), DEC); ' следующие строки уже пустотой выводит...
    Походу слишком я память засрал... То выводит, то не выводит...
    ***
    Да... Одну функцию прибил, стало отрабатывать... Реально видимо засрал память... буду дальше вырезать некритичные участки...
    И прошу подсказать, чем можно более оптимально заменить deltamills ?
     
    Последнее редактирование: 7 окт 2019
  4. Asper Daffy

    Asper Daffy Гуру

    Ничем. Она просто не нужна, её нужно выбросить и заменить обычным вычитанием старого значения из нового. Обычное вычитание, кстати, работает правильно (не врёт на 1 как Ваша функция).
    Так вставьте контроль памяти. String же пытается выделить память каждый раз. Это можно проверить, но Вы нигде не проверяете.

    Вообще, неясно, зачем нужен String c его динамическими запросами, почему не обойтись массивом символов.

    Также неясно, зачем нужны такие огромные buf2 и buf? Мало того, что они всего по 15 байтов (а выделено 100), так они ещё и одинаковые. Зачем?
     
    arkadyf и ExGen нравится это.
  5. ExGen

    ExGen Нуб

    Благодарю за развернутый ответ! Функции брал из готовых иных скетчей и пока не заморачивался с оптимизацией, что где-то выделено больше памяти, чем нужно.
    Спасибо!:)