WIFI часы с метеостанцией на ESP8266 и матричном индикаторе на MAX7219 WEB интерфейс (Русская и Украинская версии)

НАЗНАЧЕНИЕ НАБОРА

Набор «Часы на светодиодных матрицах 8х8 MAX7219 на Arduino UNO» представляет собой электронные часы и  предназначен для вывода значений реального времени на четырехразрядный светодиодный индикатор с помощью программы написанной для Arduino . Набор дает углубленное понимание  процесса последовательной передачи данных между периферийными устройствами и  понятия динамической индикации. Скетчи написаны на языке C++. 

СОСТАВ НАБОРА

1.  Arduino UNO  +  кабель для подключения к компьютеру – 1шт. 2.  Модуль часов  RTС  DS3231 – 1шт   3.  Модули  светодиодных матрицах 8х8   MAX7219 -4 шт. 4.  Макетная плата –  1 шт 5.  Набор проводов – 1 к-т. 6. Скетчи для тестирования модулей RTС  DS3231 и светодиодных матрицах 8х8     MAX7219 7. Скетч вывода реального времени на  цифровой индикатор.

СХЕМА ПОДКЛЮЧЕНИЯ К Arduino UNO

Рис. 1.

НАЧАЛО РАБОТЫ

1.Собрать схему как показано на Рисунке 1. 2.      Подключить к Arduino IDE библиотеки  DS3231.h и Time.h Загрузить скетч  I2C_Scan_OK.ino. Сканер обнаруживает два устройства на шине i2C по следующим адресам: a). 0x57 — это адрес микросхемы памяти AT24C32 b) 0x68 — адрес микросхемы DS3231SN   При неисправности   или неправильном соединении увидим сообщение 3.      Загрузить скетч Set_Time_DS3231_OK.ino для установки времени.   Скорректировать данные установок времени Clock.setYear(16); //Задаем год  2016 — две последние цифры Clock.setMonth(1); //Задаем месяц  0-12 Clock.setDate(24); //Задаем ден месяца  0-31 Clock.setDoW(7); //Задаем день недели 1-7  7-воскресенье Clock.setHour(18);     //Задаем время — часы Clock.setMinute(23);   //Задаем время — минуты Clock.setSecond(00);   //Задаем время  — секунды 4.       Отключить модуль от питания компьютера. Через 3-5 минут вновь его подключить и загрузить скетч файл   Watch_MAX7219_4_Digits_UNO_OK.ino. На  индикаторах светодиодных матриц 8х8   MAX7219 и мониторе последовательного порта должны  увидеть реальное время  .

БИБЛИОТЕКИ

LedControl.h              Предназначена для инициализации, и вывода графической информации на  модуль Dot matrix module MAX7219 . Позволяет каскадировать модули и анимировать выводимую информацию.             Библиотека также позволяет работать с семисегментными модулями, построенные на базе микросхемы  MAX7219 и поддерживает до 8-ми разрядов семисегментных индикаторов.   DS3231.h DS3231.zip   Обеспечивает работу Arduino по интерфейсу I2C микросхемой DS3231 фирмы Dallas. Wire.h – библиотека Данная библиотека позволяет Ардуино взаимодействовать с различными устройствами по интерфейсу I2C / TWI. Встроена в Arduino IDE – не требует дополнительного подключения. Time.h — библиотека Библиотека Time.h содержит  определения и функции для работы со временем такие как: second()          cекунда, minute()          минута, hour()              час, day()               день,  weekday()       день недели, month()           месяц, year()              год  setTime()

СКЕТЧИ

I2C_Scan_OK.ino /************************************************************     Сканер подключенных к Arduino устройств работающих по протоколу I2C     Файл I2C_Scan_OK.ino      2015-11-10ноя  Расположение выводов TWI на тех или иных платах Ардуино для наглядности сведено в таблицу: Ардуино  Выводы I2C / TWI Uno, Ethernet     A4 (SDA)  A5 (SCL) Mega2560          20 (SDA)  21 (SCL) Leonardo           2 (SDA)   3 (SCL) Due               20 (SDA)  21 (SCL)                       SDA1     SCL1 *****************************************************************************/     #include     void setup()     {       Wire.begin();       Serial.begin(9600);       Serial.println(«nI2C Scanner»);     }     void loop()     {       byte error, address;       int nDevices;       Serial.println(«Scanning…»);       nDevices = 0;       for(address = 1; address < 127; address++ )       {         // The i2c_scanner uses the return value of         // the Write.endTransmisstion to see if         // a device did acknowledge to the address.         Wire.beginTransmission(address);         error = Wire.endTransmission();         if (error == 0)         {           Serial.print(«I2C device found at address 0x»);           if (address<16)</span>             Serial.print(«0»);           Serial.print(address,HEX);           Serial.println(»  !»);           nDevices++;         }         else if (error==4)         {           Serial.print(«Unknow error at address 0x»);           if (address<16)</span>             Serial.print(«0»);           Serial.println(address,HEX);         }          }       if (nDevices == 0)         Serial.println(«No I2C devices foundn»);       else         Serial.println(«donen»);       delay(5000);           // wait 5 seconds for next scan     } Set_Time_DS3231_OK.ino /************************************************************ Программа установки времени для модуля часов RTS на DS3231  Файл Set_Time_DS3231_OK.ino Создан 24  янв 2016г.          Мащенко В.И.  mvi54@mail.ru   (Портал робототехники arduino.by — info@arduino.by)  Расположение выводов I2C/TWI на тех или иных платах Ардуино для наглядности сведено в таблицу: Ардуино  Выводы I2C / TWI Uno, Ethernet     A4 (SDA)  A5 (SCL) Mega2560          20 (SDA)  21 (SCL) Leonardo           2 (SDA)   3 (SCL) Due               20 (SDA)  21 (SCL)                       SDA1     SCL1 *****************************************************************************/ #include «DS3231.h» #include «Wire.h» DS3231 Clock; bool Century=false; bool h12; bool PM; byte year, month, date, DoW, hour, minute, second; void setup() { // Start the I2C interface Wire.begin(); Clock.setYear(16); //Задаем год  2016 — две последние цифры Clock.setMonth(2); //Задаем месяц  0-12 Clock.setDate(22); //Задаем ден месяца  0-31 Clock.setDoW(7); //Задаем день недели 1-7  7-воскресенье Clock.setHour( 0);     //Задаем время — часы Clock.setMinute(19);   //Задаем время — минуты Clock.setSecond(5);   //Задаем время  — секунды Serial.begin(9600); } void loop() { int second,minute,hour,date,month,year,temperature; second=Clock.getSecond(); minute=Clock.getMinute(); hour=Clock.getHour(h12, PM); date=Clock.getDate(); month=Clock.getMonth(Century); year=Clock.getYear(); temperature=Clock.getTemperature(); Serial.print(«20»); Serial.print(year,DEC); Serial.print(‘-‘); Serial.print(month,DEC); Serial.print(‘-‘); Serial.print(date,DEC); Serial.print(‘ ‘); Serial.print(hour,DEC); Serial.print(‘:’); Serial.print(minute,DEC); Serial.print(‘:’); Serial.print(second,DEC); Serial.print(‘t’); Serial.print(«Temperature=»); Serial.print(temperature); Serial.print(‘n’); delay(1000); } Watch_MAX7219_4_Digits_UNO_OK.ino /************************************************************************************* Программа вывода на четыре каскасированных индикатора LED 8*8 MAX7219 времени в формате ЧЧ—MM   Модуль часов RTC (DS3231/ AT24C32)     http://easycraft.by/product.php?article=EC141234   Модуль светодиодной матрицы MAX7219    http://easycraft.by/product.php?article=FZ0148 файл   Watch_MAX7219_4_Digits_UNO_OK.ino Создан 22 фев 2015г.    Мащенко В.И.   mvi54@mail.ru   (Портал робототехники arduino.by — info@arduino.by) Arduino UNO      RTC DS323 SCL   pin A5     SCL SDA   pin A4     SDA           5V     VCC          GND     GND Arduino UNO    MAX7219           5V     VCC          GND     GND      pin D12     DIN      pin D11     CS      pin D10     CLK *************************************************************************************/ #include #include     //http://github.com/JChristensen/DS3232RTC #include          //http://www.arduino.cc/playground/Code/Time  #include          //http://arduino.cc/en/Reference/Wire (included with Arduino IDE) const int DIN = 12;           //  выход данных с Arduino const int CLK = 11;           //  частота синхронизации последовательной передачи данных Arduino const int  CS = 10;           //  выбор Dot matrix module MAX7219 const int  Numbe_MAX = 4;     //  количество модулей  Dot matrix module MAX7219 LedControl my_MAX7219=LedControl(DIN,CLK,CS,Numbe_MAX); unsigned long delaytime=100; // представление цифр 0 до 10 для Dot matrix module MAX7219 в виде двоичных массивов   byte dig_0[7]={B01111110, B10000001, B10000001, B10000001, B01111110, B00000000, B00000000};   byte dig_1[7]={B00000001, B11111111, B01000001, B00100001, B00000000, B00000000, B00000000};   byte dig_2[7]={B01110001, B10001001, B10001001, B10000101, B01000011, B00000000, B00000000};   byte dig_3[7]={B01101110, B10010001, B10010001, B10000001, B01000010, B00000000, B00000000};   byte dig_4[7]={B11111111, B01000100, B00100100, B00010100, B00001100, B00000000, B00000000};   byte dig_5[7]={B00001110, B10010001, B10010001, B10010001, B11100010, B00000000, B00000000};   byte dig_6[7]={B00001110, B10010001, B10010001, B10010001, B01111110, B00000000, B00000000};   byte dig_7[7]={B11100000, B10010000, B10001000, B10000111, B10000000, B00000000, B00000000};   byte dig_8[7]={B01101110, B10010001, B10010001, B10010001, B01101110, B00000000, B00000000};   byte dig_9[7]={B01111110, B10001001, B10001001, B10001001, B01110000, B00000000, B00000000};   // представление двух точек  для вывода  формата ЧЧ—MM    byte dot_1[7]={B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00011000};  // byte dot_0[7]={B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000}; void setup() {     Serial.begin (9600);   for (int j=0; j< Numbe_MAX;j++)      { // инициализация всех подключенных Dot matrix module MAX7219         my_MAX7219.shutdown(j,false);   //          my_MAX7219.setIntensity(j,8);   //  устанавливаем интенсивность свечения от  0 до 16         my_MAX7219.clearDisplay(j);     //  очистка дисплея от мусора      }    setSyncProvider(RTC.get);   // синхронизируем получние времени от RTC   if(timeStatus() != timeSet)         Serial.println(«Unable to sync with the RTC»);   else        Serial.println(«RTC has set the system time»);      } void loop()  Print_Display_Time ();  // выводит время часов RTC DS3231 на монитор PC  Print_MAX7219_Time();   // выводит время часов RTC DS3231 на Dot matrix module MAX7219   delay (1000);  //Print_MAX7219_1456();  // ТЕСТ — выводид на 4-х каскадированный дисплей цифры 1456 } void Print_MAX7219_Time() { // выводид на 4-х каскадированный дисплей паказанмя часов RTC DS3231  Write_One_Digit ((hour()/10), 0);  Write_One_Digit ((hour()%10), 1);  Write_One_Digit ((minute()/10), 2);  Write_One_Digit ((minute()%10), 3); } void Print_MAX7219_1456() { // выводид на 4-х каскадированный дисплей цифры 1456  Write_One_Digit (1, 0);  Write_One_Digit (4, 1);  Write_One_Digit (5, 2);  Write_One_Digit (6, 3); }; void Write_One_Digit (int dig, int col) {// выводит на  LED Dot matrix module MAX7219  цифру «dig»  в разряд «col»  // col=0   —   часы десятки (0-2)  // col=1   —   часы единицы (0-9)  // col=2   —   минуты десятки (0-5)  // col=3   —   минуты единицы (0-9)   switch (dig)   {      case 0:           for (int t=0; t<7; t++)</span>              {                 if (col == 2)                    {                     my_MAX7219.setRow(col,t,dig_0[t]|dot_1[t]);                    }                 else                   {                          my_MAX7219.setRow(col,t,dig_0[t]);                   }              }            break;     case 1:          for (int t=0; t<7; t++)</span>             {                if (col == 2)                    {                     my_MAX7219.setRow(col,t,dig_1[t] |dot_1[t]);                    }                 else                   {                          my_MAX7219.setRow(col,t,dig_1[t]);                   }                }          break;    case 2:         for (int t=0; t<7; t++)</span>             {                if (col == 2)                    {                     my_MAX7219.setRow(col,t,dig_2[t] | dot_1[t]);                    }                 else                   {                          my_MAX7219.setRow(col,t,dig_2[t]);                   }                }          break;    case 3:         for (int t=0; t<7; t++)</span>             {                if (col == 2)                    {                     my_MAX7219.setRow(col,t,dig_3[t]|dot_1[t]);                    }                 else                   {                          my_MAX7219.setRow(col,t,dig_3[t]);                   }                }          break;     case 4:         for (int t=0; t<7; t++)</span>           {                if (col == 2)                    {                     my_MAX7219.setRow(col,t,dig_4[t]|dot_1[t]);                    }                 else                   {                          my_MAX7219.setRow(col,t,dig_4[t]);                   }            }           break;     case 5:        for (int t=0; t<7; t++)</span>           {             if (col == 2)               {                   my_MAX7219.setRow(col,t,dig_5[t]|dot_1[t]);               }             else                {                          my_MAX7219.setRow(col,t,dig_5[t]);                 }            }          break;    case 6:        for (int t=0; t<7; t++)</span>             {                if (col == 2)                    {                     my_MAX7219.setRow(col,t,dig_6[t]|dot_1[t]);                    }                 else                   {                          my_MAX7219.setRow(col,t,dig_6[t]);                   }                }          break;    case 7:         for (int t=0; t<7; t++)</span>             {                if (col == 2)                    {                     my_MAX7219.setRow(col,t,dig_7[t]|dot_1[t]);                    }                 else                   {                          my_MAX7219.setRow(col,t,dig_7[t]);                   }                }         break;    case 8:        for (int t=0; t<7; t++)</span>             {                if (col == 2)                    {                     my_MAX7219.setRow(col,t,dig_8[t]|dot_1[t]);                    }                 else                   {                          my_MAX7219.setRow(col,t,dig_8[t]);                   }                }          break;     case 9:         for (int t=0; t<7; t++)</span>             {                if (col == 2)                    {                     my_MAX7219.setRow(col,t,dig_9[t]|dot_1[t]);                    }                 else                   {                          my_MAX7219.setRow(col,t,dig_9[t]);                   }                }             break;    default:       {         // выполняется, если не выбрана ни одна альтернатива       }   } }; void Print_Display_Time() {// ТЕСТ — выводит время на монитор PC        Serial.print(hour());        Serial.print(» hour»);        Serial.print(«tt»);        Serial.print(minute());        Serial.print(» minute»);        Serial.print(«t»);        Serial.print(second());        Serial.print(» second»);        Serial.print(«t»);        Serial.print(«n»);        delay (1000); }; ССЫЛКИ Главная SPI AVR Урок 28. SPI. Драйвер LED MAX7219

&nbsp

&nbsp

&nbsp

    Урок 28

Продолжем работать с шиной SPI.

Сегодня мне в руки попался драйвер 8-разрядных светодиодных индикаторов. Данный драйвер оснащем декодером символов, умеет управлять динамической индикацией и много чего ещё. Ну, и, самое главное, управляется данная микросхема по шине SPI, что не дало мне права обойти его стороной.

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

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

Вот типовая схема подключения микросхемы MAX7219

image

Мы видим, что у данного драйвера есть 8 параллельных выходов для сегментов и также восем параллельных выходов для разрядов. Также есть контакт для последовательного входа данных, выхода на схеме нет, хотя вообще он у драйвера есть, то есть разработчики сами прекрасно понимают, что мониторить здесь нечего. Также есть вход для выбора микросхемы Chip Select и вход для синхроимупульсов. На 18 ножку Iset мы подтягиваем резистор с шины питания, который рекомендуется впаивать с номиналом 9,53 килоома, тем самым мы устанавливаем пиковый ток для сегментов. Ну и, соответственно, мы подключаем на 19 ножку питание, а на 9 и 4 – общий провод.

Так как данная микросхема не совсем простая, у неё также существует немалая структурная схема

Здесь мы видим внизу 16-битный регистр, 8 младших битов которого являются данными, а следующие 4 бита – адресом для регистров. Также мы видим несколько регистров различного назначения, драйвер сегментов и драйвер разрядов. Видим мы ещё широтно-импульсный модулятор, управляющий интенсивностью свечения и управляемый особым регистром. Существует также интересный регистр – SCAN-LIMIT, который управляет количеством задействованных разрядов.

Интересным является также декодер сегментов, который может сам формировать свечение определённых сегментов в разряде в зависимости от поступившего значения. Раньше, я помню, это называлось дешифратором. Данный декодер можно также отключать, причём его можно для каких-то разрядов включить, а для каких-то – выключить. Возникает вопрос – для чего вообще выключать декодирование? Ответ здесь многогранный. Во-первых, для того, чтобы вывести какие-то особенные замысловатые символы, которых нет в списке кодов. А самое главное то, что при использовании декодера символов мы можем управлять индикатором только с общим катодом, индикатором с общим анодом мы уже управлять не можем, а если декодирование отключить, то уже можно что-то придумать для управления и общими анодами. Ну мы этим заниматься не будем, будем пользоваться декодером.

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

Ну и тогда не будем медлить, а перейдём непосредственно к проекту. Проект создан был с именем LED7219, код нём находится весь с проекта предыдущего занятия. Единственная разница – мы не будем подключать библиотеку файлов led.c и led.h, так как у нас есть драйвер и он данными вещами, описанных в данных библиотеках, займётся на аппаратном уровне.

Уберём поэтому инициализацию таймера и прерываний из функции main()

timer_ini();

sei();

Также удалим всё полностью из бесконечного цикла.

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

А создадим мы функцию, которая будет передавать команды в данный драйвер. Добавим мы её до функции main(). Параметром будет передаваемый байт, а в теле функции мы запишем данный байт в регистр SPDR и затем стандартным способом данный байт в шину SPI передадим

void SPI_SendByte (char byte)

{

  SPDR = byte;

  while (!(SPSR & (1 <<</span> SPIF)));

}

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

void Send_7219(char rg, char dt)

{

  PORTB &= ~(1<<</span>PORTB2);

  SPI_SendByte(rg);

  SPI_SendByte(dt);

  PORTB |= (1<<</span>PORTB2);

}

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

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

Мы видим, что на вход DIN идёт выход MISO контроллера, а также мы подвели к нему синхронизацию и выбор. Ну а индикатор соответствующими разрядами и сегментами мы подключили к соответствующим параллельным выходам драйвера. Вообщем, схема получилась проще паренной репы.

А вот так вот у нас всё выглядит в модуле

А вот вид сзади

Мы видим здесь нашу микросхему MAX3219 и все соединения. Выполнено очень даже чинно. Также мы подвели к микросхеме 4 провода, воспользовавшить обычными контактными разъёмами. Здесь у нас шина питания и общий провод, а также 3 провода SPI. Вот и всё

Ну а вот так выглядит всё это вместе с отладочной платой

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

Вернёмся в наш проект.

Так как мы никуда не торопимся, давайте всё-таки включим предделитель на тактирование шины SPI в функции SPI_init()

SPCR |= (1 <<</span> SPE) | (1 <<</span> MSTR)| (1<<</span>SPR0);//включим шину, объ¤вим ведущим, делитель 16

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

Прочистим себе дорогу в main(), убрав вот это всё

SPDR = 0b00000000;

while(!(SPSR & (1<<</span>SPIF)));//подождем пока данные передадутся

SPDR = 0b00000000;

while(!(SPSR & (1<<</span>SPIF)));//подождем пока данные передадутся

//сгенерируем отрицательный фронт для записи в STORAGE REGISTER

PORTB |= (1<<</span>PORTB2); //высокий уровень

PORTB &= ~(1<<</span>PORTB2); //низкий уровень

Задержку оставим.

Давайте сначала посмотрим в даташите таблицу адресов регистров

Сначала дадим следующую команду

SPI_init();

Send_7219(0x09, 0xFF); //включим режим декодирования

По комментарию ясно, что мы включили режим декодирования.

С девяткой ясно. Разбираемся с 0xFF.

Для этого есть другая таблица с примерами настройки декодирования

То есть мы видим, что каждому биту в аргументе команды соответствует один разряд, то есть значением 0xFF мы включили декодирование на все разряды нашего индикатора. А, например, если бы передали только 0x0F, то мы бы включили только 4 младших разряда.

Вообщем, с командой ясно, можно также поглядеть саму таблицу кодов для декодирования

Здесь мы видим, какие символы мы можем передать с помощью декодера. Вообщем-то основные все есть. Обидно только, что нет буквы «C». Ну да ничего. Также мы видим, что код символа передаётся только в четырёх младших разрядах байта данных, следующие три бита вообще не используются, а последний старший бит отвечает за точку.

Следующим шагом нашей инициализации будет настройка количества задействованных разрядов. Для этого у нас есть регистр с адресом 0x0B.

Вот его таблица

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

Поэтому давайте добавим глобальную переменную для количества разрядов и сразу её и инициализируем

#include«main.h»

char dg = 8;

То есть мы будем использовать все 8 разрядов

Теперь передадим значение в регистр

Send_7219(0x09, 0xFF); //включим режим декодирования

Send_7219(0x0B, dg 1); //сколько разрядов используем

Теперь займёмся яркостью свечения. Для этого у нас существует отдельный регистр с адресом 0x0A

Так как у нас MAX7219, то для нас первая колонка. Здесь я думаю всё просто. Для начала зададим среднюю интенсивность свечения индикатора

Send_7219(0x0B, dg 1); //сколько разрядов используем

Send_7219(0x0A, 0x07); //яркость

Ну и последняя настройка – это включение индикатора, также существует отдельный регистр, думаю, показывать его нет смысла, так как у него всего два значения: 0 – отключено, 1 – включено

Send_7219(0x0A, 0x07); //яркость

Send_7219(0x0C, 1); //включим индикатор

После всех данных настроек желательно весь мусор, который наберётся в буфере данных, очистить. Для этого напишем функцию очистки дисплея, опять же над функцией main()

void Clear_7219(void)

{

  char i = dg;

  do {

    Send_7219(i, 0xF); //символ пустоты

  } while (–i);

}

Ну здесь для нас, как всегда всё просто. Мы поочерёдно во все задействованные разряды установим пустые символы. В качестве адреса регистра у нес уже здесь выступает адрес информационного регистра, соответствующий заданному разряду. А байт 0xF – это у нас код символа пустоты (в таблице выше он выглядит как «blank»).

Вызовем вышенаписанную функцию в main()

Send_7219(0x0C, 1); //включим индикатор

Clear_7219();

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

Clear_7219();

Send_7219(0x01, 1);

Send_7219(0x02, 2);

Send_7219(0x03, 3);

Send_7219(0x04, 4);

Send_7219(0x05, 5);

Send_7219(0x06, 6);

Send_7219(0x07, 7);

Send_7219(0x08, 8);

Соберём код и посмотрим сначала работу кода в протеусе

В протеусе всё хорошо. Прошьём контроллер и проверим работу нашего индикатора на живом индикаторе

Всё у нас работает.

И мы видим, где именно и какой разряд.

Казалось бы, на этом можно и закончить. Но что толку в посылании в разряд символа? Не интересно. Давайте что-то повеселее напишем.

Сначала попробуем поиграть с яркостью. Попробуем её убавить

Send_7219(0x0A, 0x02); //яркость

Посмотрим результат

Да, отличается, стало темнее.

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

Создадим такую функцию опять же над функцией main()

void Number_7219(volatile long n)

{

}

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

Начнём с переменной знака, вдруг, мы захотим вывести отрицательную величину

void Number_7219(volatile long n)

{

  char ng = 0; //переменная для минуса

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

char ng = 0; //переменная для минуса

if (n <</span> 0)

{

  ng = 1;

  n *= -1;

}

Очистим дисплей

  n *= -1;

}

Clear_7219();

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

Clear_7219();

if (n == 0) {

  Send_7219(0x01, 0); //в первый разряд напишем 0

  return;

}

Затем добавим ещё одну переменную для счётчика

  return;

}

char i = 0;

Дальше цикл, в котором мы заполним разряды цифрами из нашей величины

char i = 0;

do {

  Send_7219(++i, n%10);

  n /= 10;

} while (n);

Здесь также у нас всё несложно, мы уменьшаем с каждым разрядом в 10 раз нашу величину и извлекаем из неё последний разряд с помощью деления по модулю на 10, и отправляем в текущий разряд.

Ну и по окончанию тела функции отобразим в следующий разряд символ минуса

  } while (n);

  if (ng) {

  Send_7219(i+1, 0xA); //символ –

  }

}

Ну, давайте проверим данную функцию. После отображения наших символов от 1 до 8 в функции main() добавим небольшую задержку, а затем отобразим какую-нибудь величину

Send_7219(0x08, 8);

_delay_ms(1000);

Number_7219(-2016);

Соберём код, прошьём контроллер и посмотрим результат, так как в протеусе почему-то не заработало

Отлично!

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

Number_7219(-2016);

_delay_ms(1000);

while(1)

{

  NumberFull_7219(i);

  i++;

  _delay_ms(200);

}

В принципе можно не ограничивать счёт, у нас разрядов для максимального значения типа переменной хватит.

Соберём код, прошьём контроллер и проверим

Ну вот мы с вами и познакомились с новым устройством, тем самым потренировались лишний раз с шиной SPI.

Только мы опять с шиной SPI не заканчиваем. На следующем занятии мы попробуем подключить по данной шине внешний АЦП.

    Исходный код

    Техническая документация на микросхемы MAX7219-MAX7221

Программатор и индикатор с драйвером можно приобрести здесь:

Программатор (продавец надёжный) USBASP USBISP 2.0

Индикатор светодиодный семиразрядный с драйвером MAX7219

    Смотреть ВИДЕОУРОК

Светодиодные матрицы… … для любителей теплой аналоговой регулировки.

В силу своей лени, и ряда других причин стал пользоваться готовыми электронными модулями. Одним из таких является модуль состоящий из 4 матриц по 64 светодиода. Решив применить данный модуль для изготовления матричных часов, столкнулся с проблемой недостаточного диапазона регулировки яркости. Дело в том, что ночью люблю спать в полной темноте и не люблю когда что-то светит, а данный модуль даже на минимальной яркости освещает половину противоположной стены. Изучив даташит на MAX7219 было установлено, что кроме цифровой регулировки яркости, есть ещё и аналоговая, в виде резистора, задающего пиковый ток через сегменты. В результате было решено провести легкую модификацию модуля, путем соединения резисторов Iset с шиной питания не напрямую, а через фоторезистор, для этого необходимо провести демонтаж матриц из панелек. Эту операцию лучше проводить при помощи отвертки в роли рычага, упирая её конец в плату и немного приподнимая с разных сторон. Желательно не гнуть выводы матриц, иначе возникнут трудности при монтаже на место. Также желательно запомнить ориентацию матриц: ключом-выступом на ребре к надписи FC-16. Далее разрезаем перемычку между резистором R1 и конденсатором C1 рядом с каждой микросхемой. Далее необходимо заготовить три провода длиной 5 см и два по 10 см для подключения датчика. Припаиваем проводники как на картинке ниже: В результате тестирования установлено, что яркость регулируется очень хорошо, однако в полной темноте в зависимости от экземпляра фоторезистора, может доходить до нуля. Если такое происходит, то следует добавить параллельно фоторезистору резистор сопротивлением от 100 до 200 кОм. Резистор можно распаять прямо на плате, что и было сделано: В качестве датчика использован фоторезистор, продававшийся с наименованием LDR 5528. Примерные характеристики следующие: сопротивление на уровне освещенного рабочего стола примерно 1,3 кОм, темновое от 200 до 500 кОм. Ну и конечно же короткое видео трясущимися руками)) Ссылка на проект автора

Если Вы делаете покупки в интернет магазинах AliExpress, GearBest, Banggood, ASOS, Ozon, то вступайте в мою партнерскую программу. Таким образом поможете развитию моего сайта и скорейшему выходу новых статей. Ваша выгода — возврат до 18% потраченных средств. Кэшбэк проверенный. Деньги выводят быстро и без лишних проволочек.

—>—> —>

—>Главная—> » —>Статьи—> » Электроника » Arduino и т.п.

Arduino и светодиодные матрицы 8х8 MAX7219

Сегодня на повестке дня вывод информации на кластер матричных светодиодных панелей разрешением 8х8 точек на микросхемах MAX7219. Опишу подключение к Arduino и использование двух наиболее популярных библиотек MAX72xx Panel от Марка Райса и Parola от MajicDesigns. Рассмотрю вывод кириллических и создание пользовательских символов.

    Наконец доехали из поднебесной матричные модули. Каждый модуль состоит из микросхемы MAX7219 (здесь я уже описывал эту микросхему), светодиодной матрицы, в обвязке стоят один конденсатор и один резистор.

    Управляется MAX7219 по интерфейсу SPI.

   Микросхемы в кластере соединены последовательно. Читал в интернете, что максимально возможное последовательное подключение допускает всего 8 штук MAX7219. Не верьте. 16 модулей соединил, и все прекрасно работает.

   Модули, представленные на Али, бывают в нескольких вариантах исполнения. Наибольшей популярностью пользуются 2 вида: с микросхемой в DIP и в SOIC корпусах. Модуль с DIP-микросхемой большего размера и не так удобен при соединении в кластер. Соединять придется кучей проводов.

   Модули с микросхемой в SOIC-корпусе имеют размер светодиодной матрицы и соединяются пайкой или джамперами. Получается красиво и аккуратно.

   Наиболее известными библиотеками для работы с матрицами и кластерами  являются MAX72xx Panel от Марка Райса и Parola от MajicDesigns: первая библиотека проще в использовании, вторая посложнее с бОльшими возможностями. Распишу подробнее.

MAX72xx Panel

   При использовании MAX72xx Panel обязательна установка библиотеки Adafruit GFX.

   Для русификации текста необходимо будет скачать ЭТОТ ФАЙЛ и заменить стандартный  файл glcdfont.c в каталоге Arduino/Libraries/Adafruit-GFX-Library-master. Также в этом файле описаны, кроме нужных букв и цифр, куча всяких символов. Далеко не все они могут пригодиться. Картинка ниже поясняет как формируются символы.

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

   Итак, библиотеки MAX72xx Panel и Adafruit GFX установлены, файл glcdfont.c заменен. Запускаем Arduino IDE, открываем ФАЙЛ. В скетче есть функция utf8rus. Она обеспечивает перекодировку таблицы символов для русского языка. Она нужна только для нормального вывода из программы, то есть в программе нужный текст пишется на русском. Если текст вводится через СОМ-порт, то коррекция кодов символа происходит в функции Serial_Read. В IDE и в консоли разработчики использовали разные кодировки.

   В начале файла присутствуют строки необходимые для работы библиотеки.

int numberOfHorizontalDisplays = 1;

int numberOfVerticalDisplays = 16;

   У меня модули с микросхемой в SOIC-корпусе. У них есть небольшая особенность. Матрица у модулей установлена повернутой на 90 градусов. Это плата за удобство соединения. Если запустить скетчи, идущие в комплекте с библиотеками, они будут выводить текст снизу вверх в каждом модуле. Текст будет выводится зигзагами. Для лечения этого недуга библиотеке надо «сказать», что вертикальных дисплеев 16 (физически они расположены горизонтально). И потом в void Setup указать библиотеке строку

matrix.setRotation(matrix.getRotation() + 1);

   Она программно перевернет каждую матрицу. И отображаться все будет нормально.

   У модулей с DIP-корпусом микросхем такого нет. Там все красиво, кроме кучи проводов.

   Библиотека MAX72xx Panel довольно скромная. Визуальных эффектов вывода нет. Кластер воспринимается как одно целое. Намного лучше дела обстоят с MD Parola.

Parola от MajicDesigns.

   Обладатели модулей с микросхемой в SOIC-корпусе также столкнутся с проблемой ориентации модулей в кластере. Только выглядит это немного по-другому нежели в MAX72xx. Здесь модули окажутся как бы не в своей очереди.

   Скетч HelloWorld из образцов в комплекте с библиотекой.

   Программно в скетче мне не удалось вылечить этот недуг. Я вылечил его по-другому. В файле Adruino/libraries/MD_MAX72xx_lib.h в конце нужно найти строки как на картинке.

   И исправить в выделенной строке выделенную 1 на 0. Сохранить файл. Arduino IDE можно не перезагружать. Заливаем, смотрим.

   Теперь можно использовать 24 эффекта анимации. Анимация запускается командой P.displayText(«Текст для вывода», «выравнивание текста», скорость, задержка показа, эффект появления, эффект исчезновения). Как видите, настроек достаточно много.

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

   Как вы уже догадываетесь проблема с кириллическими буквами. Она тоже решаема. Рядом с предыдущим файлом в той же директории лежит файлик MD_MAX72xx_font.cpp. Это файл шрифта. Символы в нем сформированы аналогично файлу шрифта GFX библиотеки. Есть небольшое отличие. Здесь размер символа может быть меньше 5 точек. В библиотеке Adafruit GFX восклицательный знак, например, занимает также 5 точек шириной, как и любой другой символ, только используется один ряд точек. Остальные не светятся, но используются под символ. В Parola тот же восклицательный знак занимает также один ряд точек, только рядом не пустые точки, а могут стоять соседние символы. Понятнее будет разобраться по картинке.

   Дополнить файл кириллическими символами аналогично файлу из первой рассмотренной библиотеки пока времени нет. Если кто-нибудь это сделает и пришлет мне файл, я добавлю его к этой статье, и Вам будут благодарны и я, и гости моего сайта.

   Итог. Библиотека MAX72xx Panel от Марка Райса проста в использовании и понимании, но с бедным функционалом.

   Библиотека Parola от MajicDesigns посложнее и ее возможностей хватит практически для любого применения.

—>Категория—>: Arduino и т.п. | —>Добавил—>: Zlitos (24.01.2017) |
—>Просмотров—>: 24736 | | |
—>Всего комментариев—>: 4
3 more400   (26.05.2017 13:11) [Материал] Доброго времени суток. А у вас нет статьи про max7219 и 8ми разрядные 7ми сегментные индикаторы?
4 Zlitos   (26.05.2017 18:18) [Материал] Приветствую. Самостоятельной статьи про MAX7219 и семисегментники нет, но вот в этой статье я использовал MAX7219 и 5 семисегментных индикаторов. Там есть схема и скетч. Возможно они Вам помогут.
1 2 8136821   (09.03.2017 12:06) [Материал]
1 zoloto58   (24.01.2017 22:02) [Материал] Хороший опыт и полезная аналитическая работа. Молодец!

—>Добавлять комментарии могут только зарегистрированные пользователи.—> [ —>Регистрация—> | —>Вход—> ] —> —>

Оказывается, часы в комнату я собирал ровно два года назад. Быстро же время летит! Все это время они успешно тикали, даже весьма точно. А я коварно вынашивал планы о новой версии…

Где-то через полгода после завершения сборки я набрел на светодиодные матрицы 8×8. Купил по случаю пять штук. Они лежали и давили мне на совесть, но собирать из них что-то на 595-х регистрах было откровенно лень — вот эти вот десятки резисторов, все такое. И так бы они совсем потерялись под слоем пыли, но совершенно внезапно на ebay нашел MAX7219 по 90 рублей за пять штук. Ого! Из дополнительной обвески нужен всего один резистор и один конденсатор. Вполне себе вариант. Заказал.

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

image

Тестовая плата — MAX7219, светодиодная матрица 8×8

По пути, конечно же, сжег один пиксель на тестовой матрице 🙂

Тем временем, оформился список претензий к уже имеющимся часам:

  • Хочется, чтобы яркость регулировалась автоматически. А то приходилось периодически вручную менять время включения/выключения пониженной яркости
  • Хочется, чтобы не приходилось вручную поправлять время. В идеале — какое-нибудь NTP.
  • Хочется корпус поприличнее, а то выкрашенная белым акрилом деревянная коробка выглядит не слишком прельстиво.

Управление яркостью — это, очевидно, фоторезистор. А для дистанционного управления я решил использовать широко распространенный bluetooth модуль HC-05. В конце-концов домашний сервер с линуксом вполне в состоянии раз в сутки отправить в последовательный порт точное время. Микроконтроллер взял ATMega32. Как выяснилось, натуральный overkill — вся прошивка вместе со шрифтом вполне умещается в 6Кб. С другой стороны можно напихать невероятное множество полезных и бесполезных функций, вплоть до показа последних новостей бегущей строкой или времени восхода/захода солнца. Микросхема часов — такая же DS1307 как и в предыдущих, только в SMD корпусе. Питание — традиционно mini USB. Все компоненты — по максимуму SMD. Резисторы-конденсаторы типоразмера 0805.

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

Среди всех вариантов выбрал pcb.hqew.net — при сравнимых с остальными ценами они сначала проверяют присланные файлы, а уже потом выставляют счет на оплату. Очень важный для меня момент, так как это был первый опыт заказа промышленных плат. Действительно, пришлось немного поправить и запускать в производство уже второй вариант.

Уже после того, как платы уехали в производство, меня посетила мысль, что можно было бы добавить микросхему FT232RL, залить ардуиновский загрузчик и программировать девайс из среды разработки Arduino. Как вариант, можно добавить небольшую обвеску и делать то же самое через уже установленный bluetooth модуль. С другой стороны, мне оно не особо и нужно.

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

image

Минимальный заказ 5 штук, мне приехало 6. Качество приятно порадовало, абсолютно никаких претензий.

Далее самый приятный этап — сборка и программирование. Здесь без сюрпризов.

image

При сборке обнаружилось несколько моих косяков, допущенных при проектировании:

  • Гадский Eagle CAD потерял линии TX/RX от bluetooth модуля. В чем проблема была я так и не понял — удалил два провода со схемы и нарисовал заново — тут же появились на плате. Похоже на какой-то глюк. На плате пришлось кинуть два проводка. Не красиво, но работает.
  • Отверстия для крепежных винтов слишком близко к краю, пришлось немного подрезать индикаторы, чтобы они нормально вошли.
  • Светодиоды статуса bluetooth не нужны нафиг. Их вполне можно кинуть на микроконтроллер и обрабатывать там.

Хотел замерить потребляемый ток — безопасно ли совать в компьютерный USB порт. Но, похоже, в моем мультиметре глючный амперметр — на всех диапазонах показывает одно и то же — 0.28. Так что не понятно 0.28A или 0.28μA.

За пару часов все прекрасно собралось и началось программирование. Тоже, в общем, никаких изысков. Управление DS1307 взял из предыдущего проекта. Написал несложную библиотечку для рисования чего угодно на матричном дисплее. Нарисовал шрифт. А дальше уже дело техники.

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

image

Для желающих повторить, улучшить, посмотреть в подробностях — весь проект свободно доступен на GitHub.

Оцените статью
Рейтинг автора
5
Материал подготовил
Илья Коршунов
Наш эксперт
Написано статей
134
А как считаете Вы?
Напишите в комментариях, что вы думаете – согласны
ли со статьей или есть что добавить?
Добавить комментарий