LED-матрица + MAX7219 + MaxMatrix.lib

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018

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

vk007
Offline
Зарегистрирован: 16.06.2015

Пробуйте.

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018
 for (byte i = 0; i < 16;i++)
     byte number   = LevelStolbik[i]; 
     showNumber( number);
     delay(1000);

вот тут не знаю как обращаться к функции?

 

vk007
Offline
Зарегистрирован: 16.06.2015

Я не понял, что вы хотите так добиться?

Сейчас это выглядит так: переменной number в цикле по-очереди присваиваются значения из массива. После окончания цикла на экран выводится число (от 0 до 8), что хранится в последней ячейке массива, т.е. уровень сигнала последнего (15-го) канала.

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

vk007
Offline
Зарегистрирован: 16.06.2015

В частности, вы снова невнимательны и забываете, о чем я недавно уже говорил. Не брезгуйте фигурными скобками в for'ах, if'ах и т.п. Даже, если в цикле или условии, выполняется всего одна команда - заворачивайте ее в фигурные скобки. Вы (да и компилятор тоже) будете видеть границы блока.

То, что вы сделали отступ в строка 2-4, вовсе не значит, что все они относятся к циклу. Так, как у вас написано, к циклу относится только строка 2. Остальные - выполняются вне и после цикла.

upd. И еще в догонку к предыдущему, сразу не заметил. Запомните: все переменные, объявленные внутри блоков, за пределами этих блоков не видны и при выходе из этих блоков уничтожаются.

В данном случае таким блоком является цикл for - это строки 1 и 2. Поскольку переменную number вы объявили во 2-ой строке, т.е. внутри цикла, то в 3-й строке ее уже использовать нельзя, ее уже не будет существовать и функция showNumber(number) понятия не будет иметь, что за переменная такая этот number. Благо, это обнаружится еще на этапе компиляции и компилятор выдаст ошибку.

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

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018
[code]
   LevelStolbik[channel] = val;  //записать в значениние channel
   channel++;                         // прибавить channel
   if (channel > 15) {  
   channel = 0;                    //сбросить channel
    }
    for (byte i = 0; i < 16;i++){
    byte number   = LevelStolbik[i];
    if (number > 0 )
   {
    ... 
   }
  else 
  {
    ... = 255;
  } 
 } 
 
[/code]как к функции обратиться не знаю 
vk007
Offline
Зарегистрирован: 16.06.2015

К какой функции вы не знаете как обратиться?

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018

что вывода цифр 

vk007
Offline
Зарегистрирован: 16.06.2015

а какой функцией мы выводим цифры?

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018

showNumber() в скобках должна быть переменная , переменную с новую создать нужно ? 

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018

(byte number) или же эту же?

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018

(byte number) или же эту же?

vk007
Offline
Зарегистрирован: 16.06.2015

Смотрите, давайте чуть-чуть вернемся и расставим точки над "i". Возможно вам будет проще понять.

Вы в сообщении #356 привели набросок скетча. Там есть такая строка:

byte number = LevelStolbik[i];

А почему вы назвали свою переменную number? Разве в массиве мы храним номера каналов? За номера каналов в данном случае отвечает переменная i, а в массиве мы храним уровни этих каналов. Не логичнее было бы назвать эту переменную level, а не number? Вот смотрите, что получается:

for (byte i = 0; i < 16; i++)
{
  byte level = LevelStolbik[i];
  if (level > 0)
  {
    // если мы обнаружили, что в этом канале уровень не нулевой, то должны вывести номер этого канала
  }
  else
  {
    // а если уровень равен 0, то выводим пусто
  }
}

Что касается "showNumber() в скобках должна быть переменная". Да, чтобы вывести какое-то число на экран, в скобках должно быть указано это число или переменная, содержащая это число. В данном случае надо вывести номер канала. А какая переменная в этом цикле содержит номер канала?

upd. В догонку. Не обязательно в качестве параметра функции должна быть переменная. Вы же не пишете всегда:

int zaderzhka = 1000;
delay(zaderzhka);

а сразу:

delay(1000);

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

delay(a * 50 + i);

 

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018
  int val = analogRead(SIG);
  val = constrain(val, 0, 700);
  val = map(val, 0, 700, 0, 8);
  LC.setColumn(!(channel / 8), channel % 8, 255 >> (8 - val)); 
  
   LevelStolbik[channel] = val;  //записать в значениние channel
   channel++;                         // прибавить channel
   if (channel > 15) {  
   channel = 0;                    //сбросить channel
    }
    for (byte i = 0; i < 16;i++){
 
     byte level   = LevelStolbik[i];
    if (level > 0 )
   {
   showNumber( channel); // до меня вот тут не доходит , 
    
   }
  else 
  {
    showNumber(255);
  }
  

 

vk007
Offline
Зарегистрирован: 16.06.2015

Jenek_Anapa пишет:

showNumber( channel); // до меня вот тут не доходит ,

Ну да, до меня тоже :) , почему вы там пишите channel? Ведь мы сейчас находимся внутри цикла
for (byte i = 0; i < 16;i++){.....
И каналы перебираем переменной i.

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

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018
   for (byte i = 0; i < 16;i++){
 
     byte level   = LevelStolbik[i];
    if (level > 0 )
   {
   showNumber( i);
   
   }
  else 
  {
    showNumber(255);
  }
   вот так Правильно?
vk007
Offline
Зарегистрирован: 16.06.2015

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

Но, если собрать в кучу эти части, как есть сейчас, и залить в ардуину, то результат, что будет отображаться на экране, нас не устроит вообще. Потому что считываем данные с каналов мы реже, чем делаем их анализ, но даже и так номера каналов будут выводиться так часто, что не успеем их разглядеть. Можно, конечно, поставить секундную задержку после вывода каждого числа и тогда числа на экране сможем разглядеть. Но это еще больше усугубит ситуацию со считыванием сигнала, т.к. каждый канал будет опрашиваться примерно 1 раз в 16 секунд, а на один цикл опроса всех 16 каналов и вовсе будет уходить более 4 минут! Весело, правда?

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

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018

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

vk007
Offline
Зарегистрирован: 16.06.2015

Так оно и есть. Чтобы написать всю программу, сначала надо обкатать ее функциональные части. И, когда будет работать по частям, то склеить все в кучу проще.

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018

я имел в виду о сознании обучения ,

vk007
Offline
Зарегистрирован: 16.06.2015

Вот, что пока получилось. С этим кодом будем работать дальше:


#include "LedControl.h"

#define EN 3
#define S0 4
#define S1 5
#define S2 6
#define S3 7
#define SIG A0

LedControl LC = LedControl(12, 11, 10, 4);
byte LevelStolbik[16];
const byte CountDigits[10][8] =
{
  {0x3c, 0x66, 0x66, 0x66,  0x66, 0x66, 0x66, 0x3c},  //0
  {0x18, 0x38, 0x18, 0x18,  0x18, 0x18, 0x18, 0x7e},  //1
  {0x7c, 0x06, 0x06, 0x06,  0x0c, 0x18, 0x30, 0x7e},  //2
  {0x7c, 0x06, 0x06, 0x3c,  0x06, 0x06, 0x06, 0x7c},  //3
  {0x06, 0x0e, 0x1e, 0x36,  0x66, 0x7e, 0x06, 0x06},  //4
  {0x7e, 0x60, 0x60, 0x7c,  0x06, 0x06, 0x06, 0x7c},  //5
  {0x1c, 0x30, 0x60, 0x7c,  0x66, 0x66, 0x66, 0x3c},  //6
  {0x7e, 0x06, 0x06, 0x0c,  0x0c, 0x18, 0x18, 0x18},  //7
  {0x3c, 0x66, 0x66, 0x3c,  0x66, 0x66, 0x66, 0x3c},  //8
  {0x3c, 0x66, 0x66, 0x66,  0x3e, 0x06, 0x0c, 0x38}   //9
};

void setup()
{
  Serial.begin(9600);

  for (byte i = 0; i < 4; i++)
  {
    LC.shutdown(i, false);
    LC.setIntensity(i, 1);
    LC.clearDisplay(i);
  }

  pinMode(S0, OUTPUT);
  pinMode(S1, OUTPUT);
  pinMode(S2, OUTPUT);
  pinMode(S3, OUTPUT);

  digitalWrite(S0, LOW);
  digitalWrite(S1, LOW);
  digitalWrite(S2, LOW);
  digitalWrite(S3, LOW);

  pinMode(EN, OUTPUT);
  digitalWrite(EN, LOW);
}

void loop()
{
  //////// Опрос каналов /////////
  // В этой части программы опрашиваем каналы с 0-го до 15-го,
  // выводим уровень сигнала каждого канала в виде столбика
  // и сохраняем уровни в массив для последующего анализа
  for (byte channel = 0; channel < 16; channel++)
  {
    byte controlPin[] = { S0, S1, S2, S3 };
    for (byte i = 0; i < 4; i++)
    {
      digitalWrite(controlPin[i], bitRead(channel, i));
    }
    int val = analogRead(SIG);
    val = constrain(val, 0, 700);
    val = map(val, 0, 700, 0, 8);
    LC.setColumn(!(channel / 8), channel % 8, 255 >> (8 - val));
    LevelStolbik[channel] = val;
  }
  ///// Конец опроса каналов /////

  //////////// Анализ ////////////
  // В этой части анализируем массив с данными (со всеми
  // уровнями), собранными в предыдущей части при опросе каналов
  for (byte channel = 0; channel < 16; channel++)
  {
    byte level = LevelStolbik[channel];
    if (level > 0)
    { // если уровень не нулевой, то выводим число с номером этого канала
      byte edinicy = channel % 10;
      for (byte i = 0; i < 8; i++)
      {
        LC.setRow(2, i, CountDigits[edinicy][i]);
      }
      if (channel < 10)
      {
        LC.clearDisplay(3);
      }
      else
      {
        byte desyatki = channel / 10;
        for (byte i = 0; i < 8; i++)
        {
          LC.setRow(3, i, CountDigits[desyatki][i]);
        }
      }
    }
    else
    { // иначе (если уровень нулевой) - очищаем места под цифры
      LC.clearDisplay(2);
      LC.clearDisplay(3);
    }
  }
  //////// Конец анализа /////////
}

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

Попробуйте понять, как работает сейчас программа. В ардуину ее заливать не обязательно - визуально там почти ничего не изменилось. Когда поймете или не поймете, дайте знать, продолжим.

 

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018

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

vk007
Offline
Зарегистрирован: 16.06.2015

Хорошо. Подытожу, сейчас программа работает следующим образом: поочередно опрашиваются каналы от 0 до 15. Ихние уровни выводятся на экран и сохраняются в массив. Потом, также по-очереди, анализируются снова все каналы от 0 до 15 и для активных каналов прописываются ихние номера.

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

  //////////// Анализ ////////////
  // В этой части анализируем массив с данными (со всеми
  // уровнями), собранными в предыдущей части при опросе каналов
  for (byte channel = 0; channel < 16; channel++)
  {
    byte level = LevelStolbik[channel];
    if (level > 0)
    { // если уровень не нулевой, то выводим число с номером этого канала
      byte edinicy = channel % 10;
      for (byte i = 0; i < 8; i++)
      {
        LC.setRow(2, i, CountDigits[edinicy][i]);
      }
      if (channel < 10)
      {
        LC.clearDisplay(3);
      }
      else
      {
        byte desyatki = channel / 10;
        for (byte i = 0; i < 8; i++)
        {
          LC.setRow(3, i, CountDigits[desyatki][i]);
        }
      }
    }
    else
    { // иначе (если уровень нулевой) - очищаем места под цифры
      LC.clearDisplay(2);
      LC.clearDisplay(3);
    }
    delay(1000);
  }
  //////// Конец анализа /////////

Теперь можно будет увидеть цифры. Но такая задержка снова будет влиять на скорость опроса каналов. Уже хоть и не 1 раз в 4 минуты, а всего 1 раз в 16 секунд, но это тоже долго. Немного снизить время ожидания можно, если зажержку ставить не на весь цикл, а только, для вывода цифр (если на экране пусто, то ждать 1 с незачем - нас интересуют только цифры):

  //////////// Анализ ////////////
  // В этой части анализируем массив с данными (со всеми
  // уровнями), собранными в предыдущей части при опросе каналов
  for (byte channel = 0; channel < 16; channel++)
  {
    byte level = LevelStolbik[channel];
    if (level > 0)
    { // если уровень не нулевой, то выводим число с номером этого канала
      byte edinicy = channel % 10;
      for (byte i = 0; i < 8; i++)
      {
        LC.setRow(2, i, CountDigits[edinicy][i]);
      }
      if (channel < 10)
      {
        LC.clearDisplay(3);
      }
      else
      {
        byte desyatki = channel / 10;
        for (byte i = 0; i < 8; i++)
        {
          LC.setRow(3, i, CountDigits[desyatki][i]);
        }
      }
      delay(1000);
    }
    else
    { // иначе (если уровень нулевой) - очищаем места под цифры
      LC.clearDisplay(2);
      LC.clearDisplay(3);
    }
  }
  //////// Конец анализа /////////

Т.е. вывели число, подождали 1 с, проверяем следующее. Время бездействия сократится, но не существенно - при одном активном канале будет 1 с, а при 16 - все те же 16 с. Тоже не вариант.

Значит, будем делать по-другому. Кстати, а у вас есть предложения, как?

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018

интересно 

vk007
Offline
Зарегистрирован: 16.06.2015

Свои предложения есть, как ускорить?

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018

вытаскивать  значения с буфера только те которые больше нуля и отображать  а если  буфер в сумме будет 0 то отправить 255

vk007
Offline
Зарегистрирован: 16.06.2015

Не забывайте, что только отображать - мало. Это будет работать, если активный канал только один. Но если их будет хотя бы два, то на экране начнется такая же свистопляска - то одно, то другое число будут перемигиваться на экране с огромной скоростью. Если бы человек успевал с такой же скоростью различать числа - проблем бы не было. Но нам нужна пауза между отображениями чисел. А это получается практически последний код с delay в 97 строке.

vk007
Offline
Зарегистрирован: 16.06.2015

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

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018

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

vk007
Offline
Зарегистрирован: 16.06.2015

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

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

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

Мысли, как реализовать это в коде, есть?

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018
 for (byte channel = 0; channel < 16; channel++)

это убрать и поставить это

channel++;                       //прибавляем по еденице 
  if(channel == 16) channel = 0; 
Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018
[code]
 if(channel == 16)
 {
 channel = 0;
 }
else
 
  {
    byte level = LevelStolbik[channel];
    if (level > 0)
    { // если уровень не нулевой, то выводим число с номером этого канала
      byte edinicy = channel % 10;
      for (byte i = 0; i < 8; i++)
      {
        LC.setRow(2, i, CountDigits[channel][i]);
      }
      if (channel < 10)
      {
        LC.clearDisplay(3);
      }
      else
      {
        byte desyatki = channel / 10;
        for (byte i = 0; i < 8; i++)
        {
          LC.setRow(3, i, CountDigits[desyatki][i]);
        }
      }
    }
    else
    { // иначе (если уровень нулевой) - очищаем места под цифры
      LC.clearDisplay(2);
      LC.clearDisplay(3);
    }
  }
 channel++;  
  
[/code]

 

vk007
Offline
Зарегистрирован: 16.06.2015

Неплохо. А вписать это в итоговый скетч из поста #371 сможете?

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018

Правильно?

vk007
Offline
Зарегистрирован: 16.06.2015

Не совсем. Вот в 381 сообщении вы написали правильно, но в скетч всунули как-то странно. Почему if вначале и зачем else в 6 строке? Ведь надо всего-то убрать for, и в конце добавить channel++; if(channel == 16) channel = 0;

И еще вот что. В обеих "подпрограммах" - и сбора и анализа используется переменная channel, но это разные переменные, так как они объявлены внутри разных блоков (разных for'ов). Они несут ту же смысловую нагрузку - это счетчики каналов, но все-же они разные.

Первая channel, объявленная в 57-й строке, существует только до 69-й строки (включительно) - пока работает цикл. Цикл закончился - переменная исчезла. Аналогично вторая channel (из второго for'а - анализа данных) - существует только в строках 75-103.

И так они друг другу не мешали. Но сейчас нам надо один for "раскрыть" и, мало того, еще номер канала для анализа нам надо хранить так, чтобы из перехода из loop'а в loop переменная не теряла этот номер. Один из вариантов - это объявить эту переменную глобально, т.е. за пределами любых функций (loop'а и setup'а в том числе) - где-нибудь в начале скетча.

Но это еще не все. Теперь мы можем еще больше запутаться, ведь у нас по-прежнему две channel - только одна стала глобальной, а вторая осталась локальной. Понять, где какая с первого, да и второго, раза будет непросто. Одну из них надо назвать как-то иначе, чтобы было сразу видно, что это разные переменные.

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018
[code]
  //////////// Анализ ////////////
  // В этой части анализируем массив с данными (со всеми
  // уровнями), собранными в предыдущей части при опросе каналов
  
  if(channelA == 16) channelA = 0;
  {
    byte level = LevelStolbik[channelA];
    if (level > 0)
    { // если уровень не нулевой, то выводим число с номером этого канала
      byte edinicy = channelA % 10;
      for (byte i = 0; i < 8; i++)
      {
        LC.setRow(2, i, CountDigits[channelA][i]);
      }
      if (channelA < 10)
      {
        LC.clearDisplay(3);
      }
      else
      {
        byte desyatki = channelA / 10;
        for (byte i = 0; i < 8; i++)
        {
          LC.setRow(3, i, CountDigits[desyatki][i]);
        }
      }
    }
    else
    { // иначе (если уровень нулевой) - очищаем места под цифры
      LC.clearDisplay(2);
      LC.clearDisplay(3);
    }
  }
  channelA++;
  //////// Конец анализа /////////

[/code]

 

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018

переменную то я обьявил , но циферки десятков поплыли 

vk007
Offline
Зарегистрирован: 16.06.2015

Давайте весь скетч целиком. И все хочу спросить, откуда у вас при вставке сюда кода берутся теги [code] и [/code]?

vk007
Offline
Зарегистрирован: 16.06.2015

Строки 7 и 34 не нужны.

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018

#include "LedControl.h"

#define EN 3
#define S0 4
#define S1 5
#define S2 6
#define S3 7
#define SIG A0

LedControl LC = LedControl(12, 11, 10, 4);
byte channelA;
byte LevelStolbik[16];
const byte CountDigits[10][8] =
{
  {0x3c, 0x66, 0x66, 0x66,  0x66, 0x66, 0x66, 0x3c},  //0
  {0x18, 0x38, 0x18, 0x18,  0x18, 0x18, 0x18, 0x7e},  //1
  {0x7c, 0x06, 0x06, 0x06,  0x0c, 0x18, 0x30, 0x7e},  //2
  {0x7c, 0x06, 0x06, 0x3c,  0x06, 0x06, 0x06, 0x7c},  //3
  {0x06, 0x0e, 0x1e, 0x36,  0x66, 0x7e, 0x06, 0x06},  //4
  {0x7e, 0x60, 0x60, 0x7c,  0x06, 0x06, 0x06, 0x7c},  //5
  {0x1c, 0x30, 0x60, 0x7c,  0x66, 0x66, 0x66, 0x3c},  //6
  {0x7e, 0x06, 0x06, 0x0c,  0x0c, 0x18, 0x18, 0x18},  //7
  {0x3c, 0x66, 0x66, 0x3c,  0x66, 0x66, 0x66, 0x3c},  //8
  {0x3c, 0x66, 0x66, 0x66,  0x3e, 0x06, 0x0c, 0x38}   //9
};

void setup()
{
  Serial.begin(9600);

  for (byte i = 0; i < 4; i++)
  {
    LC.shutdown(i, false);
    LC.setIntensity(i, 1);
    LC.clearDisplay(i);
  }

  pinMode(S0, OUTPUT);
  pinMode(S1, OUTPUT);
  pinMode(S2, OUTPUT);
  pinMode(S3, OUTPUT);

  digitalWrite(S0, LOW);
  digitalWrite(S1, LOW);
  digitalWrite(S2, LOW);
  digitalWrite(S3, LOW);

  pinMode(EN, OUTPUT);
  digitalWrite(EN, LOW);
}

void loop()
{
  //////// Опрос каналов /////////
  // В этой части программы опрашиваем каналы с 0-го до 15-го,
  // выводим уровень сигнала каждого канала в виде столбика
  // и сохраняем уровни в массив для последующего анализа
  for (byte channel = 0; channel < 16; channel++)
  {
    byte controlPin[] = { S0, S1, S2, S3 };
    for (byte i = 0; i < 4; i++)
    {
      digitalWrite(controlPin[i], bitRead(channel, i));
    }
    int val = analogRead(SIG);
    val = constrain(val, 0, 700);
    val = map(val, 0, 700, 0, 8);
    LC.setColumn(!(channel / 8), channel % 8, 255 >> (8 - val));
    LevelStolbik[channel] = val;
  }
  ///// Конец опроса каналов /////

  //////////// Анализ ////////////
  // В этой части анализируем массив с данными (со всеми
  // уровнями), собранными в предыдущей части при опросе каналов
  
  if(channelA == 16) channelA = 0;
  {
    byte level = LevelStolbik[channelA];
    if (level > 0)
    { // если уровень не нулевой, то выводим число с номером этого канала
      byte edinicy = channelA % 10;
      for (byte i = 0; i < 8; i++)
      {
        LC.setRow(2, i, CountDigits[channelA][i]);
      }
      if (channelA < 10)
      {
        LC.clearDisplay(3);
      }
      else
      {
        byte desyatki = channelA / 10;
        for (byte i = 0; i < 8; i++)
        {
          LC.setRow(3, i, CountDigits[desyatki][i]);
        }
      }
    }
    else
    { // иначе (если уровень нулевой) - очищаем места под цифры
      LC.clearDisplay(2);
      LC.clearDisplay(3);
    }
  }
  channelA++;
  //////// Конец анализа /////////
}

 

vk007
Offline
Зарегистрирован: 16.06.2015

Исправьте строку 85, должно быть так:

LC.setRow(2, i, CountDigits[edinicy][i]);

Я где-то из вашего кода скопировал и не посмотрел.

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

delay(1000);

И да, фигурные скобки в строках 78 и 105 лишние.

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

А сейчас пробуйте. И пока внимательно читайте и изучайте http://arduino.ru/tutorials/BlinkWithoutDelay

vk007
Offline
Зарегистрирован: 16.06.2015

Да и Serial.begin(9600); из сетапа можно убрать. Нам он не нужен. В общем, скетч за сегодняшний день должен выглядеть так:

#include "LedControl.h"

#define EN 3
#define S0 4
#define S1 5
#define S2 6
#define S3 7
#define SIG A0

LedControl LC = LedControl(12, 11, 10, 4);
byte channelA;
byte LevelStolbik[16];
const byte CountDigits[10][8] =
{
  {0x3c, 0x66, 0x66, 0x66,  0x66, 0x66, 0x66, 0x3c},  //0
  {0x18, 0x38, 0x18, 0x18,  0x18, 0x18, 0x18, 0x7e},  //1
  {0x7c, 0x06, 0x06, 0x06,  0x0c, 0x18, 0x30, 0x7e},  //2
  {0x7c, 0x06, 0x06, 0x3c,  0x06, 0x06, 0x06, 0x7c},  //3
  {0x06, 0x0e, 0x1e, 0x36,  0x66, 0x7e, 0x06, 0x06},  //4
  {0x7e, 0x60, 0x60, 0x7c,  0x06, 0x06, 0x06, 0x7c},  //5
  {0x1c, 0x30, 0x60, 0x7c,  0x66, 0x66, 0x66, 0x3c},  //6
  {0x7e, 0x06, 0x06, 0x0c,  0x0c, 0x18, 0x18, 0x18},  //7
  {0x3c, 0x66, 0x66, 0x3c,  0x66, 0x66, 0x66, 0x3c},  //8
  {0x3c, 0x66, 0x66, 0x66,  0x3e, 0x06, 0x0c, 0x38}   //9
};

void setup()
{
  for (byte i = 0; i < 4; i++)
  {
    LC.shutdown(i, false);
    LC.setIntensity(i, 1);
    LC.clearDisplay(i);
  }

  pinMode(S0, OUTPUT);
  pinMode(S1, OUTPUT);
  pinMode(S2, OUTPUT);
  pinMode(S3, OUTPUT);

  digitalWrite(S0, LOW);
  digitalWrite(S1, LOW);
  digitalWrite(S2, LOW);
  digitalWrite(S3, LOW);

  pinMode(EN, OUTPUT);
  digitalWrite(EN, LOW);
}

void loop()
{
  //////// Опрос каналов /////////
  // В этой части программы опрашиваем каналы с 0-го до 15-го,
  // выводим уровень сигнала каждого канала в виде столбика
  // и сохраняем уровни в массив для последующего анализа
  for (byte channel = 0; channel < 16; channel++)
  {
    byte controlPin[] = { S0, S1, S2, S3 };
    for (byte i = 0; i < 4; i++)
    {
      digitalWrite(controlPin[i], bitRead(channel, i));
    }
    int val = analogRead(SIG);
    val = constrain(val, 0, 700);
    val = map(val, 0, 700, 0, 8);
    LC.setColumn(!(channel / 8), channel % 8, 255 >> (8 - val));
    LevelStolbik[channel] = val;
  }
  ///// Конец опроса каналов /////

  //////////// Анализ ////////////
  // В этой части анализируем массив с данными (со всеми
  // уровнями), собранными в предыдущей части при опросе каналов
  byte level = LevelStolbik[channelA];
  if (level > 0)
  { // если уровень не нулевой, то выводим число с номером этого канала
    byte edinicy = channelA % 10;
    for (byte i = 0; i < 8; i++)
    {
      LC.setRow(2, i, CountDigits[edinicy][i]);
    }
    if (channelA < 10)
    {
      LC.clearDisplay(3);
    }
    else
    {
      byte desyatki = channelA / 10;
      for (byte i = 0; i < 8; i++)
      {
        LC.setRow(3, i, CountDigits[desyatki][i]);
      }
    }
    delay(1000);
  }
  else
  { // иначе (если уровень нулевой) - очищаем места под цифры
    LC.clearDisplay(2);
    LC.clearDisplay(3);
  }
  channelA++;
  if (channelA == 16) channelA = 0;
  //////// Конец анализа /////////
}

 

vk007
Offline
Зарегистрирован: 16.06.2015

Ну, как там движутся дела с освоением millis? Или на этом все - текущий результат устраивает?

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018

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

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018

я бы не против сделать часы с тернометром уличным например , заодно и научится 

vk007
Offline
Зарегистрирован: 16.06.2015

Jenek_Anapa пишет:

millis, я где это встречал уже , помоему это в часах и таймерах часто используют 

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

vk007
Offline
Зарегистрирован: 16.06.2015

Jenek_Anapa пишет:

я бы не против сделать часы с тернометром уличным например , заодно и научится 

Ну чего чего, а часов уже наделано великое множество, примеров для изучения достаточно. Я свои матричные тоже недавно выкладывал http://arduino.ru/forum/proekty/eshche-odni-chasy-na-matritsakh (но матрицы немного другие, чем у вас).

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018

а millis() можно использовать на прямую в скобках указывать как у delay() 

vk007
Offline
Зарегистрирован: 16.06.2015

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

Читайте описание (ссылки я уже приводил в сообщении #153), что делают и зачем нужны разные функции. Пока не разберетесь, дальше делать нечего.

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018

#include "LedControl.h"

#define EN 3
#define S0 4
#define S1 5
#define S2 6
#define S3 7
#define SIG A0

LedControl LC = LedControl(12, 11, 10, 4);
byte channelA;
byte LevelStolbik[16];

long previousMillis = 0;        // храним время
long interval = 1000;           // интервал между включение/выключением светодиода (1 секунда)


const byte CountDigits[10][8] =
{
  {0x3c, 0x66, 0x66, 0x66,  0x66, 0x66, 0x66, 0x3c},  //0
  {0x18, 0x38, 0x18, 0x18,  0x18, 0x18, 0x18, 0x7e},  //1
  {0x7c, 0x06, 0x06, 0x06,  0x0c, 0x18, 0x30, 0x7e},  //2
  {0x7c, 0x06, 0x06, 0x3c,  0x06, 0x06, 0x06, 0x7c},  //3
  {0x06, 0x0e, 0x1e, 0x36,  0x66, 0x7e, 0x06, 0x06},  //4
  {0x7e, 0x60, 0x60, 0x7c,  0x06, 0x06, 0x06, 0x7c},  //5
  {0x1c, 0x30, 0x60, 0x7c,  0x66, 0x66, 0x66, 0x3c},  //6
  {0x7e, 0x06, 0x06, 0x0c,  0x0c, 0x18, 0x18, 0x18},  //7
  {0x3c, 0x66, 0x66, 0x3c,  0x66, 0x66, 0x66, 0x3c},  //8
  {0x3c, 0x66, 0x66, 0x66,  0x3e, 0x06, 0x0c, 0x38}   //9
};

void setup()
{
  for (byte i = 0; i < 4; i++)
  {
    LC.shutdown(i, false);
    LC.setIntensity(i, 1);
    LC.clearDisplay(i);
  }

  pinMode(S0, OUTPUT);
  pinMode(S1, OUTPUT);
  pinMode(S2, OUTPUT);
  pinMode(S3, OUTPUT);

  digitalWrite(S0, LOW);
  digitalWrite(S1, LOW);
  digitalWrite(S2, LOW);
  digitalWrite(S3, LOW);

  pinMode(EN, OUTPUT);
  digitalWrite(EN, LOW);
}

void loop()
{
   unsigned long currentMillis = millis(); //код, который будет работать постоянно


  //////// Опрос каналов /////////
  // В этой части программы опрашиваем каналы с 0-го до 15-го,
  // выводим уровень сигнала каждого канала в виде столбика
  // и сохраняем уровни в массив для последующего анализа
  for (byte channel = 0; channel < 16; channel++)
  {
    byte controlPin[] = { S0, S1, S2, S3 };
    for (byte i = 0; i < 4; i++)
    {
      digitalWrite(controlPin[i], bitRead(channel, i));
    }
    int val = analogRead(SIG);
    val = constrain(val, 0, 700);
    val = map(val, 0, 700, 0, 8);
    LC.setColumn(!(channel / 8), channel % 8, 255 >> (8 - val));
    LevelStolbik[channel] = val;
  }
  ///// Конец опроса каналов /////

  //////////// Анализ ////////////
  // В этой части анализируем массив с данными (со всеми
  // уровнями), собранными в предыдущей части при опросе каналов
  byte level = LevelStolbik[channelA];
  if (level > 0)
  { // если уровень не нулевой, то выводим число с номером этого канала
    byte edinicy = channelA % 10;
    for (byte i = 0; i < 8; i++)
    {
      LC.setRow(2, i, CountDigits[edinicy][i]);
    }
    if (channelA < 10)
    {
      LC.clearDisplay(3);
    }
    else
    {
      byte desyatki = channelA / 10;
      for (byte i = 0; i < 8; i++)
      {
        LC.setRow(3, i, CountDigits[desyatki][i]);
      }
    }
    //delay(1000);
   if(currentMillis - previousMillis > interval) { //проверяем не прошел ли нужный интервал, если прошел то
      previousMillis = currentMillis;             // сохраняем время последнего переключения
   }
    
  }
  else
  { // иначе (если уровень нулевой) - очищаем места под цифры
    LC.clearDisplay(2);
    LC.clearDisplay(3);
  }
  channelA++;
  if (channelA == 16) channelA = 0;
  //////// Конец анализа /////////
}