[QUESTION] i2c LCD 1602, рандомно "умирает", лезут крякозябры.

adrift_into_infinity
adrift_into_infinity аватар
Offline
Зарегистрирован: 02.10.2017

Доброго времени суток, господа!

Честное слово, пытался покороче, но, как обычно, не получилось =)

Не уверен, куда именно стоило разместить тему, т.к. нет 100% уверенности в природе моей проблемы.

Собственно, после своего первого мозгодробительного (для меня) опыта ковыряний с ардуиной, решил последовать совету начать с чего-то попроще. Напомню, познания в программировании у меня почти никакие, в электротехнике на уровне "что-то такое слышал", но что такое - зачастую без понятия. Т.е. почти нулевые. 

Проблему ждал всякую, да не ту, что у меня возникла. А проблема с экранчиком - лезут крякозябры спустя рандомное время, и у меня никак не получается найти причину. Но, прежде чем кидаться помидорами, и отправлять в поиск (к слову, я оттуда и пришел), хочу заметить, что проблема возникает совершенно рандомно. Т.е. не так, как у других людей в темах типа "оно вообще не пашет", или "подсветка горит, буковок нет", и т.п. Экран показывает все как надо! Может проработать и час, и два, отображая все как надо, а может и сразу начать выдавать крякозябры.

Из "железа":
1) Собственно, "виновник торжества": экранчик (LCD 1602) с адаптером i2c ("Serial I2C LCD display adapter", экранчик вместе с ним шел):
Из опознавательных знаков только надпись позади самой платы экрана "QAPASS", а на адаптере едва видно "PCF8_74_". На месте нижних подчеркиваний символы стерты. Вероятно, это "PCF8574I". Похоже на это:

2) "Китайдуино". Если верить тому, что написано на плате, то это "robotdyn nano v3 328p". Правда, качество сборки наталкивает на мысль, что это китайская копия китайской ардуины =) 

3) DHT22. Ничего необычного.
4) Tiny RTC i2c (DS1307), проведена "процедура лечения". АКА "Часы НЕреального времени" =) 

Лечение такое: Выпаял R4, R5, R6, D1, и на месте R6 сделал перемычку (дабы не заряжать обычную батарейку). Питание от обычной cr2032. Изначально часы убегали (примерно, точно не замерял) вперед минут на 12-15 в сутки. Следуя рекомендации в интернете, припаял корпус резонатора (или правильнее сказать "кварца"?) к земле (старался не перегревать его). И уже после этого они стали убегать вперед где-то минут на 5 за трое суток. Всяко лучше прежних 15 минут в сутки.
5) Какой-то преобразователь на LM317T с настройкой выходного напряжения. Питание на него подается с аккума на 12 В. На выходе с него установил 9.00 В. Ток заявлен был 1.5 ампера длительно. Выглядит так:

Ну, вот и все. Для большей наглядности попробовал сделать картинку как подключил все:

Пара моментов:
1) Крона тут представляет собой 12 В аккум подключенный через модуль на ЛМ317Т (не нашел в списке подходящий вариант)
2) Напряжение батарейки "часов нереального времени" пришлось продублировать отдельной батарейкой, т.к. на том модуле контакты батареи были недоступны.

Повторюсь, все работает (часы, DHT22, сам экран), просто в совершенно рандомное время начинают лезть крякозябры. Зависимости найти не смог =( При этом сама ардуина продолжает работать, а вот экран уже без ресета не оживает.

Проверял напряжение на пинах +5 и GND ардуины, оно обычно 4.99 В. Изредка может просесть до 4.95 В, но потом быстро возвращается.
 

Код:
 


//-----------------------------------

#include <Wire.h>

#include <RTClib.h>

#include <DHT.h>
#include <DHT_U.h>

#include <LiquidCrystal_I2C.h>

#include <i2cdetect.h>

//-----------------------------------

#define led_pin PD2 //D2
#define RTC_BATTERY A7
#define DHTPIN 9  //D9
#define DHTTYPE DHT22

//-----------------------------------

DS1307 RTC;
unsigned long RTCpreviousMillis = 0;
unsigned short RTCshowinterval = 1000;

DHT dht(DHTPIN, DHTTYPE); // 50, 68
bool DHT22conversionInProgress, DHT22_isFailed, DHTonCOOLDOWN = 0;
unsigned long DHT22conversionStartTime, LastTimeDone = 0;
float h, t, hic = 0;

LiquidCrystal_I2C lcd(0x26, 16, 2);
bool SecondLineStepOne = 1;
unsigned long prevHintSwitchTime = 0;
unsigned short HintSwitchTime = 1000, TimeToShow = 0;

//-----------------------------------

bool DEBUG = 0;

void setup()
{
  pinMode(led_pin, OUTPUT);
  pinMode(RTC_BATTERY, INPUT);

  Wire.begin();
  RTC.begin();
  dht.begin();

  if ( DEBUG ) {
    Serial.begin(2000000);

    // i2c scaner from example
    Serial.print("Scanning address range 0x03-0x77\n\n");
    i2cdetect();  // default range from 0x03 to 0x77
    delay(2000);
  }

  // if (1 == 1) use only once for RTC setup or for sync
  if (1 == 0) {
    RTC.adjust( DateTime( __DATE__, __TIME__ ) );
    DateTime now = RTC.now();
    //add ~x.0 sec as compensation of compile & upload time
    RTC.adjust( DateTime( now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second() + 9.0 ) );
  }

  if ( !RTC.isrunning() ) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    RTC.adjust( DateTime( __DATE__, __TIME__ ) );
  }

  // LCD //
  lcd.init();
  lcd.backlight(); lcd.cursor(); lcd.noBlink();

  // Short blink to show that setup is finished
  digitalWrite(led_pin, HIGH); delay(10); digitalWrite(led_pin, LOW);
}

//-----------------------------------

void loop()
{
  check_RTC();
  check_DHT22();
}

//-----------------------------------

void check_RTC() {
  unsigned long RTCcurrentMillis = millis();
  if ( RTCcurrentMillis - RTCpreviousMillis >= RTCshowinterval ) {
    RTCpreviousMillis = RTCcurrentMillis;

    float Vref = 4.99;  // measured with voltmeter
    float RTC_BATTERY_VOLTAGE = ( analogRead( RTC_BATTERY ) * Vref / 1024.0 );  // Output in Volts
    delay(50);

    DateTime now = RTC.now();

    if ( DEBUG ) {
      Serial.print( now.year(), DEC ); Serial.print('/');
      Serial.print( now.month(), DEC ); Serial.print('/');
      Serial.print( now.day(), DEC ); Serial.print(' ');

      Serial.print( now.hour(), DEC ); Serial.print(':');
      Serial.print( now.minute(), DEC ); Serial.print(':');
      Serial.print( now.second(), DEC ); Serial.print(" ");

      Serial.print("Voltage: "); Serial.print( RTC_BATTERY_VOLTAGE, 4 ); Serial.println(" V");
    }

    String RTC_VOLTAGE = String ( RTC_BATTERY_VOLTAGE, 2 );
    String RTC_TIME = String( now.hour(), DEC ) + ":"
                      + String( now.minute(), DEC ) + ":"
                      + String( now.second(), DEC );

    lcd.setCursor(0, 0); lcd.print("                ");
    lcd.setCursor(0, 0); lcd.print(RTC_TIME + " " + RTC_VOLTAGE + " V");
  }
}

//-----------------------------------

unsigned char read_dht22(void) {
  unsigned long DHT22currentTime = millis();
  if ( DHT22conversionInProgress == 0 ) {
    // 8000 ms as cooldown + 2000 for measure and conversion = new measurement every 10 sec.
    if ( DHT22currentTime - LastTimeDone > 8000 ) {
      dht.begin();
      DHT22conversionInProgress = 1;
      DHT22conversionStartTime = DHT22currentTime;
      return 2; // IN PROGRESS
    }
    else {
      return 3; // COOLDOWN
    }
  }
  else {
    if ( DHT22currentTime - DHT22conversionStartTime > 2000 ) {
      DHT22conversionInProgress = 0;
      h = dht.readHumidity();
      t = dht.readTemperature();  // Read temperature as Celsius (the default)

      // Check if any reads failed and exit early (to try again).
      if (isnan(h) || isnan(t)) {
        Serial.println("Failed to read from DHT sensor!");
        DHT22_isFailed = true;
        digitalWrite(led_pin, HIGH);
        hic = 0;
        return 0; // ERROR
      }

      // If we have reached here, then everyting is allright or failure fixed
      if (DHT22_isFailed == 1) {
        DHT22_isFailed = false;
        digitalWrite(led_pin, LOW);
        Serial.println("DHT22: Failure fixed!");
      }

      // Calculate "Heat Index"
      hic = dht.computeHeatIndex(t, h, false);  // Compute heat index in Celsius (isFahreheit = false)
    }
    else {
      return 2; // Still in progress
    }
    LastTimeDone = millis();
    return 1; // DONE
  }
}

//-----------------------------------

void check_DHT22(void) {
  unsigned char DHT22state = read_dht22();  // Get sensor state (ERROR || DONE || inPROGRESS || onCOOLDOWN || UNKNOWNERROR)

  // Redraw every HintSwitchTime (ms) + TimeToShow (ms)
  unsigned long currentHintSwitchTime = millis();
  if ( ( currentHintSwitchTime - prevHintSwitchTime > HintSwitchTime + TimeToShow ) && SecondLineStepOne == true ) {
    SecondLineStepOne = false;
    prevHintSwitchTime = currentHintSwitchTime;
    TimeToShow = 3000;

    lcd.setCursor(0, 1); lcd.print("                ");
    lcd.setCursor(0, 1); lcd.print("HUM/TEMP/HIC");
  }
  else if ( ( currentHintSwitchTime - prevHintSwitchTime > HintSwitchTime + TimeToShow ) && SecondLineStepOne == false ) {
    SecondLineStepOne = true;
    prevHintSwitchTime = currentHintSwitchTime;
    TimeToShow = 7000;

    lcd.setCursor(0, 1); lcd.print("                ");
    lcd.setCursor(0, 1); lcd.print(String(h, 1) + '/' + String(t, 1) + '/' + String(hic, 1));  // Shorten to one-tenth, otherwise the string won't fit
  }
  else {
    // Not a time to redraw
  }

  // Conversion done?
  unsigned long DHT22currentMillis = millis();
  if ( DHT22currentMillis - DHT22conversionStartTime > 2000 ) {
    switch ( DHT22state )
    {
      case 0 :  // ERROR
        if ( DEBUG ) {
          Serial.println("DHT22: ERROR!");
        }
        break;

      case 1 :  // DONE
        if ( DEBUG ) {
          DHTonCOOLDOWN = false;

          Serial.print("Humidity: "); Serial.print(h); Serial.println(" %");
          Serial.print("Temperature: "); Serial.print(t); Serial.println(" C");
          Serial.print("Heat Index: "); Serial.println(hic);
        }
        break;

      case 2 :  // IN PROGRESS
        if ( DEBUG ) {
          Serial.println("DHT22: Conversion IN PROGRESS...");
        }
        break;

      case 3 :  // ON COOLDOWN
        if ( DEBUG ) {
          if ( DHTonCOOLDOWN == false ) {
            DHTonCOOLDOWN = true; // For debug and to not to spam into console

            Serial.println("DHT22: On COOLDOWN.");
          }
        }
        break;

      default : // UNKNOWN ERROR
        if ( DEBUG ) {
          Serial.println("DHT22: Strange... We should NOT have got here");
        }
        break;
    }
  }
}

//-----------------------------------

 

Наконец, кратко поясню что выводиться на экранчик. 
1 строка: Каждую секунду выводим текущее вермя и напряжение батареи модуля часов. Т.е. строка перерисовывается каждую секунду.
2 строка: Сначала 3 секунды показываем подсказку "HUM/TEMP/HIC". Потом в течении 7 секунд показываем текущие измеренные значения в формате "XX.XX/XX.XX/XX.XX". Т.о. 2 строка перерисовывается 2 раза за 10 секунд: первый раз через 3 секунды, потом через 7, и так по кругу.

Вроде ничего важного не упустил... Так в чем же косяк? Из-за чего могут начать лезть крякозябры? Буду рад подсказкам. Пардон, если это что-то очевидное...

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Где-то память портица. 

А сериал лиарьно на такой скорости пашеть? 

Serial.begin(2000000);

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

Вопрос, как это собрано? На проводках (соплях), аля макет или все пропаяно?

adrift_into_infinity
adrift_into_infinity аватар
Offline
Зарегистрирован: 02.10.2017

DetSimen пишет:

Где-то память портица. 

А сериал лиарьно на такой скорости пашеть? 

Serial.begin(2000000);

Так точно.

DetSimen пишет:

Где-то память портица. 

Подразумевается что она портится на каком уровне? Железном или программном?

Учитывая, что питание довольно стабильное (ну, на мой неопытный взгляд), испортиться она должна скорее программно. Проблема с Ардуиной как я понимаю, отпадает, ибо в консоль она все отлично выводит даже тогда, когда экранчик внезапно умирает, и даже спустя час и более после "смерти" экранчика.

А что именно может ее испорить? Электромагнитные помехи? Нестабильное питание? Во всяком случае, в даташите к такому экрану пишут что питаться он может от 3 (минимум) до 6 (максимум) Вольт. А у меня на +5 пине ниже 4.9 В не опускается. Во всяком случае я ниже ни разу не заметил ни на обычном вольтметре, ни на измеренном самой ардуиной (вплоть до сотых совпадает).

bwn пишет:

Вопрос, как это собрано? На проводках (соплях), аля макет или все пропаяно?

На соплях, конечно же. Рано мне еще делать платы =) Длина одной сопли около 10 см (от кончика одного пина до кончика второго пина).

Я по мере знакомства с переферией подключаю оную и быдлокодю, что можно, собственно, заметить в коде. Но вот до создания своих плат - мне как раком до Китая, да еще на цыпочках. Я, конечно, уже покурил тему немного, и подумываю о ЛУТе (если вообще доберусь до этого), ибо с фоторезистом как-то муторно выходит... Да и не думаю, что в ближайшее время мне понадобится делать такие проекты, что ширина дорожек получающаяся с помощью ЛУТа будет через чур велика. Но это немного я заоффтопился...

Уже посетила мысль что может быть дело в радиопомехах. Может, тогда стоит сделать экран из фольги (а ведь еще и шапочку надо бы! =Р)? Где-то такое вычитал в сети, и вроде как человеку даже помогло. Но, если я правильно понимаю, то надо будет еще к фольге припаять проводок и соединить с землей (минусом) ардуины. Верно ли это? Поможет ли? И если да, то может оклеить небольшую коробочку фольгой и поместить все это дело внутрь, а экран вывести наружу? Или это совсем ересь в данном случае? 

Хотя вон, в витухе (обычно в категории 6 и выше) могут экранировать каждую пару фольгой, да еще и экран общий в довесок бывает, и это все соединяется и заземляется вполне успешно. Хотя, сравнивать, конечно, не особо то и корректно. Но суть вроде как одна...

Гриша
Offline
Зарегистрирован: 27.04.2014

adrift_into_infinity пишет:

bwn пишет:

Вопрос, как это собрано? На проводках (соплях), аля макет или все пропаяно?

На соплях, конечно же. Рано мне еще делать платы =) Длина одной сопли около 10 см (от кончика одного пина до кончика второго пина).

провода пропаяны или разъмы стоят???

adrift_into_infinity
adrift_into_infinity аватар
Offline
Зарегистрирован: 02.10.2017

Гриша пишет:

adrift_into_infinity пишет:

bwn пишет:

Вопрос, как это собрано? На проводках (соплях), аля макет или все пропаяно?

На соплях, конечно же. Рано мне еще делать платы =) Длина одной сопли около 10 см (от кончика одного пина до кончика второго пина).

провода пропаяны или разъмы стоят???

В данный момент почти все на проводах-перемычках типа BLS. До этого все тестировал на... кхм... как бы их назвать... вот на таких:
 вот такие

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

Пока не обеспечите хороший контакт по шине питания и данных на LCD (он кстати под 100мА с подсветкой жрет) говорить особо не о чем. Экранировка - паранойя, если конечно не под высоковольтной ЛЭП живете. ИМХО.

Гриша
Offline
Зарегистрирован: 27.04.2014

сам первый раз наступил на грабли под названием макетная плата с такими проводами, в оконцове их же и припаял, а потом отпаял и пользую их дальше. Просто аккуратно зачистил после пайки. для светодиодов их можно просто воткнуть, но для шины связи пайка 100% обязательна.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Стопудово память переполняется. Поставьте печать адреса выделенного куска в функцию запроса памяти класса String и убедитесь сами.

sadman41
Offline
Зарегистрирован: 19.10.2016

А я бы спросил для начала, что за кракозябры. Может это экран на родимом китайском просит пощадить...

adrift_into_infinity
adrift_into_infinity аватар
Offline
Зарегистрирован: 02.10.2017

bwn пишет:

Пока не обеспечите хороший контакт по шине питания и данных на LCD (он кстати под 100мА с подсветкой жрет) говорить особо не о чем. Экранировка - паранойя, если конечно не под высоковольтной ЛЭП живете. ИМХО.

Понял вас, с экранировкой - отбой. А сами провода с BLS разъемами считаются "плохими" или "хорошими" контактами? У меня они на штыри довольно туго натягиваются, к слову.

Кстати, на счет пожирания 100 мА экраном с  подсветкой. У меня меньше кушает, оказывается.
С модуля питания на ЛМ317Т замерил ток текущий в VIN ардуины.
На выходе модуля питания:
- 9.00 В, 61.2-62.6 мА с включенной подстветкой экрана
- 9.00 В, 10-12 мА без оной (снял джампер отвечающий за питание подсветки на экране).

При таком питании, на +5 пине имеем 4.98-4.99 В и 51-52 мА с учетом подключенной переферии и включенной подстветки экрана.

Судя по описанию, снятие с +5 пина до 200 мА не является проблемой. С самих пинов ардуины норма 20 мА, но можно и 40 мА, хотя не рекомендуется. Так что, в эти рамки мы свободно влезаем.

В общем, если все же строго пайка нужна, то мне нужно сообразить плату для верности? Или достаточно припаять провода напрямую к штырям ардуины и экрана? Имею ввиду, что пайка "напрямую" = голый провод без разъемов припаивается прямо к штырю. 

Нуидела
Offline
Зарегистрирован: 31.01.2017

Здравствуйте, я бы для начала поменял 4 проводка идущие от блока I2C, припаяного к LCD.
(не зря тут было сказано "Пока не обеспечите хороший контакт по шине питания и данных на LCD").

adrift_into_infinity
adrift_into_infinity аватар
Offline
Зарегистрирован: 02.10.2017

Гриша пишет:

сам первый раз наступил на грабли под названием макетная плата с такими проводами, в оконцове их же и припаял, а потом отпаял и пользую их дальше. Просто аккуратно зачистил после пайки. для светодиодов их можно просто воткнуть, но для шины связи пайка 100% обязательна.

Понял, значит паяем =)

ЕвгенийП пишет:

Стопудово память переполняется. Поставьте печать адреса выделенного куска в функцию запроса памяти класса String и убедитесь сами.

Понял, что ничего не понял, но разберусь =)

sadman41 пишет:

А я бы спросил для начала, что за кракозябры. Может это экран на родимом китайском просит пощадить...

На иероглифы не похоже... ну, во всяком случае на те, что показывает гугл для этих экранов. Иногда мелькает что-то похожее, но все равно не то. Глаза вытекают на такое смотреть =)

Нуидела пишет:

Здравствуйте, я бы для начала поменял 4 проводка идущие от блока I2C, припаяного к LCD.
(не зря тут было сказано "Пока не обеспечите хороший контакт по шине питания и данных на LCD").

Приветствую! А поменять на что? Не припаивать же штыри экрана на печатную плату? Как-то это дико выходит что-ли...

2 ALL, всем спасибо за ответы, как что-то получу - отпишусь сюда.

Нуидела
Offline
Зарегистрирован: 31.01.2017

Поменяйте на куски от витухи (можно/лучше припаять)

sadman41
Offline
Зарегистрирован: 19.10.2016

Попробуйте sprintf(). Он явно не больше пожрет, чем String class, но память не будет дырявить почем зря.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sadman41 пишет:

Попробуйте sprintf(). Он явно не больше пожрет, чем String class, 

1. больше. 2. ТС не умеет.

inspiritus
Offline
Зарегистрирован: 17.12.2012

Пинчики в бредборде штука коварная, на расстоянии сантиметра по питанию падение может пары вольт достигать

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

adrift_into_infinity пишет:

ЕвгенийП пишет:

Стопудово память переполняется. Поставьте печать адреса выделенного куска в функцию запроса памяти класса String и убедитесь сами.

Понял, что ничего не понял, но разберусь =)

А чего тут не понимать - это самая дешёвая проверка, которая, может быть, снимет все вопросы.

1. Лезете в папку <где установлена IDE>\hardware\arduino\avr\cores\arduino
2. Там открываете файл WString.cpp
3. В этом файле ищете функцию String::changeBuffer. У меня она выгладит вот так.

unsigned char String::changeBuffer(unsigned int maxStrLen)
{
	char *newbuffer = (char *)realloc(buffer, maxStrLen + 1);
	if (newbuffer) {
		buffer = newbuffer;
		capacity = maxStrLen;
		return 1;
	}
	return 0;
}

4. Непосредственно перед строкой "return 0;" (между "}" и "return 0;") вставляете что-нибудь: например включение светодиода или печать слова ACHTUNG в Serial - что-нибудь, что будет сигнализировать о беде.

Запускаете программу. Если Ваше "что-нибудь" сработало хоть раз - всё понятно, памяти не хватает. Если не срабатывает ни разу, то дело не в этом.

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

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

bwn пишет:

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

С засёром памяти никаким проводам не сравниться :))))

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

ЕвгенийП пишет:

bwn пишет:

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

С засёром памяти никаким проводам не сравниться :))))

Так хтож спорит. но как и положено, идем от простого к сложному. А вот в этом месте мнения расходятся.))))

sadman41
Offline
Зарегистрирован: 19.10.2016

bwn пишет:

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

Не вижу ни единой причины чтобы не сойтись вместе проблемам как железячным, так и программным. Каждый из нас посоветовал то, в чём больше понимает - что же тут страшного и спорного? Я тоже за то, чтобы всё на сварку посадить. Но это уже посоветовали и без меня. sprintf() поможет отсечь варианты связанные с проделками подлого стринга. Или, во всяком случае, локализовать их. 

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

sadman41 пишет:

bwn пишет:

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

Не вижу ни единой причины чтобы не сойтись вместе проблемам как железячным, так и программным. Каждый из нас посоветовал то, в чём больше понимает - что же тут страшного и спорного? Я тоже за то, чтобы всё на сварку посадить. Но это уже посоветовали и без меня. sprintf() поможет отсечь варианты связанные с проделками подлого стринга. Или, во всяком случае, локализовать их. 

Так и имел в виду, что каждый начинает с того, что для него проще. Хотя за провода, есть слова ТС, что дуина дальше продолжает работать, виснет только экран. С памятью думаю и МК вошел бы в ступор или здесь не прав?

sadman41
Offline
Зарегистрирован: 19.10.2016

bwn пишет:

Так и имел в виду, что каждый начинает с того, что для него проще. Хотя за провода, есть слова ТС, что дуина дальше продолжает работать, виснет только экран. С памятью думаю и МК вошел бы в ступор или здесь не прав?

Ну, почему, никто не мешает заслать LCD такой набор байтов, которые вызовут отображение второй части кодовой таблицы с иероглифами. Например - ардуинщик искренне хочет что-нибудь написать по-русски на LCD, а ему треклятый китаец за два доллара подсунул дисплей с катаной в прошивке. И вот бъётся этот несчастный, значится, неделю, две, качает всякие скетчи "русификации", оборачивает экран фольгой... А у него всё "кракозябры лезут". Или там, к примеру, забыл char buffer[] почистить и понеслось - прилетели в дисплей всякие \x08, \x02, всякая прочая веселуха. 

Вобщем, как говорится, на всякого мудреца довольно простоты. Пусть припаяет. Будем хотя бы знать, что дело не бобине. А так-то я на каких только соплях эти 1602 не подключал. Ни разу ничего не лезло ничего нежеланного. Или печатало или не печатало. Все остальное - это программные проблемы были. Инициализировать забыл или тайминги не выдержал, к примеру...

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

bwn пишет:

и МК вошел бы в ступор или здесь не прав?

Вообще, последствия распашки памяти совершенно не предсказуемы. И как раз в данной ситуации ничего ему не сделается.

А вообще, благодаря Блюму и прочим апостолам, которые в своих примерах никогда не проверяют результаты операций, все новоардуинщики пользуются стрингом совершенно варварски. Ну, блин, он же (стринг) сообщает, когда ему памяти не хватает, но кто б ещё на его сообщения внимание обращал и проверял их :(

nik182
Offline
Зарегистрирован: 04.05.2015

Ну так запустите привет мир из примеров в цикле выводя с первой позиции. Будут кракозябры значит провода. Не будет - память портится.

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

sadman41, Евгений, спасибо за разъяснения, на LCD только с аппаратными косяками сталкивался (но и стринги там не юзал), а вот на матрицах проблема возникла, но посадочно-строительно-уборочный сезон начался, оставил по минимуму лишь бы работало, зимой поразбираюсь.

adrift_into_infinity
adrift_into_infinity аватар
Offline
Зарегистрирован: 02.10.2017

ЕвгенийП пишет:

adrift_into_infinity пишет:

ЕвгенийП пишет:

Стопудово память переполняется. Поставьте печать адреса выделенного куска в функцию запроса памяти класса String и убедитесь сами.

Понял, что ничего не понял, но разберусь =)

А чего тут не понимать - это самая дешёвая проверка, которая, может быть, снимет все вопросы.

1. Лезете в папку <где установлена IDE>\hardware\arduino\avr\cores\arduino
2. Там открываете файл WString.cpp
3. В этом файле ищете функцию String::changeBuffer. У меня она выгладит вот так.

unsigned char String::changeBuffer(unsigned int maxStrLen)
{
	char *newbuffer = (char *)realloc(buffer, maxStrLen + 1);
	if (newbuffer) {
		buffer = newbuffer;
		capacity = maxStrLen;
		return 1;
	}
	return 0;
}

4. Непосредственно перед строкой "return 0;" (между "}" и "return 0;") вставляете что-нибудь: например включение светодиода или печать слова ACHTUNG в Serial - что-нибудь, что будет сигнализировать о беде.

Запускаете программу. Если Ваше "что-нибудь" сработало хоть раз - всё понятно, памяти не хватает. Если не срабатывает ни разу, то дело не в этом.

"Поставьте печать адреса выделенного куска в функцию запроса памяти класса String" - вот эту строчку не понял. Для начала понять бы что за "функция запроса памяти класса String". Потом попытаться понять о каком "выделенном куске" идет речь (кусок чего именно?). А в довесок еще "поставить печать адреса" этого самого куска. 

Догадываюсь, что "кусок" - это строка, "поставить печать адреса" - вывести адрес этой строки в памяти... а вот с "функцией запроса памяти класса String" - совсем ничего не понял. Может, это что-то очевидное, но мой мозг не может воспринять это предложение =( Знаний, видимо, не хватает.

Однако, сразу после прочтения вашего поста и попытке понять, что же надо сделать, решил пойти "простым" путем, и вспомнил одну тему вашу, на которую наталкивался на форуме:
http://arduino.ru/forum/programmirovanie/etyudy-dlya-nachinayushchikh-ko.... Собственно, как уже и было указано вами выше, я добавил эти строки, перезагрузил ИДЕ (у меня 1.8.5, если что), откомпилил по новой и залил скетч. Так же чуток подправил вот этот момент у себя:
 

    String RTC_VOLTAGE = String ( RTC_BATTERY_VOLTAGE, 2 );
    if ( RTC_VOLTAGE == false ) {
      Serial.print("PROBLEM WITH RTC_VOLTAGE STRING!");
    }

    String RTC_TIME = String( now.hour(), DEC ) + ":"
                      + String( now.minute(), DEC ) + ":"
                      + String( now.second(), DEC );
    if ( RTC_TIME == false ) {
      Serial.print("PROBLEM WITH RTC_TIME STRING!");
    }

Ну и "для скорости" сделал так:
 

//unsigned short RTCshowinterval = 1000; 
unsigned short RTCshowinterval = 10;

Экран потускнел после после "RTCshowinterval = 10", напряжение просело до 4.77 В и на 1 строчке начался ад эпилептика =) (стробоскопическй эффект). В остальном все хорошо, в консоли чисто, светодиод не загорается. 

*прошло минут 5* 
И вот, пока это все писал, все же экран вновь "умер". Ардуина как слала в сериал, так и шлет. Светодиод не загорался, в консоли ошибки не замечено. Нажал ресет, дисплей выдал сразу крякозябры. Нажал еще раз ресет - все вывелось как надо.

*прошло еще некоторое время, сейчас на часах 23.20 по Мск* На экране все отображается как надо. Светодиод так и не загорелся. В консоли без ошибок до сих пор.

В общем, оставлю до завтра работать, а там уже постараюсь что-то придумать с пайкой. 

Кстати, так что на счет "надежности" BLS-ных разъемов? Можно ли их считать надежными?

P.S. Немного залип с построением печатной платы во Фртицзинге... автоматическое построение - что-то с чем-то... некоторые линии по 2-3-4 раза дублирует через всю плату порой, а изгибов добавляет не в меру. Бррр... Ну да ладно, на сегодня хватит =)

 

sadman41 пишет:

bwn пишет:

Так и имел в виду, что каждый начинает с того, что для него проще. Хотя за провода, есть слова ТС, что дуина дальше продолжает работать, виснет только экран. С памятью думаю и МК вошел бы в ступор или здесь не прав?

Ну, почему, никто не мешает заслать LCD такой набор байтов, которые вызовут отображение второй части кодовой таблицы с иероглифами. Например - ардуинщик искренне хочет что-нибудь написать по-русски на LCD, а ему треклятый китаец за два доллара подсунул дисплей с катаной в прошивке. И вот бъётся этот несчастный, значится, неделю, две, качает всякие скетчи "русификации", оборачивает экран фольгой... А у него всё "кракозябры лезут". Или там, к примеру, забыл char buffer[] почистить и понеслось - прилетели в дисплей всякие \x08, \x02, всякая прочая веселуха. 

Вобщем, как говорится, на всякого мудреца довольно простоты. Пусть припаяет. Будем хотя бы знать, что дело не бобине. А так-то я на каких только соплях эти 1602 не подключал. Ни разу ничего не лезло ничего нежеланного. Или печатало или не печатало. Все остальное - это программные проблемы были. Инициализировать забыл или тайминги не выдержал, к примеру...

На счет "оборачивания экрана фольгой" - это камень в мой огород что ли? =) Да и я же ничего не говорил про китайцев, да и не у них брал, а у нас, и не за 2 бакса, а за 4 или 5 с копейками (да, было лень ждать) Да и не приходило в голову качать "скетчи русификации" даже. Что-то вы мне больно много "заслуг" приписали =)

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

adrift_into_infinity пишет:

Кстати, так что на счет "надежности" BLS-ных разъемов? Можно ли их считать надежными?

P.S. Немного залип с построением печатной платы во Фртицзинге... автоматическое построение - что-то с чем-то... некоторые линии по 2-3-4 раза дублирует через всю плату порой, а изгибов добавляет не в меру. Бррр... Ну да ладно, на сегодня хватит =)

На счет "оборачивания экрана фольгой" - это камень в мой огород что ли? =) Да и я же ничего не говорил про китайцев, да и не у них брал, а у нас, и не за 2 бакса, а за 4 или 5 с копейками (да, было лень ждать) Да и не приходило в голову качать "скетчи русификации" даже. Что-то вы мне больно много "заслуг" приписали =)

Любой разъем имеет свойство со временем окисляться, что на низковольтных и слаботочных цепях может быть фатально. Если хотите надежности - пайка-винт-скрутка, последнее нежелательно.
Для разводки использую DipTrace, денек подолбался, потом пошло на лад. Автотрассировка нормально работает на несложных платах, обычно авто и вручную.
За "камни" не обижайтесь, здесь публика разная проходит, в т.ч. и у китайцев кириллицу ищет (он ведь написал, что она есть).

adrift_into_infinity
adrift_into_infinity аватар
Offline
Зарегистрирован: 02.10.2017

bwn пишет:

adrift_into_infinity пишет:

Кстати, так что на счет "надежности" BLS-ных разъемов? Можно ли их считать надежными?

P.S. Немного залип с построением печатной платы во Фртицзинге... автоматическое построение - что-то с чем-то... некоторые линии по 2-3-4 раза дублирует через всю плату порой, а изгибов добавляет не в меру. Бррр... Ну да ладно, на сегодня хватит =)

На счет "оборачивания экрана фольгой" - это камень в мой огород что ли? =) Да и я же ничего не говорил про китайцев, да и не у них брал, а у нас, и не за 2 бакса, а за 4 или 5 с копейками (да, было лень ждать) Да и не приходило в голову качать "скетчи русификации" даже. Что-то вы мне больно много "заслуг" приписали =)

Любой разъем имеет свойство со временем окисляться, что на низковольтных и слаботочных цепях может быть фатально. Если хотите надежности - пайка-винт-скрутка, последнее нежелательно.
Для разводки использую DipTrace, денек подолбался, потом пошло на лад. Автотрассировка нормально работает на несложных платах, обычно авто и вручную.
За "камни" не обижайтесь, здесь публика разная проходит, в т.ч. и у китайцев кириллицу ищет (он ведь написал, что она есть).

Принято. Посмотрю DipTrace. Спасибо.

За камни не обижаюсь. Сам хоть и нулевый, но почитывая разные темы - диву даюсь порой (хотя сам  не очень и далеко ушел =) ).

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

sadman41
Offline
Зарегистрирован: 19.10.2016

adrift_into_infinity пишет:

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

На каких-то есть, на каких-то нет. Те, что нонейм 1602/2002/2004/etc - на 90% вероятности ее не имеют. Даже если в описании товара она в наличии.  Вы дисплей купили за 250р, не нашли там кириллицы и забили на это. Или не забыли, вступив в спор с продавцом. Тот в диспуте пишет - извини, май френд, ошибка вышла. Высылай дисплей назад, я тебе 250р верну. Идете на почту, а там вам сообщают, что отправка обойдется в 500р (условно). И еще таможенную декларацию надо заполнять. Какой процент потерпевших будет с этим связываться? Отзывчивый китаец тем временем продает дисплей следующему наивному ляоваю, делая свой небольшой бизнес.

"Брендованные" дисплеи имеют кириллицу с большим процентом вероятности. Мой винстар, к примеру, имеет.

Но бывают и такие персонажи, которые даже в нонеймах без заявленной кириллицы ищут ее до тех пор, пока всех не заеб... или со стула в изнеможении не грохнутся. Кракозябр в исполнении вашего дисплея мы не видели, вполне может быть, что опытный глаз сразу определит что почём.

BLS разъемы ваши разные бывают. Равно как и пинхидеры. Вот у вашей ардуины от RobotDyn должны быть нормальные. На материнских платах нормальные. В старых корпусах компутерных BLS качественные. Я такими свой дисплей на проводе в 25см держал без всякой пайки - с обоих сторон втыкалки. Но, алиэкспресс - это рулетка китайская, которая похлеще русской. Была у меня ардуина, у которой ноги зеленели. Спиртом их протрешь, в разъем вставишь - работают. Через месяцок вкл-выкл или вытащил ее из разъема и вставил обратно  - всё, абзац, через пень-колоду сигналы на SPI идут. Надоело спирт переводить, отдал ее пионерам. ...А то еще попадаются пинхидеры с более тонкими штырьками. Плановая экономия, так скыть. 

Так что, если не хотите экспериментов или глаз не наметан на такие подлянки - паяйте.

 

adrift_into_infinity
adrift_into_infinity аватар
Offline
Зарегистрирован: 02.10.2017

Доброго времени суток!

Где-то в 2 часа ночи экран вновь приказал жить и сразу же откинулся. Однако, в порт все так же приходили нормальные значения. Светодиод так и не зажегся. Видимо, с памятью все нормально.

Еще подумывал избавиться от стрингов посреди ночи... *тут автора пробрало на "ха-ха"*, но шаловливые руки как-то сами полезли потыкать во что-нибудь во фритзинге во вкладке с печатной платой. Итогом моих извращенных изысканий явилось сие:

Со второй попытки таки вытравил плату. Но, для себя решил, что для моих корявых рук ширину дорожек надобно делать раза в 2 больше, чем автоматом выбирается во фритзинге.

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

Теперь подключаю питание и... ардуина пашет, а монитор застыл словно на стадии инициализации с квадратиками в 1 строке и с пустой 2 строкой... Странно, раньше не замечал такого. "Ну, ресет поможет!" - подумал я. Но ресет сказал - "нЭт"(экран продолжал висеть, ардуина работала без проблем). Я еще разок пнул ресет, но реакции со стороны экранчика не было. Тогда я отключил питание и подождал секунд 5, после чего вновь запитал. И все так же. Ардуина пашет нормально, но экранчик не реагирует. Тогда я опять начал проверять все (хотя тут трудно ошибиться, но вдруг все же ошибся), но все оказалось верно. Подергал все места пайки, авось где-то непропаял и контакт теряется, но все оказалось в норме. Пока сидел и чесал репу, экранчик внезапно вышел из "комы" и выдал несколько крякозябр, и вскоре "самоочистился". Тогда я еще разок тыкнул ресет, и экран ожил как и раньше, и уже несколько часов работает без проблем. 

Только в отличии от сборки на макетке, теперь, при отключении и подключении питания, экран может и сразу заработать как надо, а может и "задуматься" секунд на 20-30, если не больше. Но как он "затрепыхается" - можно сразу жать ресет, и все начинает работать как надо. Может все же проблема в самом экране или его i2c адаптере? На макетке на соплях он хотя бы НЕ входил в кому при подаче питания, а сразу начинал что-то выдавать. Дурка какая-то получается с этим экраном. Может и правда, дело в коде? Но где именно? Косяков со строками так и не проявилось, кстати. 

В общем, я в растерянности. Вечером попробую заполучить еще один i2c модуль для экрана. Вдруг дело именно в нем, а новый заработает как надо...

adrift_into_infinity
adrift_into_infinity аватар
Offline
Зарегистрирован: 02.10.2017

sadman41, принял к сведению, спасибо. 

Для себя же брал экранчик ради "побаловаться", ну может еще и для дебага использовать. Наличие кириллицы было не важно.

sadman41 пишет:

Но бывают и такие персонажи, которые даже в нонеймах без заявленной кириллицы ищут ее до тех пор, пока всех не заеб... или со стула в изнеможении не грохнутся.

Хе хе хе, повеселило =D

А с "тонкими" пинами BLS лично встречался раньше. Та еще "кака". Пин гнется от легкого прикосновения, а если попытаться обратно отогнуть - зачастую обламывается. С тех пор даже не смотрю в их сторону, только "толстые" беру, ежели понадобятся.

P.S. уже все спаял, жду очередного "приступа" с крякозябрами =)

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

Для уверенности в отсутствии аппаратных проблем, запустите "HELLO WORLD" в цикле, да посмотрите денек. ИМХО.

5N62V
Offline
Зарегистрирован: 25.02.2016

adrift_into_infinity пишет:

А проблема с экранчиком - лезут крякозябры спустя рандомное время, и у меня никак не получается найти причину. 

У меня была такая фигня на 1602 экране. Но там присутствовала вибрация, перепад температур и давления. Решилось заменой экрана.

5N62V
Offline
Зарегистрирован: 25.02.2016

sadman41 пишет:

 sprintf() поможет отсечь варианты связанные с проделками подлого стринга. 

Пользовать sprintf() удобно, но буквально неделю назад столкнулся с фактом, когда после апгрейда (добавления кода) дуина начала уходить в перезагрузку. Сразу заподозрил память, т.к оперативка , если верить IDE , была на исходе. Исключил sprintf(), все заработало, и еще приобрел 10% свободной RAM. Вот. 

sadman41
Offline
Зарегистрирован: 19.10.2016

5N62V пишет:

Пользовать sprintf() удобно, но буквально неделю назад столкнулся с фактом, когда после апгрейда (добавления кода) дуина начала уходить в перезагрузку. Сразу заподозрил память, т.к оперативка , если верить IDE , была на исходе. Исключил sprintf(), все заработало, и еще приобрел 10% свободной RAM. Вот. 

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

Но в данный момент задача в том, чтобы локализовать проблему. 

sprintf мне и самому не особо нравится, но если в буфер нужно пихать сложноформатированную строку с несколькими разными переменными - то альтернативу ему найти сложно. Вернее - на каком-то этапе ее  поиск становится бессмысленным. А если еще и учесть, что есть такие волшебные штуки, как vsnprintf_P() и sprintf_P()...

oleg_kazakof
Offline
Зарегистрирован: 24.04.2015
lcd.clear();     //очистка дисплея 

добавте эту команду, мне это помогло

 

adrift_into_infinity
adrift_into_infinity аватар
Offline
Зарегистрирован: 02.10.2017

Вечер добрый, господа.

Вот, вернулся только что. Сразу пошел смотреть на экранчик, а он даже без крякозябр. Напряжение на +5 пине составляет сейчас 4.98 В, стабильно. Даже боязно отключать и подключать питание, дабы проверить на "коматозное" состояние после подачи питания. Лучше еще подожду, пока не полезут крякозябры.

bwn пишет:

Для уверенности в отсутствии аппаратных проблем, запустите "HELLO WORLD" в цикле, да посмотрите денек. ИМХО.

А надо ли? Перед тем как открыть топик, я в течении пары дней +- несколько часов гонял "почти чистый хелло ворлд", и крякозябры вылезали совершенно рандомно. Могли и сразу показаться, а могли и пару часов спустя.

"Почти чистый" ввиду того, что на экран хоть и выводилось только "хелло ворлд", на фоне ардуина еще считывала показания с DHT22 (раз в 2 секунды), но на экран инфу не выводила. А сделано было с целью выявления косяков с датчиком, ибо если бы он не смог хоть раз по какой-то причине получить корректные значения для температуры и/или влажности, то загорелся бы светодиод и уже бы не потух (в том варианте кода я еще не "обнулял" светодиод после устранения проблемы с датчиком). Но, т.к. светодиод за это время так и не загорелся ни разу, я решил что датчик нормальный.

5N62V пишет:

adrift_into_infinity пишет:

А проблема с экранчиком - лезут крякозябры спустя рандомное время, и у меня никак не получается найти причину. 

У меня была такая фигня на 1602 экране. Но там присутствовала вибрация, перепад температур и давления. Решилось заменой экрана.

А решилось именно заменой экранчика, или адаптера i2c? Уточните, пожалуйста.

Ну, перепады температуры, в принципе, есть, в пределах от 20 до 30 градусов, но не резкие (многочасовые плавные колебания могут быть). Вибрация не то что бы сильная, но когда проезжают по ЖД путям, всем телом чувствуется вибрация дома и мебели. Не ходуном ходит, конечно, но нельзя сказать, что она незаметная. Ну а давление атмосферное. Ничего криминального не вижу.

 

oleg_kazakof пишет:

lcd.clear();     //очистка дисплея 

добавте эту команду, мне это помогло

 

Куда именно добавить ее предполагается? 

Я ее уже использовал на ранних этапах, и для меня она оказалась лишней. Если ее в "Сетап" добавить после инициализации экранчика или же после последующих настроек оного - в поведении ничего принципиально не изменяется. А если добавлять ее перед отрисовкой всего экрана, то текст на экране будет заметнее "моргать".  Все это проверялось еще когда все было собрано на макетке. Так что, я просто не использую ее за ненадобностью.

 

oleg_kazakof
Offline
Зарегистрирован: 24.04.2015

Ставил в сетап, без неё происходило с дисплеем всё как описано у Вас, сейчас все проблемы исчезли (дисплеи 1602 и 2004).

 

 

5N62V
Offline
Зарегистрирован: 25.02.2016

adrift_into_infinity пишет:

А решилось именно заменой экранчика, или адаптера i2c? Уточните, пожалуйста.

Именно заменой дисплея.

sadman41
Offline
Зарегистрирован: 19.10.2016

adrift_into_infinity пишет:

Куда именно добавить ее предполагается? 

Я ее уже использовал на ранних этапах, и для меня она оказалась лишней. Если ее в "Сетап" добавить после инициализации экранчика или же после последующих настроек оного - в поведении ничего принципиально не изменяется.

Безотносительно вашего случая хочу отметить, что инициализация дисплея действительно может приводить состояние ячеек памяти его внутреннего буфера в случайное состояние, что выглядит, как мусор на экране (но  знаки будут вполне себе из кодовой страницы). После нее дисплей желательно "чиститить" через clear() (команда 0x01 контроллера) или сразу напечатать что-то поверху. Если "запечатывание" в алгоритме предусмотренно через определенные паузы, то внешне ситуация будет выглядеть как "полез мусор, потом стало нормально". Или - "полчаса видел прямоугольники, потом только пошли цифири".

Так как дисплей при очередном print() ничего не чистит у себя в памяти, то разнообразные наложения выводимых строк могут так же выглядеть, как сбой - например, было выведено число '1234', потом в эту же позицию прилетело '985'. В итоге пользователь видит '9854', недоумевает и ищет ошибку в вычислениях. Ну, а если, к примеру, до этого на дисплее был неочищенный после init() мусор, то...

...инициализированный и "очищенный" дисплей не требует, конечно, повторных операций clear(), однако МК, например, может вызывать init() не один раз за наблюдаемый цикл, даже если эта функция определена для вызова только  в setup(). Почему? Например - после soft reset в результате проблем с памятью МК, некорректным ее использованием.

Исходя из приведенных выше размышлений можно дать один совет для дополнительной проверки - выводить дополнительно аптайм на дисплей. Это может быть, как millis(), так и millis()/1000 (в зависимости от того, как хорошо вы запоминаете длинные числа).

 

adrift_into_infinity
adrift_into_infinity аватар
Offline
Зарегистрирован: 02.10.2017

В общем, тут с новостями...

Так и не дождался крякозябр, а аккум уже изрядно разрядился. Ну я и отключил все, воткнул другой аккум. Ну и по рекомендациям подправил в сетапе:
 

  // LCD //
  lcd.init();
  lcd.backlight(); lcd.cursor(); lcd.noBlink(); 
  lcd.clear();

Но ничего толком не изменилось. Экранчик мог впасть в кому после подачи питания сразу же, а мог и без проблем запуститься. Причем, зависал он не на один и тот же период... мог "протупить" в течении 3-15 секунд. Чаще тупило в районе 5-8 секунд (если, конечно же, экранчик не начинал работать в первые пару секунд). При этом питание 4.98-4.99 В на +5 пине. На плюсе возле экранчика нарпяжение аналогично напряжению на +5 пине. Ну, на самом деле все же немного отличается (на 0.005 В) относительно самого пина на ардуине. Но это скорее погрешность измерений.

НО! Кажется, я нашел странное решение своей проблемой подвисания экрана. Не 100% фикс, но заметно лучше, чем без него.  Я подправил код вот так:
 

  // LCD //
  lcd.init();

  lcd.setCursor(0, 0); lcd.print("0123456789ABCDEF");
  lcd.setCursor(0, 1); lcd.print("FEDCBA9876543210"); 
  
  lcd.backlight(); lcd.cursor(); lcd.noBlink();
  lcd.clear();

После этого почти ни одного затыка экрана при подаче питания! Из 20-30 подключений и отключений (пауза 3-5-10 (и больше) секунд в промежутке), зависает  1-2 раза примерно с этими двумя добавленными строчками. А вот если оставить вариант который я показал в начале текущего поста - экран виснет гораздо чаще. Не знаю в чем тут прикол, но эти 2 строки реально помогают... дурдом какой-то.  

Пойду и прикуплю еще один экранчик, может все же дело в нем... 

sadman41
Offline
Зарегистрирован: 19.10.2016

Возможно, что они просто дают небольшую задержку после инита. Влепите дилэй тогда уж... Хотя, конечно, ситуация нездоровая.

adrift_into_infinity
adrift_into_infinity аватар
Offline
Зарегистрирован: 02.10.2017

Я пробовал разные варианты делеев после инита: 1, 10, 100, 1000, 2000, 3000, 5000, 10000 мс. и, если даже 10 секундный делей пройдет, экран, в случае глюка (если он длится 12-15 сек), может еще повисеть какое-то время. Что же теперь делать? Сразу бахнуть 20 секундную задержку? Как-то уж слишком коряво получается... даже для меня.

Но вот стоило добавить эти две строчки (даже без делеев), как экрану "полегчало". Сначала думал что кажется, но вооружившись секундомером - только подтвердил свои мысли. С ними реально реже зависает. А если и подвисание случилось, то оно проходит за пару-тройку секунд. Вот такие вот "чудо строчки"... 

sadman41
Offline
Зарегистрирован: 19.10.2016

У меня идеи закончились. Могу ваш хелловорд на своем экране погонять: замена комплекта - это единственный способ отделить железячные проблемы от программных.

nik182
Offline
Зарегистрирован: 04.05.2015

У меня есть дисплей, который после lcd.clear() требует задержки 2 секунды. Если начать что то писать раньше, может случится затык или полное отключение отображения. Поэтому clear не пользую. Просто пишу две стороки пробелов для очистки. Так быстрее.

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

Мдя, конкретный бред. Хдето вы, батенька, согрешили. Чисто для очистки совести, пройти паялом и иголкой с лупой (тут от зрения зависит) по ногам ПЦФ-ки и экрана (с двух сторон). Хотя вряд ли поможет, зато в пайке скил повысите.)))) 

adrift_into_infinity
adrift_into_infinity аватар
Offline
Зарегистрирован: 02.10.2017

sadman41 пишет:

У меня идеи закончились. Могу ваш хелловорд на своем экране погонять: замена комплекта - это единственный способ отделить железячные проблемы от программных.

Было бы неплохо, спасибо! Вот код, который сейчас у меня крутится уже почти 13 часов (текущая версия кода):
 

//-----------------------------------

#include <Wire.h>

#include <RTClib.h>

#include <DHT.h>
#include <DHT_U.h>

#include <LiquidCrystal_I2C.h>

#include <i2cdetect.h>

//-----------------------------------

#define led_pin PD2 //D2
#define RTC_BATTERY A7
#define DHTPIN 9  //D9
#define DHTTYPE DHT22

//-----------------------------------

DS1307 RTC;
unsigned long RTCpreviousMillis = 0;
unsigned short RTCshowinterval = 1000;
DateTime boardStartupTime;

DHT dht(DHTPIN, DHTTYPE); // 50, 68
bool DHT22conversionInProgress, DHT22_isFailed, DHTonCOOLDOWN = 0;
unsigned long DHT22conversionStartTime, LastTimeDone = 0;
float h, t, hic = 0;

LiquidCrystal_I2C lcd(0x26, 16, 2);
unsigned char SecondLineStep = 1;
unsigned long prevHintSwitchTime = 0;
unsigned short HintSwitchTime = 1000, TimeToShow = 0;

//-----------------------------------

bool DEBUG = 0;

void setup()
{
  pinMode(led_pin, OUTPUT);
  pinMode(RTC_BATTERY, INPUT);

  Wire.begin();
  RTC.begin();
  dht.begin();

  boardStartupTime = RTC.now(); // Used to calc uptime

  if ( DEBUG ) {
    Serial.begin(2000000);

    // i2c scaner from example
    Serial.print("Scanning address range 0x03-0x77\n\n");
    i2cdetect();  // default range from 0x03 to 0x77
    delay(2000);
  }

  // if (1 == 1) use only once for RTC setup or for sync
  if (1 == 0) {
    RTC.adjust( DateTime( __DATE__, __TIME__ ) );
    DateTime now = RTC.now();
    //add ~x.0 sec as compensation of compile & upload time
    RTC.adjust( DateTime( now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second() + 9.0 ) );
  }

  if ( !RTC.isrunning() ) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    RTC.adjust( DateTime( __DATE__, __TIME__ ) );
  }

  // LCD //
  lcd.init();

  lcd.setCursor(0, 0); lcd.print("0123456789ABCDEF");
  lcd.setCursor(0, 1); lcd.print("FEDCBA9876543210");

  lcd.backlight(); lcd.cursor(); lcd.noBlink();
  lcd.clear();

  // Short blink to show that setup is finished
  digitalWrite(led_pin, HIGH); delay(500); digitalWrite(led_pin, LOW); delay(500);
}

//-----------------------------------

void loop()
{
  check_RTC();
  check_DHT22();
}

//-----------------------------------

void getUptime(void) {
  DateTime uptimeCheck = RTC.now();
  DateTime uptime( uptimeCheck.unixtime() - boardStartupTime.unixtime() );

  unsigned long uptimeSecs = uptime.unixtime(), uptimeMins = uptimeSecs / 60;
  unsigned int uptimeHours = uptimeMins / 60, uptimeDays = uptimeHours / 24;
  uptimeSecs -= uptimeMins * 60;
  uptimeMins -= uptimeHours * 60;
  uptimeHours -= uptimeDays * 24;

  lcd.setCursor(0, 1); lcd.print("                ");
  lcd.setCursor(0, 1); lcd.print( "UP: " + (String)uptimeDays + "D "
                                  + (String)uptimeHours + ":"
                                  + (String)uptimeMins + ":"
                                  + (String)uptimeSecs );
}

//-----------------------------------

void check_RTC(void) {
  unsigned long RTCcurrentMillis = millis();
  if ( RTCcurrentMillis - RTCpreviousMillis >= RTCshowinterval ) {
    RTCpreviousMillis = RTCcurrentMillis;

    float Vref = 4.99;  // measured with voltmeter
    float RTC_BATTERY_VOLTAGE = ( analogRead( RTC_BATTERY ) * Vref / 1024.0 );  // Output in Volts
    delay(50);

    DateTime now = RTC.now();

    if ( DEBUG ) {
      Serial.print( now.year(), DEC ); Serial.print('/');
      Serial.print( now.month(), DEC ); Serial.print('/');
      Serial.print( now.day(), DEC ); Serial.print(' ');

      Serial.print( now.hour(), DEC ); Serial.print(':');
      Serial.print( now.minute(), DEC ); Serial.print(':');
      Serial.print( now.second(), DEC ); Serial.print(" ");

      Serial.print("Voltage: "); Serial.print( RTC_BATTERY_VOLTAGE, 4 ); Serial.println(" V");
    }

    String RTC_VOLTAGE = String ( RTC_BATTERY_VOLTAGE, 2 );
    if ( DEBUG == true && RTC_VOLTAGE == false ) {
      Serial.println("PROBLEM WITH RTC_VOLTAGE STRING!");
    }

    String RTC_TIME = String( now.hour(), DEC ) + ":"
                      + String( now.minute(), DEC ) + ":"
                      + String( now.second(), DEC );
    if ( DEBUG == true && RTC_TIME == false ) {
      Serial.println("PROBLEM WITH RTC_TIME STRING!");
    }

    lcd.setCursor(0, 0); lcd.print("                ");
    lcd.setCursor(0, 0); lcd.print(RTC_TIME + " " + RTC_VOLTAGE + " V");
  }
}

//-----------------------------------

unsigned char read_dht22(void) {
  unsigned long DHT22currentTime = millis();
  if ( DHT22conversionInProgress == 0 ) {
    // 8000 ms as cooldown + 2000 for measure and conversion = new measurement every 10 sec.
    if ( DHT22currentTime - LastTimeDone > 8000 ) {
      dht.begin();
      DHT22conversionInProgress = 1;
      DHT22conversionStartTime = DHT22currentTime;
      return 2; // IN PROGRESS
    }
    else {
      return 3; // COOLDOWN
    }
  }
  else {
    if ( DHT22currentTime - DHT22conversionStartTime > 2000 ) {
      DHT22conversionInProgress = 0;
      h = dht.readHumidity();
      t = dht.readTemperature();  // Read temperature as Celsius (the default)

      // Check if any reads failed and exit early (to try again).
      if (isnan(h) || isnan(t)) {
        Serial.println("Failed to read from DHT sensor!");
        DHT22_isFailed = true;
        digitalWrite(led_pin, HIGH);
        hic = 0;
        return 0; // ERROR
      }

      // If we have reached here, then everyting is allright or failure fixed
      if (DHT22_isFailed == 1) {
        DHT22_isFailed = false;
        digitalWrite(led_pin, LOW);
        Serial.println("DHT22: Failure fixed!");
      }

      // Calculate "Heat Index"
      hic = dht.computeHeatIndex(t, h, false);  // Compute heat index in Celsius (isFahreheit = false)
    }
    else {
      return 2; // Still in progress
    }
    LastTimeDone = millis();
    return 1; // DONE
  }
}

//-----------------------------------

void check_DHT22(void) {
  unsigned char DHT22state = read_dht22();  // Get sensor state (ERROR || DONE || inPROGRESS || onCOOLDOWN || UNKNOWNERROR)

  // Redraw every TimeToShow (ms)
  unsigned long currentHintSwitchTime = millis();
  if ( ( currentHintSwitchTime - prevHintSwitchTime > TimeToShow ) && SecondLineStep == 1 ) {
    SecondLineStep = 2;
    prevHintSwitchTime = currentHintSwitchTime;
    TimeToShow = 3000;

    lcd.setCursor(0, 1); lcd.print("                ");
    lcd.setCursor(0, 1); lcd.print("HUM/TEMP/HIC    ");
  }
  else if ( ( currentHintSwitchTime - prevHintSwitchTime > TimeToShow ) && SecondLineStep == 2 ) {
    SecondLineStep = 3;
    prevHintSwitchTime = currentHintSwitchTime;
    TimeToShow = 4000;

    lcd.setCursor(0, 1); lcd.print("                ");
    lcd.setCursor(0, 1); lcd.print(String(h, 1) + '/' + String(t, 1) + '/' + String(hic, 1));  // Shorten to one-tenth, otherwise the string won't fit
  }
  else if ( ( currentHintSwitchTime - prevHintSwitchTime > TimeToShow ) && SecondLineStep == 3 ) {
    SecondLineStep = 1;
    prevHintSwitchTime = currentHintSwitchTime;
    TimeToShow = 3000;
    getUptime();
  }
  else {
    // Not a time to redraw
  }

  // Conversion done?
  unsigned long DHT22currentMillis = millis();
  if ( DHT22currentMillis - DHT22conversionStartTime > 2000 ) {
    switch ( DHT22state )
    {
      case 0 :  // ERROR
        if ( DEBUG ) {
          Serial.println("DHT22: ERROR!");
        }
        break;

      case 1 :  // DONE
        if ( DEBUG ) {
          DHTonCOOLDOWN = false;

          Serial.print("Humidity: "); Serial.print(h); Serial.println(" % ");
          Serial.print("Temperature: "); Serial.print(t); Serial.println(" C");
          Serial.print("Heat Index: "); Serial.println(hic);
        }
        break;

      case 2 :  // IN PROGRESS
        if ( DEBUG ) {
          Serial.println("DHT22: Conversion IN PROGRESS...");
        }
        break;

      case 3 :  // ON COOLDOWN
        if ( DEBUG ) {
          if ( DHTonCOOLDOWN == false ) {
            DHTonCOOLDOWN = true; // For debug and to not to spam into console

            Serial.println("DHT22: On COOLDOWN.");
          }
        }
        break;

      default : // UNKNOWN ERROR
        if ( DEBUG ) {
          Serial.println("DHT22: Strange... We should NOT have got here");
        }
        break;
    }
  }
}

//-----------------------------------

P.S. заказал экранчик. 

 

nik182 пишет:
У меня есть дисплей, который после lcd.clear() требует задержки 2 секунды. Если начать что то писать раньше, может случится затык или полное отключение отображения. Поэтому clear не пользую. Просто пишу две стороки пробелов для очистки. Так быстрее.

Интересно. А моему экранчику все равно, есть ли задержка до/после/ и до и после lcd.clear(). "Магия", не иначе =)

 

bwn пишет:

Мдя, конкретный бред. Хдето вы, батенька, согрешили. Чисто для очистки совести, пройти паялом и иголкой с лупой (тут от зрения зависит) по ногам ПЦФ-ки и экрана (с двух сторон). Хотя вряд ли поможет, зато в пайке скил повысите.)))) 

Дык, все мы грешные =) Но, судя по всему, я как-то где-то "особенно" согрешил =Р

На счет пройтись паяльником - это для того, что бы убедиться, что нормально ли они припаяли ноги микросхемы? И, пардон за глупый вопрос, но иголка то тут зачем нужна?

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

adrift_into_infinity пишет:

На счет пройтись паяльником - это для того, что бы убедиться, что нормально ли они припаяли ноги микросхемы? И, пардон за глупый вопрос, но иголка то тут зачем нужна?

Истинно (хотя думаю не ваш случай). А иголка, у меня с возрастом руки коротковаты стали, сопельки сразу не увижу, вот приходится извращатся.)))))

sadman41
Offline
Зарегистрирован: 19.10.2016

adrift_into_infinity пишет:

Было бы неплохо, спасибо! Вот код, который сейчас у меня крутится уже почти 13 часов (текущая версия кода):

Конечно я не знаю, откуда вы библиотеки брали, у меня таких нет и я накачал с гугола. Подключил только один дисплей без RTC и DHT.

Затыков на старте я не вижу (несколько раз ребутил по разному) и с двумя строчами и с одной. А вот непонятная ерунда один раз проскочила. Но она быстро была запечатана цифрами. Однако, судя по коду, это случилось в районе:

    lcd.setCursor(0, 0); lcd.print("                ");
    lcd.setCursor(0, 0); lcd.print(RTC_TIME + " " + RTC_VOLTAGE + " V");

Это была пустая строка, оканчивающаяся неизвестным мне знаком (но я видел его менее долей секунды), потом 'V'. Т.е. можно предположить, что проблема в RTC_TIME & RTC_VOLTAGE (часы у меня не подключены, а у вас, может и отваливаются вовсе).

Вообще мне фрагмент предваряющего кода кажется весьма странным (хотя я в стрингах не особо разбираюсь): 

    String RTC_VOLTAGE = String ( RTC_BATTERY_VOLTAGE, 2 );
    if ( DEBUG == true && RTC_VOLTAGE == false ) {
      Serial.println("PROBLEM WITH RTC_VOLTAGE STRING!");
    }

Насколько я понял, String() возвращает адрес в памяти. В этом случае непонятно, когда вы предполагаете увидеть "PROBLEM WITH RTC_VOLTAGE STRING!" - когда адрес будет равен 0x00? Но если так, то зачем вы засылаете на LCD область памяти в любом случае - и когда есть проблема и когда нет.

Будь я на вашем месте - я бы начал с простого: повыкидывал к чертям из кода всю остальную перефирию и куски, не относящийся к LCD. Пусть прямо в сетапе одну строку печатает, а в лупе ничего не делает. После этого бы решал - проблема в дисплее или, к примеру, в часах которые тупят.