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

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

Пока все понятно? Если да, то давайте эту функцию немного доработаем и подгоним ее поближе к нашим реалиям.

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

да мне все понятно , спасибо вы хорошо обьясняете 

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

Вопрос, как вы планируете выводить номера каналов на табло: от 0 до 15 или от 1 до 16?

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

1- 16

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

Тогда, следующий вопрос, что хотите видеть на экране, если ни на одном канале сигнала нет? Пусто или 0?

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

пустоту 

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

ОК. Тогда давайте показывать пустоту будем тоже с помощью этой же функции и научим ее это делать.

Проще всего условиться, что пустоту будет обозначать какое-то число, которое мы не используем для показа номеров каналов. Т.е. любое, которое больше 16. А еще лучше, если этим числом будет 255 (максимально возможное для типа byte).

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

upd. Можно, конечно, и ноль передавать, ведь его тоже не планируется отображать, если будем выводить только 1-16, но тогда можно запутаться в коде - внутренние номера каналов у нас заведены как 0-15. Поэтому предпочтительней 255 - видим его в коде в качестве параметра функции и понимаем, что это точно не номер канала.

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018
void showNumber(byte number)
{
 if (number == 255) 
 LC.clearDisplay(2);
 LC.clearDisplay(3);
 
  byte edinicy   = number % 10;
  for (byte i = 0; i < 8; i ++)
  {
    LC.setRow(2, i, CountDigits[edinicy][i]);
  }
  if (number < 10 ) LC.clearDisplay(3);


  else
  {
    byte desyatki = number / 10;
    for (byte i = 0; i < 8; i ++)
      LC.setRow(3, i, CountDigits[desyatki][i]);
  }
}

я решил вот так поступить но что то не получаетьс мерцающая цифра

 

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

Неправильно. Сейчас у вас оно работает так:
1) Если number == 255, то очищаем матрицу 2.
2) Очищаем матрицу 3 (в любом случае).
3) Не зависимо от того, какое число пришло, пытаемся показать его на экране (даже если это 255).

Исправляйте.
 

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

все тупик, у меня решения нет 

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

Да ладно! о_О Смотрите то вы в ту сторону, что надо, но не до конца доделываете. Осталось расставить несколько скобок и дописать в нужном месте else.

Проверяем число на 255, если да, то очищаем матрицы 2 и 3, иначе показываем цифры.

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

Вы бы не брезговали в if фигурными скобками, как в строке 12, то глядишь бы все и стало на своим места.

В 12-й строке их, конечно, можно опустить, но привыкните и будете их опускать, где надо и не надо.

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

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

[code]

void loop()
{
  byte channel = 99;

  showNumber(channel) ;
}


void showNumber(byte number)
{
  if (number == 255) {
    LC.clearDisplay(2);
    LC.clearDisplay(3);
  }

  else {
    byte edinicy   = number % 10;
    for (byte i = 0; i < 8; i ++)
    {
      LC.setRow(2, i, CountDigits[edinicy][i]);
    }
    if (number < 10 ) {
      LC.clearDisplay(3);
    }
    else
    {
      byte desyatki = number / 10;
      for (byte i = 0; i < 8; i ++)
        LC.setRow(3, i, CountDigits[desyatki][i]);
    }

  }
}
[/code]

 

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

Вы мультиплексоры уже подключали к ардуине или у вас пока, кроме матрицы, ничего не подключено?

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

к сожалению мультиплексоры с китая еще не пришли , у меня есть 8 входной, но показывает он по два столбика тоесть дублирует 0ю и 1ю матрицу для  эсперемта можно я думаю подойдет 

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

С цифрами мы практически закончили, теперь надо немного вернуться и подкорректировать вывод столбцов: слева - направо. Я просто думал, как бы проще определить, с какой стороны матрицы у вас отображается первый канал, а с какой последний.

В нашем предыдущем скетче, в том, что выводит столбики, в строке if(channel == 16) channel = 0; вместо 16 временно поставьте 15, и посмотрите какой столбик не будет показываться на матрице - крайний справа, слева или вообще какой-то другой?

upd. Если что, то мультиплексоры для этого подключать не надо. Ардуина просто будет считывать тот хаос в виде наводок на входном пине (А0 в нашем случае). Или для гарантии А0 подключить к +5В.

 

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

на 0й  слева на прова 1й столбик 

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

Меняли 16 на 15?

if(channel == 15) channel = 0;

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

а так  если то на 1й матрице  с лево на право последний столбик 

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

Т.е. вот так? Где точки - пусто

00000000 00000000 0000000. 00000000
00000000 00000000 0000000. 00000000
........

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

да 

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

да 

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

ОК. Поменяйте строку

LC.setColumn(channel / 8, channel % 8, 255 >> (8 - val));

на такую:

LC.setColumn(!(channel / 8), channel % 8, 255 >> (8 - val));

И снова посмотрите, должен быть погашен самый правый столбик.

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

! инверсия?

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

Да. Меняем местами 1-ю и 0-ю матрицы.

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

Так какой сейчас не горит, последний?

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

if(channel == 15) channel = 0;  

00000000 00000000 00000000 0000000.
00000000 00000000 00000000 0000000.
.......

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

ОК, понятно. Странное, вообще-то, как для меня, подключение матриц. Получается столбцы в матрицах считаются слева направо, а сами матрицы расположены справа - налево. Ну да ладно.

Меняйте обратно 15 на 16 и продолжим.

Должен пока-что получиться вот такой скетч:

#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 channel;

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()
{
  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));

  showNumber(channel);      // временно, для проверки

  channel++;
  if (channel == 16) channel = 0;
}

void showNumber(byte number)
{
  if (number == 255)
  {
    LC.clearDisplay(2);
    LC.clearDisplay(3);
  }
  else
  {
    byte edinicy = number % 10;
    for (byte i = 0; i < 8; i++)
    {
      LC.setRow(2, i, CountDigits[edinicy][i]);
    }
    if (number < 10)
    {
      LC.clearDisplay(3);
    }
    else
    {
      byte desyatki = number / 10;
      for (byte i = 0; i < 8; i++)
        LC.setRow(3, i, CountDigits[desyatki][i]);
    }
  }
}

 

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

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

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

цыфры меняться  быстро , а вот еденица моргает на разных местах обоих матриц 

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

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

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

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

 

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

Странно, добавьте пожалуйста, например, перед строкой channel++; строку delay(1000);

На первых двух матрицах должны по-очереди меняться числа от 0 до 15 и далее по-кругу.

Попробуйте на несколько секунд A0 притягивать к земле, потом к +5V и оставлять висеть свободным. Это не должно сказываться на выводе цифр, только на столбиках. Результат сообщите.

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

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

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

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

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

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

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

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

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

Ну все правильно. Главное, что все на своих местах.

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

да все на своих местах

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

Поехали дальше. Я для себя уже выстроил сценарий. Но мне интересны ваши мысли. Для начала, как вы себе представляете должны показываться активные номера каналов? Т.е., как оно все должно выглядеть визуально?

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

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

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

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

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

Направление мыслей верное. Но вы говорили, что активным может быть не только один канал. Как предлагаете разглядеть числа, если активными будут одновременно каналов 5, 10, а то и все 16? Вы же видели, что творилось на экране, когда числа выводились все по-очереди (до введения задержки).

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

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

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

ОК. Тогда приступайте к реализации. А с проблемами будем разбираться по мере их возникновения.

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018
[code]
#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 channel;
 byte LevelStolbik[16],n;             //массив для значения столбиков 
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()
{
  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)); 
  
   byte LevelStolbik[n] = val;  //записать в значениние n 
   n++;                         // прибавить n 
   if (n > 16) {               // если больше 16 сбросить n
    n = 0;
   }
   
//  showNumber(channel);      // временно, для проверки
//  delay(1000);
  channel++;
  if (channel == 16) channel = 0;
}

void showNumber(byte number)
{
  if (number == 255)
  {
    LC.clearDisplay(2);
    LC.clearDisplay(3);
  }
  else
  {
    byte edinicy = number % 10;
    for (byte i = 0; i < 8; i++)
    {
      LC.setRow(2, i, CountDigits[edinicy][i]);
    }
    if (number < 10)
    {
      LC.clearDisplay(3);
    }
    else
    {
      byte desyatki = number / 10;
      for (byte i = 0; i < 8; i++)
        LC.setRow(3, i, CountDigits[desyatki][i]);
    }
  }
} 
[/code]этот этап по записи массива правильный ?

 

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

Не совсем. Во-первых. Строки 68-69: если n > 16, то n = 0. Т.е., n будет принимать значения от 0 до 16, итого 17 значений. ??? Но у нас ведь только 16 каналов, да и массив объявлен на 16 элементов. А во-вторых, зачем нам n, если у нас уже есть переменная channel, которая работает абсолютно точно так же (ну, если учесть замечание) - постоянно меняет свое значение от 0 до 15 при каждом проходе лупа? Зачем нам еще одна точно такая же переменная (только с другим именем)? Используйте channel.

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

И в-третьих. В строке 66 вы пишете byte LevelStolbik[n] = val; Похоже, вы не понимаете разницы между объявлением переменной и ее использованием. Проще говоря, зачем снова писать byte перед переменной, если вы уже это делали в 13-й строке? Я уже ранее писал, что делая так в разных блоках, вы объявляете новую (еще одну) переменную с таким же именем. Ну и эта конструкция вообще не будет компилироваться, поскольку массивы объявляются несколько иначе (с точки зрения компилятора тут вы как раз попытались объявить массив, а не присвоить его какому-то элементу значение).

Jenek_Anapa
Offline
Зарегистрирован: 13.02.2018
[code]
   LevelStolbik[channel] = val;  //записать в значениние channel
   channel++;                         // прибавить channel
   if (channel > 15) {               // если больше 16 сбросить channel
    channel = 0;
   }

[/code] я просто считал что каждая переменная предназначена для определенного действия , так правильно?

 

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

Если я больше ничего не проглядел, то так уже правильно.

Ну, как-бы, да - переменные предназначены для хранения данных (если быть точнее, меняющихся данных). Но ведь никто не запрещает нам хранящиеся в них данные использовать в разных местах. Вот, например, эту же переменную chanel мы сначала использовали чтобы задать адрес для мультиплексора (строки 55-59) - "вытягивали" из нее биты, а потом в 64-й строке использовали ее уже для расчета номеров матрицы и столбца при выводе столбиков.

Мало того, одну и ту же переменную можем использовать для хранения однотипных данных, логически никак не связанных. Например, в одно время хранить в ней значение температуры, а потом, когда температура нам больше не нужна, записать туда расстояние до объекта. Но это уже моветон и лучше так не делать, сами же можем и запутаться. Это как грузовиком, что возит навоз, возить еще и персики.