Включение двух 3-разрядных индикаторов

Glyuk1
Offline
Зарегистрирован: 30.04.2016
Требуется выводить информацию на 2 независимых друг от друга семисегментных трёхразрядных индикатора. 
Делал по примеру:
http://arduino.ru/forum/proekty/vyvod-informatsii-na-4-razryadnyi-7segmentnyi-indikator-pri-pomoshchi-dvukh-74hc595

Код:

#include "math.h"
#define DATA_PIN    13                 // пин данных (англ. data)
#define LATCH_PIN   12                 // пин строба(защёлки) (англ. latch)
#define CLOCK_PIN   11                 // пин такта (англ. clock)
#define DATA_PIN2   10                 // пин данных (англ. data)
#define LATCH_PIN2   9                 // пин строба(защёлки) (англ. latch)
#define CLOCK_PIN2   8                 // пин такта (англ. clock)
byte SegDisplay;                       // переменная для вывода символов на индикаторе
byte RazrDisplay;                      // переменная для включения разрядов
byte SegDisplay2;                      // переменная для вывода символов на индикаторе
byte RazrDisplay2;                     // переменная для включения разрядов
byte razryad[3]={127,191,223};         // массив цифр, указывающий разряды
byte segments[12]= {                   // массив цифр, генерирующий из сегментов цифры
  252, 96, 218, 242,                   // 0, 1, 2, 3
  102, 182, 190, 224,                  // 4, 5, 6, 7
  254, 246, 2, 0 };                    // 8, 9, -, .
int POT_PIN = A0;                      // потенциометр, задатчик температуры 
int POT_PIN2 = A2;                     // потенциометр, задатчик температуры 

void setup(){
  pinMode(DATA_PIN, OUTPUT);           // DATA_PIN выход
  pinMode(CLOCK_PIN, OUTPUT);          // CLOCK_PIN выход 
  pinMode(LATCH_PIN, OUTPUT);          // LATCH_PIN выход   
  pinMode(DATA_PIN2, OUTPUT);          // DATA_PIN выход
  pinMode(CLOCK_PIN2, OUTPUT);         // CLOCK_PIN выход 
  pinMode(LATCH_PIN2, OUTPUT);         // LATCH_PIN выход                    
}
 
void loop(){  
  
  
  int POT = analogRead(POT_PIN);
  int POT_NUMBER = map(POT, 0, 1023, 0, 120); 
  int number = 0;                     // создаем переменную для вывода на экран
      number = POT_NUMBER;                                 
                                      // Разбиваем цифру по разрядам индикатора
  if (number < 10){                   // если наша цифра меньше 10, то
    Indicate(0, 11);                  // пишем в первый разряд пусто
    Indicate(1, 11);                  // пишем во второй разряд пусто
    Indicate(2, number);              // пишем в третий разряд цифру
  }
  else if (number < 100){             // если наша цифра меньше 100, то
    Indicate(0, 11);                  // пишем в первый разряд пусто
    Indicate(1, number / 10);         // пишем во второй разряд - цифру делёную на 10
    Indicate(2, number % 10);         // пишем в третий разряд - цифру цифру оставшуюся от деления на 10
  }
  else {                              // если наша цифра меньше 1000, то
    Indicate(0, number / 100);        // пишем в первый разряд - цифру делёную на 100
    Indicate(1, (number % 100) / 10); // пишем во второй разряд - цифру цифру оставшуюся от деления на 100 делённую на 10   
    Indicate(2, number % 10);         // пишем в третий разряд - цифру цифру оставшуюся от деления на 10
  }
  int POT2 = analogRead(POT_PIN2);
  int POT_NUMBER2 = map(POT2, 0, 1023, 0, 120); 
  int number2 = 0;                     // создаем переменную для вывода на экран
      number2 = POT_NUMBER2;            

                     
                                      // Разбиваем цифру по разрядам индикатора
  if (number2 < 10){                   // если наша цифра меньше 10, то
    Indicate2(0, 11);                  // пишем в первый разряд пусто
    Indicate2(1, 11);                  // пишем во второй разряд пусто
    Indicate2(2, number2);              // пишем в третий разряд цифру
  }
  else if (number2 < 100){             // если наша цифра меньше 100, то
    Indicate2(0, 11);                  // пишем в первый разряд пусто
    Indicate2(1, number2 / 10);         // пишем во второй разряд - цифру делёную на 10
    Indicate2(2, number2 % 10);         // пишем в третий разряд - цифру цифру оставшуюся от деления на 10
  }
  else {                              // если наша цифра меньше 1000, то
    Indicate2(0, number2 / 100);        // пишем в первый разряд - цифру делёную на 100
    Indicate2(1, (number2 % 100) / 10); // пишем во второй разряд - цифру цифру оставшуюся от деления на 100 делённую на 10   
    Indicate2(2, number2 % 10);         // пишем в третий разряд - цифру цифру оставшуюся от деления на 10
  }
}

void Indicate(int r,int x){
SegDisplay=segments[x];                                     // получаем цифру и выводим символ, из массива цифр, соответствующий этой цифре.
RazrDisplay=razryad[r];                                     // получаем цифру и выводим номер регистра, из массива цифр, соответствующий этой цифре.
  digitalWrite(LATCH_PIN, LOW);                             // устанавливаем синхронизацию "защелки" на LOW
      shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, RazrDisplay); // Записываем информацию для второго регистра (Номер разряда)
      shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, SegDisplay);  // Записываем информацию для первого регистра (Номер символа)
  digitalWrite(LATCH_PIN, HIGH);                            // "защелкиваем" регистр, тем самым устанавливая значения на выходах
      delay(5);                                       // пауза, чтобы сегменты "разгорелись"
}  
void Indicate2(int r2,int x2){
SegDisplay2=segments[x2];                                     // получаем цифру и выводим символ, из массива цифр, соответствующий этой цифре.
RazrDisplay2=razryad[r2];                                     // получаем цифру и выводим номер регистра, из массива цифр, соответствующий этой цифре.
  digitalWrite(LATCH_PIN2, LOW);                             // устанавливаем синхронизацию "защелки" на LOW
      shiftOut(DATA_PIN2, CLOCK_PIN2, LSBFIRST, RazrDisplay2); // Записываем информацию для второго регистра (Номер разряда)
      shiftOut(DATA_PIN2, CLOCK_PIN2, LSBFIRST, SegDisplay2);  // Записываем информацию для первого регистра (Номер символа)
  digitalWrite(LATCH_PIN2, HIGH);                            // "защелкиваем" регистр, тем самым устанавливая значения на выходах
      delay(5);                                            // пауза, чтобы сегменты "разгорелись"
}  

С таким кодом на обоих индикаторах тускло горят 2 и 3 разряды  мерцают ещё цифры, 1 разряд на обоих нормально, и если задержу в одной из функций убрать, то нормально работает идникатор, в функции которого задержка осталась. На сколько я понимаю реализовать 2 функции в одной нельзя. В программирования я не силён, что можно сделать?

Andy
Andy аватар
Offline
Зарегистрирован: 01.01.2016

В 12 строке должно быть

byte razryad[3]={1,2,4};

При условии, что разряды включаются единицей.

Glyuk1
Offline
Зарегистрирован: 30.04.2016

Включаются нулём, индикаторы с рбщим катодом у меня

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

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

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

Glyuk1
Offline
Зарегистрирован: 30.04.2016

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

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

Дело Ваше. Я своё мнение сказал и не навязываюсь.

Glyuk1
Offline
Зарегистрирован: 30.04.2016

На счёт функций можно по-подробнее?

Glyuk1
Offline
Зарегистрирован: 30.04.2016
#include "math.h"
#define DATA_PIN    13                 // пин данных (англ. data)
#define LATCH_PIN   12                 // пин строба(защёлки) (англ. latch)
#define CLOCK_PIN   11                 // пин такта (англ. clock)
#define DATA_PIN2   10                 // пин данных (англ. data)
#define LATCH_PIN2   9                 // пин строба(защёлки) (англ. latch)
#define CLOCK_PIN2   8                 // пин такта (англ. clock)
byte SegDisplay;                       // переменная для вывода символов на индикаторе
byte RazrDisplay;                      // переменная для включения разрядов
byte SegDisplay2;                      // переменная для вывода символов на индикаторе
byte RazrDisplay2;                     // переменная для включения разрядов
byte razryad[3]={127,191,223};         // массив цифр, указывающий разряды
byte segments[12]= {                   // массив цифр, генерирующий из сегментов цифры
  252, 96, 218, 242,                   // 0, 1, 2, 3
  102, 182, 190, 224,                  // 4, 5, 6, 7
  254, 246, 2, 0 };                    // 8, 9, -, .
int POT_PIN = A0;                      // потенциометр
int POT_PIN2 = A2;                     // потенциометр

void setup(){
  pinMode(DATA_PIN, OUTPUT);           // DATA_PIN выход
  pinMode(CLOCK_PIN, OUTPUT);          // CLOCK_PIN выход 
  pinMode(LATCH_PIN, OUTPUT);          // LATCH_PIN выход   
  pinMode(DATA_PIN2, OUTPUT);          // DATA_PIN выход
  pinMode(CLOCK_PIN2, OUTPUT);         // CLOCK_PIN выход 
  pinMode(LATCH_PIN2, OUTPUT);         // LATCH_PIN выход                    
}
 
void loop(){  
  int POT = analogRead(POT_PIN);
  int POT_NUMBER = map(POT, 0, 1023, 0, 120); 
  int number = 0;                     // создаем переменную для вывода на экран
      number = POT_NUMBER;                                 
                                      // Разбиваем цифру по разрядам индикатора
  if (number < 10){                   // если наша цифра меньше 10, то
    Indicate(0, 11);                  // пишем в первый разряд пусто
    Indicate(1, 11);                  // пишем во второй разряд пусто
    Indicate(2, number);              // пишем в третий разряд цифру
  }
  else if (number < 100){             // если наша цифра меньше 100, то
    Indicate(0, 11);                  // пишем в первый разряд пусто
    Indicate(1, number / 10);         // пишем во второй разряд - цифру делёную на 10
    Indicate(2, number % 10);         // пишем в третий разряд - цифру цифру оставшуюся от деления на 10
  }
  else {                              // если наша цифра меньше 1000, то
    Indicate(0, number / 100);        // пишем в первый разряд - цифру делёную на 100
    Indicate(1, (number % 100) / 10); // пишем во второй разряд - цифру цифру оставшуюся от деления на 100 делённую на 10   
    Indicate(2, number % 10);         // пишем в третий разряд - цифру цифру оставшуюся от деления на 10
  }
  
  int POT2 = analogRead(POT_PIN2);
  int POT_NUMBER2 = map(POT2, 0, 1023, 0, 120); 
  int number2 = 0;                     // создаем переменную для вывода на экран
      number2 = POT_NUMBER2;                      
                                       // Разбиваем цифру по разрядам индикатора
  if (number2 < 10){                   // если наша цифра меньше 10, то
    Indicate2(0, 11);                  // пишем в первый разряд пусто
    Indicate2(1, 11);                  // пишем во второй разряд пусто
    Indicate2(2, number2);             // пишем в третий разряд цифру
  }
  else if (number2 < 100){             // если наша цифра меньше 100, то
    Indicate2(0, 11);                  // пишем в первый разряд пусто
    Indicate2(1, number2 / 10);        // пишем во второй разряд - цифру делёную на 10
    Indicate2(2, number2 % 10);        // пишем в третий разряд - цифру цифру оставшуюся от деления на 10
  }
  else {                               // если наша цифра меньше 1000, то
    Indicate2(0, number2 / 100);       // пишем в первый разряд - цифру делёную на 100
    Indicate2(1, (number2 % 100) / 10);// пишем во второй разряд - цифру цифру оставшуюся от деления на 100 делённую на 10   
    Indicate2(2, number2 % 10);        // пишем в третий разряд - цифру цифру оставшуюся от деления на 10
  }
}

void Indicate(int r,int x){
SegDisplay=segments[x];                                     // получаем цифру и выводим символ, из массива цифр, соответствующий этой цифре.
RazrDisplay=razryad[r];                                     // получаем цифру и выводим номер регистра, из массива цифр, соответствующий этой цифре.
  digitalWrite(LATCH_PIN, LOW);                             // устанавливаем синхронизацию "защелки" на LOW
      shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, RazrDisplay); // Записываем информацию для второго регистра (Номер разряда)
      shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, SegDisplay);  // Записываем информацию для первого регистра (Номер символа)
  digitalWrite(LATCH_PIN, HIGH);                            // "защелкиваем" регистр, тем самым устанавливая значения на выходах
      delayMicroseconds(2500);                              // пауза, чтобы сегменты "разгорелись"
}  

void Indicate2(int r2,int x2){
SegDisplay2=segments[x2];                                     // получаем цифру и выводим символ, из массива цифр, соответствующий этой цифре.
RazrDisplay2=razryad[r2];                                     // получаем цифру и выводим номер регистра, из массива цифр, соответствующий этой цифре.
  digitalWrite(LATCH_PIN2, LOW);                              // устанавливаем синхронизацию "защелки" на LOW
      shiftOut(DATA_PIN2, CLOCK_PIN2, LSBFIRST, RazrDisplay2);// Записываем информацию для второго регистра (Номер разряда)
      shiftOut(DATA_PIN2, CLOCK_PIN2, LSBFIRST, SegDisplay2); // Записываем информацию для первого регистра (Номер символа)
  digitalWrite(LATCH_PIN2, HIGH);                             // "защелкиваем" регистр, тем самым устанавливая значения на выходах
      delayMicroseconds(2500);                                // пауза, чтобы сегменты "разгорелись"
}

Поставив задержку в 2.5 миллисекунды  на каждой функции мерцание пропало, но только первый разряд ярко горит

 

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

Glyuk1,

а почему не хотите воспользоваться готовой библиотекой?

Подробнее про функции, ну, это типа как написать новую библиотеку. Я могу, конечно описать, как это делается. если хотите, но это в выходной - много времени надо.

Andy
Andy аватар
Offline
Зарегистрирован: 01.01.2016

Цитата:
Поставив задержку в 2.5 миллисекунды  на каждой функции мерцание пропало, но только первый разряд ярко горит
Потому что у тебя два независимых индикатора, пока ты динамически обновляешь один, на другом светится последний включенный разряд. Если ты добавишь Indicate(2,11); то все разряды будут светиться одинаково тускло.

Тебе надо избавляться от delay и выводить цифры сразу на оба индикатора.

Glyuk1
Offline
Зарегистрирован: 30.04.2016

Не встречал ещё нигде таких библиотек.

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

Glyuk1 пишет:

Не встречал ещё нигде таких библиотек.

А где Вы их планировали встретить? У меня на кухне, например, не водятся. Думаю, у Вас тоже :)))

А вот если в гугле набрать SevenSement arduino library, то вывалится немерянно.

Вот, например (все разные - выбирай любую!)

1. https://github.com/sparkfun/SevSeg

2. http://www.theengineeringprojects.com/2015/03/arduino-library-seven-segment-display.html

3. http://www.thecoderscorner.com/products/38-arduino-downloads/68-arduino-7-segment-leddisplay-library-download

И это далеко не всё. Этого добьра в сети, как дерьма за баней.