Несколько TM1637. Общая процедура вывода информации

2611sergey
Offline
Зарегистрирован: 17.01.2019

Всем доброго!

Вопрос навеян этой темой.

В устройстве будет 3 индикатора TM1637. В топике есть обычный вариант применения:

01 #include "TM1637.h" // Подключаем библиотеку
02 #define CLK_1 8 // первый семисегмент
03 #define DIO_1 9 //
04 #define CLK_2 10 // второй семисегмент
05 #define DIO_2 11 //
06 TM1637 disp_1(CLK_1, DIO_1);
07 TM1637 disp_2(CLK_2, DIO_2);
08 void setup() {
09   disp_1.set(7);
10   //disp_1.init(D4056A);
11   disp_2.set(7);
12   //disp_2.init(D4056A);
13   }
14  
15 void loop()
16   {
17   disp_1.display(1234);
18   delay(2000);
19   disp_2.display(5678);
20   delay(2000);
21   }

Хотелось бы написать одну процедуру вывода на индикатор, где аргументом будет этот самый индикатор.

Подскажите, плс: как передать нужный дисплей в процедуру вывода (какой это тип данных)?

Как пример:

15 void out_disp(disp)
16   {
17   disp.display(1234);
18   delay(2000);
19   disp.display(5678);
20   delay(2000);
21   }

Возможно такое?

Спасибо.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Возможно. Надо в функцию передавать указатель на класс. Примерно так:

void out_disp(TM1637 * disp)
{
	  disp->display(1234);
	  delay(2000);
	  disp->display(5678);
	  delay(2000);
}

//Пишем в первый дисплей
out_disp(&disp_1);

//Пишем во второй дисплей
out_disp(&disp_2);

 

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

asam пишет:

void out_disp(TM1637 * disp)

{
	  disp->display(1234);
	  delay(2000);
	  disp->display(5678);
	  delay(2000);
}

если уж ты проверку на NULL не делаешь, то передавать надо ссылку

void out_disp(const TM1637  &disp)
{
	  disp.display(1234);
	  delay(2000);
	  disp.display(5678);
	  delay(2000);
}

out_disp(disp1);
out_disp(disp2);

 

2611sergey
Offline
Зарегистрирован: 17.01.2019
Если:
void out_disp(const TM1637  &disp)
то ошибка:
E:\Arduino\libraries\TM1637/TM1637.h:73:8: note:   in call to 'void TM1637::display(int16_t)'
   void display(int16_t Decimal);
        ^
Посмотрел TM1637.h, там:
 
#define D4036B 0
#define D4056A 1
class TM1637
 { 
  public:
uint8_t Cmd_SetData;
uint8_t Cmd_SetAddr;
uint8_t Cmd_DispCtrl;
boolean _PointFlag;
//_PointFlag=1:the clock point on
uint8_t _DispType;
TM1637(uint8_t, uint8_t);
void init(uint8_t = D4036B);
void writeByte(int8_t wr_data);//write 8bit data to tm1637
void start(void);//send start bits
void stop(void); //send stop bits
void display(int8_t DispData[]);
void display(uint8_t BitAddr,int8_t DispData);
void display(double Decimal);
void display(int16_t Decimal);
void clearDisplay(void);
void set(uint8_t = BRIGHT_TYPICAL,uint8_t = 0x40,uint8_t = 0xc0);//To take effect the next time it displays.
void point(boolean PointFlag);//whether to light the clock point ":".To take effect the next time it displays.
void coding(int8_t DispData[]); 
int8_t coding(int8_t DispData); 
 
Пробовал все типы данных int8_t,  uint8_t, double,  int16_t. 
void out_disp(uint8_t TM1637  &disp)
Ошибка одинаковая:
Test_Procedure_out_disp.ino: In function 'void out_disp(int8_t)':
Test_Procedure_out_disp:10:7: error: 'disp' was not declared in this scope
Test_Procedure_out_disp.ino: In function 'void loop()':
Test_Procedure_out_disp:24:18: error: cannot convert 'TM1637' to 'int8_t {aka signed char}' for argument '1' to 'void out_disp(int8_t)'
 
Чего-то не хватает...
 

 

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Приведите полностью ваш скетч и целиком сообщение об ошибке 

2611sergey
Offline
Зарегистрирован: 17.01.2019

Всем спасибо! Разобрался.

Вот рабочий вариант:


#include "TM1637.h"
#define CLK 9//Pins for TM1637   
#define DIO 8//Pins for TM1637
TM1637 disp_1(CLK,DIO); 

void out_disp(TM1637  &disp)

{
      disp.display(1234);
      delay(2000);
      disp.display(5678);
      delay(2000);
}


void setup() {
  disp_1.init();
  disp_1.set(BRIGHT_TYPICAL);

}

void loop() {
  out_disp(disp_1);
}
DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Нальёшь при случае :)

2611sergey
Offline
Зарегистрирован: 17.01.2019

Наливаю. Вот рабочий вариант подключения нескольких TM1637.

Таймер CLK подается на все одновременно. Сигнальный DIO - для каждого свой.

#include "TM1637.h"
#define CLK 9//Pins for TM1637 #1 & #2 
#define DIO 8//Pins for TM1637 #1
#define DIO2 10//Pins for TM1637 #2 
TM1637 disp_1(CLK,DIO); 
TM1637 disp_2(CLK,DIO2); 

void out_disp(TM1637  &disp)

{
      disp.display(1234);
      delay(2000);
      disp.display(5678);
      delay(2000);
}


void setup() {
  disp_1.init();
  disp_1.set(BRIGHT_TYPICAL);
  disp_2.init();
  disp_2.set(BRIGHT_TYPICAL);

}

void loop() {
  out_disp(disp_1);
  out_disp(disp_2);
}

 

ra9ane
Offline
Зарегистрирован: 01.11.2016

Можете помочь чайнику, видимо пенсию не зря назначают, перерыл весь инет и не нашел как вывести десятичные данные на ТМ1637. Думаю что нужно вставить строку "displayInt(value) - вывести на экран четырёхзначное число" Сделал вольтметр на 220В, в монитор порта выводит напряжение, а на индикатор не получается. Будет у Вас время посмотреть код.

ra9ane
Offline
Зарегистрирован: 01.11.2016
Help
 
BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

А где код то?

ra9ane
Offline
Зарегистрирован: 01.11.2016
/*Подключаем библиотеку*/
#include "TM1637.h"
#define CLK 3   //Pins for TM1637      
#define DIO 2   //Pins for TM1637
TM1637 tm1637(CLK, DIO);

/* переменные работающие в обработчике прерывания */
volatile int Umass_A[101]; //масив переменных для хранения мгновенных напряжений фазы А
int Ucor = 0;
long Uism_A = 0; // переменная для хранения измеренного напряжения и квадрата фазы А
long Usumm_A = 0; // переменная для хранения сумм квадратов фазы А 
volatile byte counter = 0; // счетчик в обработчике прерывания
int ADC0 = 0; // аналоговый вход 0 для переменной Ucor!
int ADC1 = 1; // аналоговый вход фазы А
#define ADC1    1  
volatile byte flag = 0;
/* переменные для усреднения напряжений*/
float sqrtUsum_A = 0;
int real_U_A = 0;
float coff = 0.138;    //0.138 коэф для получения 220V
unsigned long timeOut = 0;// переменная для хранения времени!!!

void setup()  
{ 
    //Инициализация модуля
  tm1637.init();
  tm1637.set(BRIGHT_TYPICAL);
  //BRIGHT_TYPICAL = 2,BRIGHT_DARKEST = 0,BRIGHTEST = 7   0-7;
  delay(1500);  //Delay

    TIMSK2 = 0b00000000;         // запрещение прерывания по совпадению таймера/счетчика Т2  
    TCCR2A = 0b00000010;       // режим работы СТС
    TCCR2B = 0b00000011;     // предделитель на 32
    ASSR &= ~(1<<AS2);    // Выбор источника синхронизации таймера(от системного генератора
    OCR2A = 98;                                     
               // срабатывание таймера 16000000/32/100=5000 раз в секунду 100 раз за секунду  
    ADMUX = (0<<REFS1)|(1<<REFS0)|(0<<ADLAR)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(0<<MUX0);
    ADCSRA = 0b10000111;
    Serial.begin(9600);    
  }

void loop()
{
   if(millis()-timeOut > 400)
     {
       timeOut = millis();      
         metod();    
      } 
   if(flag == 3)
   {
     for ( int i = 1; i<101; i++)
     {  
       Uism_A =  Umass_A [i];
       Uism_A -= Ucor;// убираем подьем синусоиды на 2 вольт      
       Uism_A *= Uism_A;
       Usumm_A += Uism_A;      
      }
      sqrtUsum_A = sqrt(Usumm_A); //вычисляем квадратный корень из суммы квадратов
      real_U_A = coff * sqrtUsum_A; //вычисляем реальное напряжение для фазы А     
       Usumm_A = 0;
       counter = 0;
       flag = 0;
       
       Serial.println(real_U_A);  //вывод напряжения 220

  tm1637.point(false);  //Задание на выключение разделителя
      
  int digitoneV = real_U_A/100;  // После деления на 100 остаётся разряд сотен. 
  int digittwoV = real_U_A/10;    // Выделяем разряд. десятков.
  int digitfriV = real_U_A*10;   // Выделяем разряд едениц.
   //Выводим массив на дисплей
  tm1637.display(1, digitoneV);
  tm1637.display(2, digittwoV);
  tm1637.display(3, digitfriV);
  tm1637.display(4, 28); //  U
  //Задержка
  delay(1000);
   }
}
void metod()
{
   Ucor = analogRead(ADC0);  
   TIMSK2 |= (1<<OCIE2A); // разрешаем прерывание
   while(flag<3);
   TIMSK2 = 0b00000000; // останавливаем таймер     
}

word read_adc(byte adc_input)
{
         ADMUX = adc_input | (ADMUX & 0xF0); //задержка для стабилизации входного напряжения
         ADCSRA |= (1<<ADSC); //начинаем преобразование (ADSC = 1)
         while((ADCSRA & 0x10)==0); //ждем, пока АЦП закончит преобразование (ADIF = 0)
        ADCSRA|=0x10;//устанавливаем ADIF
        return ADCW;//ADCW - содержит ADCH и ADCL как нам нужно
  //****************обработчик прерывания********************
ISR(TIMER2_COMPA_vect) 
{  
  counter++;
  if((counter<= 100)&&flag == 0)
  {
    Umass_A[counter] = read_adc(ADC1);  
    if(counter == 100)
    {
      flag = 3;
      counter = 1;
    }
  }
}

1

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

вставьте код по правилам форума, без этого никто помогать не станет

ra9ane
Offline
Зарегистрирован: 01.11.2016

Всё получилось, помогли добрые люди.

/*Подключаем библиотеку*/
#include "TM1637.h"
/*Определяем пины подключения*/
#define CLK 3
#define DIO 2
TM1637 tm1637(CLK, DIO);
/* переменные работающие в обработчике прерывания */
volatile int Umass_A[101]; //масив переменных для хранения мгновенных напряжений фазы А
int Ucor = 0;
long Uism_A = 0; // переменная для хранения измеренного напряжения и квадрата фазы А
long Usumm_A = 0; // переменная для хранения сумм квадратов фазы А 
volatile byte counter = 0; // счетчик в обработчике прерывания
int ADC0 = 0; // аналоговый вход 0 для переменной Ucor!
int ADC1 = 1;
#define ADC1    1  
volatile byte flag = 0;
/* переменные для усреднения напряжений*/
float sqrtUsum_A = 0;
int real_U_A = 0;
float coff = 0.138;
unsigned long timeOut = 0;// переменная для хранения времени!!!

void setup()  {   
      /*Инициализация дисплея*/
  tm1637.init();
  tm1637.set(BRIGHT_TYPICAL);  
    TIMSK2 = 0b00000000;         // запрещение прерывания по совпадению таймера/счетчика Т2  
    TCCR2A = 0b00000010;       // режим работы СТС
    TCCR2B = 0b00000011;     // предделитель на 32
    ASSR &= ~(1<<AS2);    // Выбор источника синхронизации таймера(от системного генератора
    OCR2A = 98;                                     
               // срабатывание таймера 16000000/32/100=5000 раз в секунду 100 раз за секунду   
    ADMUX = (0<<REFS1)|(1<<REFS0)|(0<<ADLAR)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(0<<MUX0);
    ADCSRA = 0b10000111;
    Serial.begin(9600);   
}

void loop()
{  
   if(millis()-timeOut > 400)
     {
       timeOut = millis();     
         metod();      
      }   
   if(flag == 3)
   {
     for ( int i = 1; i<101; i++)
     {  
       Uism_A =  Umass_A [i];
       Uism_A -= Ucor;// убираем подьем синусоиды на 2 вольт     
       Uism_A *= Uism_A;
       Usumm_A += Uism_A;      
      }
      sqrtUsum_A = sqrt(Usumm_A); //вычисляем квадратный корень из суммы квадратов
      real_U_A = coff * sqrtUsum_A; //вычисляем реальное напряжение для фазы А    
       Usumm_A = 0;
       counter = 0;
       flag = 0;    
       Serial.println(real_U_A);
  /*Вывод чисел массива на дисплей*/
  int digitV = real_U_A/1000;      // После деления на 1000 остаётся разряд тысяч.
  int digitoneV = real_U_A/100%10;   // После деления на 100 остаётся разряд сотен. 
  int digittwoV = real_U_A/10%10; // Выделяем разряд. десятков.
  int digitfriV = real_U_A%10;     // Выделяем разряд единиц.
     //Выводим массив на дисплей
  tm1637.display(0, digitV);
  tm1637.display(1, digitoneV); 
  tm1637.display(2, digittwoV);
  tm1637.display(3, digitfriV);
  delay(1000);       
   }
}
   
void metod()
{
   Ucor = analogRead(ADC0);   
   TIMSK2 |= (1<<OCIE2A); // разрешаем прерывание
   while(flag<3);
   TIMSK2 = 0b00000000; // останавливаем таймер     
}
word read_adc(byte adc_input)
{
         ADMUX = adc_input | (ADMUX & 0xF0);//задержка для стабилизации входного напряжения  
//начинаем преобразование (ADSC = 1)
         ADCSRA |= (1<<ADSC);
         while((ADCSRA & 0x10)==0); //ждем, пока АЦП закончит преобразование (ADIF = 0)
        ADCSRA|=0x10;//устанавливаем ADIF
        return ADCW;//ADCW - содержит ADCH и ADCL как нам нужно
}  
  //****************обработчик прерывания********************
ISR(TIMER2_COMPA_vect)  
{  
  counter++;
  if((counter<= 100)&&flag == 0)
  {
    Umass_A[counter] = read_adc(ADC1);  
    if(counter == 100)
    {
      flag = 3;
      counter = 1;
    }
  }
}