Модуль 4 LED на драйвер чипе ТМ1637

Romul
Offline
Зарегистрирован: 03.03.2014

Здравствуйте.

Имеется такой индикатор.

Подключаю к ARDUINO  - всё вроде работает. При работе использую библиотеку: http://yadi.sk/d/qBMFhwjl8khMh.

#include "TM1637.h"
#include <Arduino.h>
static int8_t TubeTab[] = {0x3f,0x06,0x5b,0x4f,
                           0x66,0x6d,0x7d,0x07,
                           0x7f,0x6f,0x77,0x7c,
                           0x39,0x5e,0x79,0x71};//0~9,A,b,C,d,E,F                        
TM1637::TM1637(uint8_t Clk, uint8_t Data)
{
  Clkpin = Clk;
  Datapin = Data;
  pinMode(Clkpin,OUTPUT);
  pinMode(Datapin,OUTPUT);
}

void TM1637::init(void)
{
  clearDisplay();
}

void TM1637::writeByte(int8_t wr_data)
{
  uint8_t i,count1;   
  for(i=0;i<8;i++)        //sent 8bit data
  {
    digitalWrite(Clkpin,LOW);      
    if(wr_data & 0x01)digitalWrite(Datapin,HIGH);//LSB first
    else digitalWrite(Datapin,LOW);
    wr_data >>= 1;      
    digitalWrite(Clkpin,HIGH);
      
  }  
  digitalWrite(Clkpin,LOW); //wait for the ACK
  digitalWrite(Datapin,HIGH);
  digitalWrite(Clkpin,HIGH);     
  pinMode(Datapin,INPUT);
  while(digitalRead(Datapin))    
  { 
    count1 +=1;
    if(count1 == 200)//
    {
     pinMode(Datapin,OUTPUT);
     digitalWrite(Datapin,LOW);
     count1 =0;
    }
    pinMode(Datapin,INPUT);
  }
  pinMode(Datapin,OUTPUT);
  
}
//send start signal to TM1637
void TM1637::start(void)
{
  digitalWrite(Clkpin,HIGH);//send start signal to TM1637
  digitalWrite(Datapin,HIGH); 
  digitalWrite(Datapin,LOW); 
  digitalWrite(Clkpin,LOW); 
} 
//End of transmission
void TM1637::stop(void)
{
  digitalWrite(Clkpin,LOW);
  digitalWrite(Datapin,LOW);
  digitalWrite(Clkpin,HIGH);
  digitalWrite(Datapin,HIGH); 
}
//display function.Write to full-screen.
void TM1637::display(int8_t DispData[])
{
  int8_t SegData[4];
  uint8_t i;
  for(i = 0;i < 4;i ++)
  {
    SegData[i] = DispData[i];
  }
  coding(SegData);
  start();          //start signal sent to TM1637 from MCU
  writeByte(ADDR_AUTO);//
  stop();           //
  start();          //
  writeByte(Cmd_SetAddr);//
  for(i=0;i < 4;i ++)
  {
    writeByte(SegData[i]);        //
  }
  stop();           //
  start();          //
  writeByte(Cmd_DispCtrl);//
  stop();           //
}
//******************************************
void TM1637::display(uint8_t BitAddr,int8_t DispData)
{
  int8_t SegData;
  SegData = coding(DispData);
  start();          //start signal sent to TM1637 from MCU
  writeByte(ADDR_FIXED);//
  stop();           //
  start();          //
  writeByte(BitAddr|0xc0);//
  writeByte(SegData);//
  stop();            //
  start();          //
  writeByte(Cmd_DispCtrl);//
  stop();           //
}

void TM1637::clearDisplay(void)
{
  display(0x00,0x7f);
  display(0x01,0x7f);
  display(0x02,0x7f);
  display(0x03,0x7f);  
}
//To take effect the next time it displays.
void TM1637::set(uint8_t brightness,uint8_t SetData,uint8_t SetAddr)
{
  Cmd_SetData = SetData;
  Cmd_SetAddr = SetAddr;
  Cmd_DispCtrl = 0x88 + brightness;//Set the brightness and it takes effect the next time it displays.
}

//Whether to light the clock point ":".
//To take effect the next time it displays.
void TM1637::point(boolean PointFlag)
{
  _PointFlag = PointFlag;
}
void TM1637::coding(int8_t DispData[])
{
  uint8_t PointData;
  if(_PointFlag == POINT_ON)PointData = 0x80;
  else PointData = 0; 
  for(uint8_t i = 0;i < 4;i ++)
  {
    if(DispData[i] == 0x7f)DispData[i] = 0x00;
    else DispData[i] = TubeTab[DispData[i]] + PointData;
  }
}
int8_t TM1637::coding(int8_t DispData)
{
  uint8_t PointData;
  if(_PointFlag == POINT_ON)PointData = 0x80;
  else PointData = 0; 
  if(DispData == 0x7f) DispData = 0x00 + PointData;//The bit digital tube off
  else DispData = TubeTab[DispData] + PointData;
  return DispData;
} 

Как я понимаю при помощи данной библиотеки можно подключить только один индикатор. Посмотрел альтернативные решения – тоже одно устройство.

Вопрос, есть или библиотека для работы с несколькими индикаторами?

Romul
Offline
Зарегистрирован: 03.03.2014

Похоже я тормознул - всё можно, нужно пробовать.

ImaSoft
ImaSoft аватар
Offline
Зарегистрирован: 22.09.2015

Прикольно, перерыл весь инет на предмет бага в библиотеке TM1637.cpp которая может вешать контроллер, и не где этого не нашел, такое впечатление что только у меня вылезло это! В общем от лирики к делу: валялся у меня контроллер ATiny2313A решил на нем сделать часы(так поиграться) столкнулся с проблемой нехватки памяти в МК, прикупил 4313 вроде пока хватает памяти(4к), но вот была бида что МК, хаотично постоянно зависал, уже думал что бракованный МК купил, да вот оказалось что нет, потратив 2 дня на поиски проблемы пришел к выводу что 2313 тоже иногда виснит но реже, начал копать и выяснил что вешает контроллер вызов tm1637.display(TimeDisp), начал копаться в библиотеке и нашел баг,

отрывок кода(оригинал):

void TM1637::writeByte(int8_t wr_data)
{
  uint8_t i,count1;   
  for(i=0;i<8;i++)        //sent 8bit data
  {
    digitalWrite(Clkpin,LOW);      
    if(wr_data & 0x01)digitalWrite(Datapin,HIGH);//LSB first
    else digitalWrite(Datapin,LOW);
    wr_data >>= 1;      
    digitalWrite(Clkpin,HIGH);
      
  }  
  digitalWrite(Clkpin,LOW); //wait for the ACK
  digitalWrite(Datapin,HIGH);
  digitalWrite(Clkpin,HIGH);     
  pinMode(Datapin,INPUT);
  while(digitalRead(Datapin))    
  { 
    count1 +=1;
    if(count1 == 200)//
    {
     pinMode(Datapin,OUTPUT);
     digitalWrite(Datapin,LOW);
     count1 =0;
     }
    pinMode(Datapin,INPUT);
  }
  pinMode(Datapin,OUTPUT);
  
}

отрывок кода(Исправленный): 

void TM1637::writeByte(int8_t wr_data)
{
  uint8_t i,count1;   
  for(i=0;i<8;i++)        //sent 8bit data
  {
    digitalWrite(Clkpin,LOW);      
    if(wr_data & 0x01)digitalWrite(Datapin,HIGH);//LSB first
    else digitalWrite(Datapin,LOW);
    wr_data >>= 1;      
    digitalWrite(Clkpin,HIGH);
      
  }  
  digitalWrite(Clkpin,LOW); //wait for the ACK
  digitalWrite(Datapin,HIGH);
  digitalWrite(Clkpin,HIGH);     
  pinMode(Datapin,INPUT);
  while(digitalRead(Datapin))    
  { 
    count1 +=1;
    if(count1 == 200)//
    {
     pinMode(Datapin,OUTPUT);
     digitalWrite(Datapin,LOW);
     count1 =0;
     break;
    }
    pinMode(Datapin,INPUT);
  }
  pinMode(Datapin,OUTPUT);
  
}

Что характерно на UNO не чего не висло, а вот на других МК проявлялось, думаю данная информация будет полезна не только мне, если кто то захочет поиграться с дисплеями часов на основе TM1637

dhog1
Offline
Зарегистрирован: 01.03.2016

Эта библиотека - один большой баг, она написана без понимания работы линий с подтяжкой. Зависание неизбежно при вхождении в цикл while. Войти в него можно, пропустив ACK от TM1637. Выйти из него неможно (почти по-польски).

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

Krendelyok
Offline
Зарегистрирован: 05.10.2016

ImaSoft пишет:
Что характерно на UNO не чего не висло, а вот на других МК проявлялось, думаю данная информация будет полезна не только мне, если кто то захочет поиграться с дисплеями часов на основе TM1637

Просто в UNO сигнал ACK стабильно приходил. А на дургом контроллере - не всегда) Наверное, тайминги надо подправить. А отсутствие аварийного выхода из цикла - это, конечно, беда.

uv3afl
Offline
Зарегистрирован: 09.12.2016

ImaSoft пишет:

Прикольно, перерыл весь инет на предмет бага в библиотеке TM1637.cpp которая может вешать контроллер, и не где этого не нашел, такое впечатление что только у меня вылезло это!

Ай, спасибо тебе, добрый человек!

Очень похоже на мою ситуацию: часы, которые прекрасно отпахали все лето у меня на подоконнике на Леонарде в виде клубка проводов, после того, как я перевоплотил их на Про-Микро и без клубка проводов стали подвисать ежедневно в районе 8 утра. Я башку чуть не сломал - сначала грешил на модуль реал-тайм на 3231 - думал там какие-нибудь будильники срабатывают, потом на Про-Микро... Стал осциллографом тыкаться - вроде что-то есть на выводах от МК к индикатору - значит, думаю, не виснет контроллер. А на код как-то и не думал совсем: вроде он работал, и работал стабильно. Уже подумал, что дело в индикаторе, и вот набрел на этот тред и это сообщение. Очень похоже все получается: когда индикация "замерзает" осциллом видно, что на SCK высокий уровень постоянный, а на Дате коротенькие инверсные импульсы - пару десятков микросекунд и с периодом порядка 4мс. Учитывая, что и Дата и ЦЛК подтянуты к плюсу, прям напоминает результат вот этого:

  //begin TM1637.cpp fragment

  digitalWrite(Datapin,HIGH);
  digitalWrite(Clkpin,HIGH);
  pinMode(Datapin,INPUT);
  while(digitalRead(Datapin))
  {
    count1 +=1;
    if(count1 == 200)
    {
     pinMode(Datapin,OUTPUT);
     digitalWrite(Datapin,LOW);
     count1 =0;
    } 
    pinMode(Datapin,INPUT);
  }

//end TM1637.cpp fragment

Уже залил было поправленный код с брейком, как потом обнаружил, что та библиотечка, которой мы пользуемся (DigitalTube ?) образца 2012-го года - это уже история и довольно дремучая. Есть гораздо свежее.

Вот ссыль:

https://github.com/Seeed-Studio/Seeed_Grove_4Digital_Display_g

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

uv3afl
Offline
Зарегистрирован: 09.12.2016

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

Если вдруг что-то вылезет позже, дам знать.

Gogi
Offline
Зарегистрирован: 17.09.2017

uv3afl пишет:

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

Если вдруг что-то вылезет позже, дам знать.

Спасибо. У меня такая же ситуация с TM1637 была. Тормозила бегущая строка вместе с ним в 8:00 и далее. Поменял библиотеку и всё работает(пока работает) думаю что будет нормально. Я не программист-поэтому ещё раз большое спасибо-иначе я бы не разобрался бы.

AntonHT
Offline
Зарегистрирован: 29.12.2017

Там, в этой библиотеке есть еще один прикол (TM1637.cpp). Когда выводите данные на дисплей, они дублируются в серийный монитор. По началу вообще понять не мог почему идет задвоение.

 else
  {
	for( ;i > 1; i --)
	{
	  if(Decimal > -100)Decimal *= 10;
	  else break;
	}
	temp = (int)Decimal;
	if((temp - Decimal)>0.5)temp--;
  }
  DecPoint = i;
  
  Serial.println(Decimal);   <--------- УДАЛИТЬ ЭТУ СТРОЧКУ !!!!!!!
  BlankingFlag = 0;
  display(temp);
   
}

void TM1637::display(int16_t Decimal)

Встречается не во всех библиотеках, у меня было. Может кому поможет.

kraiv
Offline
Зарегистрирован: 02.12.2015
ImaSoft пишет:

 

Прикольно, перерыл весь инет на предмет бага в библиотеке TM1637.cpp которая может вешать контроллер, и не где этого не нашел, такое впечатление что только у меня вылезло это!

 

Благодарствую, спас. Всё висло насмерть при передергивании питания, только break; и помог. Теперь всё нормально. Другие библтотеки не помогали.

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

ImaSoft пишет:

Прикольно, перерыл весь инет на предмет бага в библиотеке TM1637.cpp которая может вешать контроллер, и не где этого не нашел, такое впечатление что только у меня вылезло это! 

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