Индикатор TM1637. Как убрать число 85?

NikitaS
Offline
Зарегистрирован: 22.10.2016

Доброго времени суток! При помощи Attiny85 сделал термометр, чтобы показывал уличную температуру. Датчик DS18B20, индикатор ТМ1637. Код брал из Интернета. Залил в Аттини85, все работает, прекрасно. За исключением одной маленькой неприятности: как только подается напряжение на весь термометр, показывается цифра 85, и только после секундной задержки появляется собственно температура. Просмотрел код и библиотеку, но ничего не нашел. Никакого оператора display, который бы выводил 85. Помогите, пожалуйста, убрать это число, чтобы температура выводилась без задержек.

Программа в Ардуино IDE:

#include <TM1637Display.h>
#include <OneWire.h>

//------------------------------------- Дополнительные установки --------------------------
int inTSensorConnectedPin = 0;
OneWire ds1(inTSensorConnectedPin);

int pinCLK = 2;
int pinDIO = 3;
TM1637Display display(pinCLK, pinDIO);

//------------------------------------- SETUP ---------------------------------------------

void setup()
{
}

//----------------------------------------- LOOP ------------------------------------------

void loop() {
display.setBrightness(0x0f);
bool DisplayNulls = false;

float temp = getInsideTemp();

display.showNumberDec(temp, DisplayNulls);
delay(500);

}
float getInsideTemp()
{
byte data[12];
byte addr[8];
if ( !ds1.search(addr)) {
//error NO more addrss
ds1.reset_search();
return -1001;
}
if ( OneWire::crc8( addr, 7) != addr[7]) {
//error CRC is not valid!
return -1002;
}
if ( addr[0] != 0x10 && addr[0] != 0x28) {
//error NOT recognizd!
return -1003;
}
ds1.reset();
ds1.select(addr);
ds1.write(0x44,1);
byte present = ds1.reset();
ds1.select(addr);
ds1.write(0xBE);
for (int i = 0; i < 9; i++) {
data[i] = ds1.read();
}
ds1.reset_search();
byte MSB = data[1];
byte LSB = data[0];
float TRead = ((MSB<<8) | LSB);
float Temperature = TRead / 16;
return Temperature;
}

Библиотека TM1637Display.h:



#ifndef __TM1637DISPLAY__
#define __TM1637DISPLAY__

#include <inttypes.h>

#define SEG_A   0b00000001
#define SEG_B   0b00000010
#define SEG_C   0b00000100
#define SEG_D   0b00001000
#define SEG_E   0b00010000
#define SEG_F   0b00100000
#define SEG_G   0b01000000

#define DEFAULT_BIT_DELAY  100

class TM1637Display {

public:

  TM1637Display(uint8_t pinClk, uint8_t pinDIO, unsigned int bitDelay = DEFAULT_BIT_DELAY);

 
  void setBrightness(uint8_t brightness, bool on = true);

  void setSegments(const uint8_t segments[], uint8_t length = 4, uint8_t pos = 0);

  //! Clear the display
  void clear();

  
  void showNumberDec(int num, bool leading_zero = false, uint8_t length = 4, uint8_t pos = 0);

  
  void showNumberDecEx(int num, uint8_t dots = 0, bool leading_zero = false, uint8_t length = 4, uint8_t pos = 0);

  void showNumberHexEx(uint16_t num, uint8_t dots = 0, bool leading_zero = false, uint8_t length = 4, uint8_t pos = 0);

 
  uint8_t encodeDigit(uint8_t digit);

protected:
   void bitDelay();

   void start();

   void stop();

   bool writeByte(uint8_t b);

   void showDots(uint8_t dots, uint8_t* digits);
   
   void showNumberBaseEx(int8_t base, uint16_t num, uint8_t dots = 0, bool leading_zero = false, uint8_t length = 4, uint8_t pos = 0);


private:
	uint8_t m_pinClk;
	uint8_t m_pinDIO;
	uint8_t m_brightness;
	unsigned int m_bitDelay;
};

#endif // __TM1637DISPLAY__

Файл TM1637Display.cpp, который был в папке ТМ1637. Выкладываю на всякий случай, может, нужен.:


//  Author: avishorp@gmail.com
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

extern "C" {
  #include <stdlib.h>
  #include <string.h>
  #include <inttypes.h>
}

#include <TM1637Display.h>
#include <Arduino.h>

#define TM1637_I2C_COMM1    0x40
#define TM1637_I2C_COMM2    0xC0
#define TM1637_I2C_COMM3    0x80

//
//      A
//     ---
//  F |   | B
//     -G-
//  E |   | C
//     ---
//      D
const uint8_t digitToSegment[] = {
 // XGFEDCBA
  0b00111111,    // 0
  0b00000110,    // 1
  0b01011011,    // 2
  0b01001111,    // 3
  0b01100110,    // 4
  0b01101101,    // 5
  0b01111101,    // 6
  0b00000111,    // 7
  0b01111111,    // 8
  0b01101111,    // 9
  0b01110111,    // A
  0b01111100,    // b
  0b00111001,    // C
  0b01011110,    // d
  0b01111001,    // E
  0b01110001     // F
  };

static const uint8_t minusSegments = 0b01000000;

TM1637Display::TM1637Display(uint8_t pinClk, uint8_t pinDIO, unsigned int bitDelay)
{
	// Copy the pin numbers
	m_pinClk = pinClk;
	m_pinDIO = pinDIO;
	m_bitDelay = bitDelay;

	// Set the pin direction and default value.
	// Both pins are set as inputs, allowing the pull-up resistors to pull them up
    pinMode(m_pinClk, INPUT);
    pinMode(m_pinDIO,INPUT);
	digitalWrite(m_pinClk, LOW);
	digitalWrite(m_pinDIO, LOW);
}

void TM1637Display::setBrightness(uint8_t brightness, bool on)
{
	m_brightness = (brightness & 0x7) | (on? 0x08 : 0x00);
}

void TM1637Display::setSegments(const uint8_t segments[], uint8_t length, uint8_t pos)
{
    // Write COMM1
	start();
	writeByte(TM1637_I2C_COMM1);
	stop();

	// Write COMM2 + first digit address
	start();
	writeByte(TM1637_I2C_COMM2 + (pos & 0x03));

	// Write the data bytes
	for (uint8_t k=0; k < length; k++)
	  writeByte(segments[k]);

	stop();

	// Write COMM3 + brightness
	start();
	writeByte(TM1637_I2C_COMM3 + (m_brightness & 0x0f));
	stop();
}

void TM1637Display::clear()
{
    uint8_t data[] = { 0, 0, 0, 0 };
	setSegments(data);
}

void TM1637Display::showNumberDec(int num, bool leading_zero, uint8_t length, uint8_t pos)
{
  showNumberDecEx(num, 0, leading_zero, length, pos);
}

void TM1637Display::showNumberDecEx(int num, uint8_t dots, bool leading_zero,
                                    uint8_t length, uint8_t pos)
{
  showNumberBaseEx(num < 0? -10 : 10, num < 0? -num : num, dots, leading_zero, length, pos);
}

void TM1637Display::showNumberHexEx(uint16_t num, uint8_t dots, bool leading_zero,
                                    uint8_t length, uint8_t pos)
{
  showNumberBaseEx(16, num, dots, leading_zero, length, pos);
}

void TM1637Display::showNumberBaseEx(int8_t base, uint16_t num, uint8_t dots, bool leading_zero,
                                    uint8_t length, uint8_t pos)
{
    bool negative = false;
	if (base < 0) {
	    base = -base;
		negative = true;
	}


    uint8_t digits[4];

	if (num == 0 && !leading_zero) {
		// Singular case - take care separately
		for(uint8_t i = 0; i < (length-1); i++)
			digits[i] = 0;
		digits[length-1] = encodeDigit(0);
	}
	else {
		//uint8_t i = length-1;
		//if (negative) {
		//	// Negative number, show the minus sign
		//    digits[i] = minusSegments;
		//	i--;
		//}
		
		for(int i = length-1; i >= 0; --i)
		{
		    uint8_t digit = num % base;
			
			if (digit == 0 && num == 0 && leading_zero == false)
			    // Leading zero is blank
				digits[i] = 0;
			else
			    digits[i] = encodeDigit(digit);
				
			if (digit == 0 && num == 0 && negative) {
			    digits[i] = minusSegments;
				negative = false;
			}

			num /= base;
		}

		if(dots != 0)
		{
			showDots(dots, digits);
		}
    }
    setSegments(digits, length, pos);
}

void TM1637Display::bitDelay()
{
	delayMicroseconds(m_bitDelay);
}

void TM1637Display::start()
{
  pinMode(m_pinDIO, OUTPUT);
  bitDelay();
}

void TM1637Display::stop()
{
	pinMode(m_pinDIO, OUTPUT);
	bitDelay();
	pinMode(m_pinClk, INPUT);
	bitDelay();
	pinMode(m_pinDIO, INPUT);
	bitDelay();
}

bool TM1637Display::writeByte(uint8_t b)
{
  uint8_t data = b;

  // 8 Data Bits
  for(uint8_t i = 0; i < 8; i++) {
    // CLK low
    pinMode(m_pinClk, OUTPUT);
    bitDelay();

	// Set data bit
    if (data & 0x01)
      pinMode(m_pinDIO, INPUT);
    else
      pinMode(m_pinDIO, OUTPUT);

    bitDelay();

	// CLK high
    pinMode(m_pinClk, INPUT);
    bitDelay();
    data = data >> 1;
  }

  // Wait for acknowledge
  // CLK to zero
  pinMode(m_pinClk, OUTPUT);
  pinMode(m_pinDIO, INPUT);
  bitDelay();

  // CLK to high
  pinMode(m_pinClk, INPUT);
  bitDelay();
  uint8_t ack = digitalRead(m_pinDIO);
  if (ack == 0)
    pinMode(m_pinDIO, OUTPUT);


  bitDelay();
  pinMode(m_pinClk, OUTPUT);
  bitDelay();

  return ack;
}

void TM1637Display::showDots(uint8_t dots, uint8_t* digits)
{
    for(int i = 0; i < 4; ++i)
    {
        digits[i] |= (dots & 0x80);
        dots <<= 1;
    }
}

uint8_t TM1637Display::encodeDigit(uint8_t digit)
{
	return digitToSegment[digit & 0x0f];
}

 

strarbit
Offline
Зарегистрирован: 12.06.2016

Значение 85 это норма от сенсор DS18X20 если вы сенсор не просили  начать температурное измерение.

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

NikitaS пишет:

Помогите, пожалуйста, убрать это число, чтобы температура выводилась без задержек.

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

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

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

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Первое выдаваемое значение 85 служит для
того чтобы сообщить что он жив.

alex_r61
Offline
Зарегистрирован: 20.06.2012

В setup запускаете первое преобразование, без считывания результата, делаете задержку на преобразование и в loop уже будет нормально работать.

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

b707 пишет:

NikitaS пишет:

Помогите, пожалуйста, убрать это число, чтобы температура выводилась без задержек.

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

Выйдет, если не пользоваться какой. В шину достаточно раз в N секунд давать команду на запуск конвертации (при этом пропуская адреса ROM, т.е. для всех датчиков на линии), и уже когда хочется, в любой момент времени - читать с конкретного датчика. Дебильная задержка в 0.8 секунд в дебильной библиотеке - вообще не нужна, т.к. датчик всегда отдаёт значение температуры, а вот изменяется оно во внутренней памяти датчика - только после окончания конвертации, которая (конвертация) занимает некое время, описанное в даташите на каждую разрядность измерений.

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

DIYMan пишет:

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

ты какой-то резкий сегодня. Лезешь в спор, где его нет.

Речь о том, что СРАЗУ ПОСЛЕ ВКЛЮЧЕНИЯ значение температуры с датчика не получить - что с "дебильной либой", что без нее. Один раз конверсию подождать всяко придется. Дефолтное время - 750мс.

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

b707 пишет:

ты какой-то резкий сегодня. 

Понедельник :)

b707 пишет:

Лезешь в спор, где его нет.

Не, не спорил, просто на всякий.

b707 пишет:

Речь о том, что СРАЗУ ПОСЛЕ ВКЛЮЧЕНИЯ значение температуры с датчика не получить - что с "дебильной либой", что без нее. Один раз конверсию подождать всяко придется. Дефолтное время - 750мс.

Ну не согласен в терминах. Сразу после включения - можно получить температуру. Ждать - не надо ничего. А вот вопрос - будет ли правильной полученная температура - это совершенно другое. Правильный ответ такой: температура будет правильной после окончания конвертации, которая произойдёт через N времени после команды запуска конвертации. Ждать - не надо, надо просто при старте запустить конвертацию, а начать выводить информацию - после её завершения. И - никаких ожиданий, пускай всё работает параллельно. Щас псевдокод накидаю.

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

Вот псевдокод без ждать:

#define CONVERSION_TIME 750
uint32_t timer = 0;
void setup()
{
	startConversion();
	timer = millis();
}

void loop()
{
	if(millis() - timer > CONVERSION_TIME)
	{
		Temperature t = getTemp();
		displayTemp(t);
		startConversion();
		timer = millis();
	}
}

Нигде не жду, никого не жду :)

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

Сам запуск конвертации:

void startConversion()
{
	OneWire ow(pin);
	ow.write(0xCC); // пофиг на адреса (SKIP ROM)
	ow.write(0x44); // запускаем преобразование

	ow.reset();
}

Уже почти весь код написан :)

NikitaS
Offline
Зарегистрирован: 22.10.2016

b707 пишет:

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

Хорошо, можно подождать 0.8 секунды. Хотелось бы только, чтобы цифра 85 не мозолила глаза каждый раз, когда буду узнавать температуру на улице.

 

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

NikitaS пишет:

Хорошо, можно подождать 0.8 секунды. Хотелось бы только, чтобы цифра 85 не мозолила глаза каждый раз, когда буду узнавать температуру на улице.

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

NikitaS
Offline
Зарегистрирован: 22.10.2016

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

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

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

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

NikitaS пишет:

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

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

Согласен, это наилучшее решение.

Если вы поняли это так, что надо отлавливать значение 85 и не выводить его на дисплей - вы поняли неправильно. Хотя это тоже вариант :) если вы измеряете температуру таких обьектов, у которых 85 гр С маловероятно :)

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Ну прочитайте-ж, наконец, документацию  !!!!!!!!!!!!!!!!!

POWER-UP STATE означает " состояние после включения питания"

Он ВСЕГДА после подачи питания в первые два регистра САМ  прописывает туда 50h и 05h  ( 85 градусов )
И 85 там будет лежать до первого запущенного вами преобразования.

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

NikitaS пишет:

Согласен, это наилучшее решение. Только не пойму, в силу малого опыта в программировании, куда вписать код (а может, убрать).

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

NikitaS
Offline
Зарегистрирован: 22.10.2016

b707 пишет:

Если вы поняли это так, что надо отлавливать значение 85 и не выводить его на дисплей - вы поняли неправильно. Хотя это тоже вариант :) если вы измеряете температуру таких обьектов, у которых 85 гр С маловероятно :)

Да, именно так, максимум 40 гр. Эти цифры мне нужны были только, чтобы показать, что датчик жив. Если выводит температуру, значит, датчик работает. 85 это уже избыточная информация. А если датчик перестанет показывать температуру, можно тогда раскомментировать строчки, и посмотреть, что за код ошибки датчик показывает. Так что от цифры 85 можно избавляться. Только вот не знаю, как. Просмотрел код TM1637Display.cpp еще раз. Там есть строки

   // Write the data bytes

 for (uint8_t k=0; k < length; k++)
 writeByte(segments[k]);

Может, команда writeByte и выводит цифры на дисплей?

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

NikitaS пишет:

Может, команда writeByte и выводит цифры на дисплей?

Так Вы что, ни буквы в этом коде не понимаете?

NikitaS
Offline
Зарегистрирован: 22.10.2016

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

Так Вы что, ни буквы в этом коде не понимаете?

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

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

Понятно.