LedControl и 3 штуки MAX7219CWG пропадает изображение

Тема в разделе "Arduino & Shields", создана пользователем santer, 10 окт 2019.

  1. santer

    santer Нерд

    Приветствую всех.
    Имею непонятную проблему.
    использую библиотеку LedControl.h
    Управляет она тремя последовательно включенными микрухами MAX7219CWG.
    Т.е имеем 3 строки 7-ми сегментных индикаторов по 8 знаков в каждой.
    При загрузке значения отображаются на всех трех строках.
    Спустя 10-15 сек (каждый раз по разному) исчезает вторая строка, топом первая (иногда сразу обе), НО третья продолжает работать как ни в чем не бывало. 3-я строка самая последняя, т.е. сигнал проходит сквозняком через первые две микрухи.
    Проверил питание - стабильно 5В везде.
    Масса - отлично.
    Думал потеря на CLK,LOAD, нифига, сопротивление на дорожках 0,002 Ом (дальше тестер видимо не умеет).
    В общем полтергей какой-то...
    Беру тестовый скетч, DemoCascadedDevices - все пашет, сегменты везде загораются.
    А вот когда LCDDemo7Segment - первый раз показывает на всех строках, потом опять работает только 3-я.
    Я уже мозг сломал. Помогите!!! ))

    вот образец кода, без шелухи.

    Код (C++):
    // LedControl lc=LedControl(DIN,CLK,LOAD,количество модулей);
    LedControl lc=LedControl(3,5,4,3);

    setup
      lc.shutdown(0,false);    // выключаем срящий режим перводо модуля
      lc.shutdown(1,false);    // выключаем срящий режим второго модуля
      lc.shutdown(2,false);    // выключаем срящий режим третьего модуля
      lc.clearDisplay(0);      // Очистка первого дисплея
      lc.clearDisplay(1);      // Очистка второго дисплея
      lc.clearDisplay(2);      // Очистка второго дисплея
      lc.setIntensity(0,15);   // яркость свечения первого модуля
      lc.setIntensity(1,15);   // яркость свечения второго модуля
      lc.setIntensity(2,15);   // яркость свечения второго модуля

    loop
    ....
    получение значений и вывод на экран через функцию
    ....
    void printDistance1(long v) {
        byte ones, tens, hundreds, thousands, tenthousands, fltens, flones;
        flones=v%10;
        v=v/10;
        fltens=v%10;
        v=v/10;
        ones=v%10;
        v=v/10;
        tens=v%10;
        v=v/10;
        hundreds=v%10;
        v=v/10;
        thousands=v%10;
        v=v/10;
        tenthousands=v%10;
         
        //Now print the number digit by digit
        lc.setDigit(1,7,tenthousands,false);
        lc.setDigit(1,6,thousands,false);
        lc.setDigit(1,5,hundreds,false);
        lc.setDigit(1,4,tens,false);
        lc.setDigit(1,3,ones,true);
        lc.setDigit(1,2,fltens,false);
        lc.setDigit(1,1,flones,false);
        lc.setDigit(1,0,flones,false);
    if (tenthousands == 0 & thousands==0 & hundreds==0 & tens==0)
    {
    lc.setScanLimit(1, 2);
    }
    else if (tenthousands == 0 & thousands==0 & hundreds==0)
    {
    lc.setScanLimit(1, 3);
    }
    else if (tenthousands == 0 & thousands==0)
    {
    lc.setScanLimit(1, 4);
    }
    else if (tenthousands == 0)
    {
    lc.setScanLimit(1, 5);
    }
    }
     
    Последнее редактирование: 10 окт 2019
  2. NikitOS

    NikitOS Король шутов Администратор

    Читаем пост про использование редактора и исправляем ошибки
     
  3. b707

    b707 Гуру

    в этом образце только одна строка, с одной строкой у вас, как я понял,проблемы нет.
    Выкладывайте реально тот код, на котором возникает проблема
     
    Asper Daffy нравится это.
  4. santer

    santer Нерд

    В этом коде возникает проблема, но как я и раньше писал, эта проблема возникает даже в дэмо коде к библиотеке.
    Код (C++):
    #include <EEPROM.h>

    // controller 7-segment LED indicator MAX7219
    #include "LedControl.h"
    // Инициализация дисплеев
    // LedControl lc=LedControl(DIN,CLK,LOAD,количество модулей);
    LedControl lc=LedControl(3,5,4,3);
    // MAX7219 конец

    //клавиатура
    #include <Keypad.h>
    const byte ROWS = 4; //four rows
    const byte COLS = 4; //four columns
    //Указываем символы и знаки на клавиатуре
    char hexaKeys[ROWS][COLS] = {
      {'1','2','3','A'},
      {'4','5','6','B'},
      {'7','8','9','C'},
      {'*','0','#','D'}
    };
    byte rowPins[ROWS] = {13, 12, 11, 10}; //connect to the row pinouts of the keypad  9, 8, 7, 6  6, 7, 8, 9
    byte colPins[COLS] = {9, 8, 7, 6}; //connect to the column pinouts of the keypad  10, 11, 12, 13   13, 12, 11, 10
    //initialize an instance of class NewKeypad
    Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
    ////// клавиатура конец ////////////

    // переменные для трипа
    volatile unsigned long trip_count, tripA_count, tripSpeedcount;     // переменные для функции по прерыванию число импульсов датчика, счетчик одометра А,B для трип компьютера
    unsigned long eepromTime, coef1, coef2, coef3, coef, trip_counteeprom;   // рассчитанное время длительности импульса + коэфициент пересчета/калибровка под разные диаметры колес
    int dist_A, dist_total;
    byte pedAres = 0;
    byte pedBres = 1;
    byte odoAres, odoBres;

    /// переменные для меню
    byte MenuPos =1;
    byte MenuPosMax = 3;
    byte Submenu = 1;
    byte SubmenuMax = 5;
    byte calselect = 1; // значение для меню для выбора конкретной калибровки
    byte calselectTotal = 3;  // общее число возможных калибровок

    /// конец меню

    /// переменные для скорости
    int SPEED, SPEEDmax;
    /// конец переменных для скорости

    /// переменные для периода
    unsigned long period;
    /// конец переменных для париодов



    void setup() {
        Serial.begin(9600);
        customKeypad.setHoldTime(500);                   // Default is 1000mS

      lc.shutdown(0,false);    // выключаем срящий режим перводо модуля
      lc.shutdown(1,false);    // выключаем срящий режим второго модуля
      lc.shutdown(2,false);    // выключаем срящий режим третьего модуля
      lc.clearDisplay(0);      // Очистка первого дисплея
      lc.clearDisplay(1);      // Очистка второго дисплея
      lc.clearDisplay(2);      // Очистка второго дисплея
      lc.setIntensity(0,15);   // яркость свечения первого модуля
      lc.setIntensity(1,15);   // яркость свечения второго модуля
      lc.setIntensity(2,15);   // яркость свечения второго модуля

      coef   = 10;
    //coef   = EEPROM_ulong_read(0);
    coef1  = EEPROM_ulong_read(4);
    coef2  = EEPROM_ulong_read(8);
    coef3  = EEPROM_ulong_read(12);

    trip_count = EEPROM_ulong_read(16);
    tripA_count = EEPROM_ulong_read(20);
    SPEEDmax = EEPROM.read(24);
    attachInterrupt(0, WheelSensor, CHANGE);
    }

    void loop() {



    printDistance0(dist_A); // вызываем функцию отображения на нижнем дисплее и рисуем там промежуточную дистанцию
    printDistance1(dist_total); // вызываем функцию отображения на вернем дисплее и рисуем там общую дистанцию
    printDistance2(SPEED);   // показываем текущую скорость на выносном дисплее

    }

    void WheelSensor()
    {
    trip_count++;
    tripA_count++;
    //tripB_count++;
    //tripTime = millis();
    tripSpeedcount++;
    }

    void printDistance0(long v) {
        byte ones, tens, hundreds, thousands, tenthousands, fltens, flones;

        flones=v%10;
        v=v/10;
        fltens=v%10;
        v=v/10;
        ones=v%10;
        v=v/10;
        tens=v%10;
        v=v/10;
        hundreds=v%10;
        v=v/10;
        thousands=v%10;
        v=v/10;
        tenthousands=v%10;
       
        //Now print the number digit by digit
        lc.setDigit(0,7,tenthousands,false);
        lc.setDigit(0,6,thousands,false);
        lc.setDigit(0,5,hundreds,false);
        lc.setDigit(0,4,tens,false);
        lc.setDigit(0,3,ones,true);
        lc.setDigit(0,2,fltens,false);
        lc.setDigit(0,1,flones,false);
        lc.setDigit(0,0,flones,false);
    if (tenthousands == 0 & thousands==0 & hundreds==0 & tens==0)
    {
    lc.setScanLimit(0, 2);
    }
    else if (tenthousands == 0 & thousands==0 & hundreds==0)
    {
    lc.setScanLimit(0, 3);
    }
    else if (tenthousands == 0 & thousands==0)
    {
    lc.setScanLimit(0, 4);
    }
    else if (tenthousands == 0)
    {
    lc.setScanLimit(0, 5);
    }
    }

    void printDistance1(long v) {
        byte ones, tens, hundreds, thousands, tenthousands, fltens, flones;

        flones=v%10;
        v=v/10;
        fltens=v%10;
        v=v/10;
        ones=v%10;
        v=v/10;
        tens=v%10;
        v=v/10;
        hundreds=v%10;
        v=v/10;
        thousands=v%10;
        v=v/10;
        tenthousands=v%10;
       
        //Now print the number digit by digit
        lc.setDigit(1,7,tenthousands,false);
        lc.setDigit(1,6,thousands,false);
        lc.setDigit(1,5,hundreds,false);
        lc.setDigit(1,4,tens,false);
        lc.setDigit(1,3,ones,true);
        lc.setDigit(1,2,fltens,false);
        lc.setDigit(1,1,flones,false);
        lc.setDigit(1,0,flones,false);
    if (tenthousands == 0 & thousands==0 & hundreds==0 & tens==0)
    {
    lc.setScanLimit(1, 2);
    }
    else if (tenthousands == 0 & thousands==0 & hundreds==0)
    {
    lc.setScanLimit(1, 3);
    }
    else if (tenthousands == 0 & thousands==0)
    {
    lc.setScanLimit(1, 4);
    }
    else if (tenthousands == 0)
    {
    lc.setScanLimit(1, 5);
    }
    }

    void printDistance2(long v) {
        byte ones, tens, hundreds, thousands, tenthousands, fltens, flones;

        flones=v%10;
        v=v/10;
        fltens=v%10;
        v=v/10;
        ones=v%10;
        v=v/10;
        tens=v%10;
        v=v/10;
        hundreds=v%10;
        v=v/10;
        thousands=v%10;
        v=v/10;
        tenthousands=v%10;
       
        //Now print the number digit by digit
        lc.setDigit(2,7,0,false);
        lc.setDigit(2,6,tenthousands,false);
        lc.setDigit(2,5,thousands,false);
        lc.setDigit(2,4,hundreds,false);
        lc.setDigit(2,3,tens,false);
        lc.setDigit(2,2,ones,true);
        lc.setDigit(2,1,fltens,false);
        lc.setDigit(2,0,flones,false);
    if (tenthousands == 0 & thousands==0 & hundreds==0 & tens==0)
    {
    lc.setScanLimit(2, 2);
    }
    else if (tenthousands == 0 & thousands==0 & hundreds==0)
    {
    lc.setScanLimit(2, 3);
    }
    else if (tenthousands == 0 & thousands==0)
    {
    lc.setScanLimit(2, 4);
    }
    else if (tenthousands == 0)
    {
    lc.setScanLimit(2, 5);
    }

    }

    // чтение
    unsigned long EEPROM_ulong_read(int addr) {
      byte raw[4];
      for(byte i = 0; i < 4; i++) raw = EEPROM.read(addr+i);
      unsigned long &num = (unsigned long&)raw;
      return num;
    }


    // запись
    void EEPROM_ulong_write(int addr, unsigned long num) {
      byte raw[4];
      (unsigned long&)raw = num;
      for(byte i = 0; i < 4; i++) EEPROM.write(addr+i, raw);
    }
     
    Последнее редактирование: 11 окт 2019
  5. NikitOS

    NikitOS Король шутов Администратор

    Или
    Или получаем предупреждение, после которого может быть бан
     
  6. santer

    santer Нерд

    В общем, разобрался.
    Оказывается нужно добавлять конденсатор 0,1мкф между 19 и 4 ногой MAX7219CWG.
    Так что в коде все ок.
     
    arkadyf нравится это.
  7. santer

    santer Нерд

    Небольшая ремарка.
    Даже в стандартных/покупных модулях имеется недоработка в схемотехнике. Если подключать модуль короткими проводами, то все работает отлично. Но если вы используете провода длинее 5см, начинается пор..фия. Строки пропадают, знаки могут дублироваться, загораются лишние сегменты и пр. В результате нужно:
    - на КАЖДУЮ микросхему max7219 ставить емкости на питание/земля 0,1 мкФ керамика + 4,7-10мкФ Электролит
    - так же на ногу Din подтягивающий к земле резистор 10 кОм. В результате сегменты даже горят ярче. (это очень странно, но факт).
    Плюс библиотека ledcontrol.h поддерживает максимум 8 микросхем.
    Наверняка есть способ это обойти, но я пока не решил.

    В моей схеме к плате с МК подключен дисплей проводами 7см. В дисплее 3шт МС МАХ7219. За ними подключается выносной дисплей с 4мя МС МАХ7219 на проводе длиной 1м. На выносном дисплее также пришлось ставить емкости.
    В результате схема отлично заработала.
    Всем спасибо, план выполнен.
     
    arkadyf и b707 нравится это.