Часы на трех матрицах 8x8 MAX7219

Дим M
Автор темы, Администратор
Администратор
Аватара
Дим M
Автор темы, Администратор
Администратор
Сообщения: 1608
Зарегистрирован: 5 апреля 2013
С нами: 10 лет 11 месяцев

#1 Дим » 3 августа 2019, 15:40

Не успев доделать ещё один экземпляр часов на матрицах 8x8 MAX7219, как они пришли в негодность. Кот уронил сиё произведение на пол и что то в них заглючило. Перепроверив все соединения и не обнаружив в них изъяна решил распаять пластину состоящую из четырёх матриц (изначально они были по одному экземпляру). Ну а уж коли разобрал всё то решил попробовать другой вариант часов. Нашёл на просторах интернета проект _http://arduino.ru/forum/proekty/eshche-odni-chasy-na-matritsakh, спаял новую схему, но она почему то не захотела работать должным образом. Примеры каскодного соединения работали (точка бегали по всем матрицам), а часы не желали работать. Тогда решил спаять схему по прежнему (последовательное соединение матриц), но и тут меня ждало огорчение - видимо после всех моих манипуляций, вышла из строя плата управления матрицей. И в итоге остались рабочими только три. Тут то я и на толкнулся на проект часов на трёх матрицах _https://mysku.ru/blog/aliexpress/33196.html. Почти сразу всё заработало нормально - только в скетче нужно было изменить пару строк

Код: Выделить всё

  char old_char[2]; //used when we use itoa to transpose the current digit (type byte) into a char to pass to the animation function
  char new_char[2]; //used when we use itoa to transpose the new digit (type byte) into a char to pass to the animation function        

двоечку заменить на троечку

Код: Выделить всё

  char old_char[3]; //used when we use itoa to transpose the current digit (type byte) into a char to pass to the animation function
  char new_char[3]; //used when we use itoa to transpose the new digit (type byte) into a char to pass to the animation function        


Примерная схема соединения:
Часы на трех матрицах 8x8 MAX7219.PNG
Часы на трех матрицах 8x8 MAX7219
Часы на трех матрицах 8x8 MAX7219.PNG (134.08 КБ) 3817 просмотров


Весь код:

Код: Выделить всё

//matrix clock 32x8_pro_mini_v1.2 (align data & fix slow DHT22)

//include libraries:
#include "LedControl.h"
#include "FontLEDClock.h"                // Font library
#include "Wire.h"                        
#include "RTClib.h"                      // DS1307 clock
#include "Button.h"                      // Button library by Alexander Brevig
#include "DHT.h"                         // DHT22
#include "EEPROM.h"

#define DS3231_I2C_ADDRESS 0x68
#define DHTPIN 7
#define DHTTYPE DHT22

// DS3231
// SCL pin -> Arduino A5
// SDA pin -> Arduino A4
// VCC pin -> Arduino +5v
// GND pin -> Arduino gnd

// Setup LED Matrix
// pin 6 is connected to the DataIn on the display
// pin 5 is connected to the CLK on the display
// pin 4 is connected to LOAD on the display (CS)

const int numDevices = 3;      // number of MAX7219s used
LedControl lc = LedControl(6,4,5,numDevices); //sets the 3 pins and numDevices

//global variables
byte intensity = EEPROM.read(0);         // value intensity from EEPROM (0-11)
byte clock_mode = 0;                     // Default clock mode. Default = 0 (basic_mode)
byte old_mode = clock_mode;              // Stores the previous clock mode, so if we go to date or whatever, we know what mode to go back to after.
byte change_mode_time = 0;               // Holds hour when clock mode will next change if in random mode.
unsigned long delaytime = 500;           // We always wait a bit between updates of the display
int rtc[7];                              // Holds real time clock output
float temp3231;
byte tMSB, tLSB;
DHT dht(DHTPIN, DHTTYPE);

//  "Sunday", "Monday", "Tuesday", "Wed", "Thursday", "Friday", "Saturday"
char days[7][4] = {
  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
}; 

//define constants
#define NUM_DISPLAY_MODES 1              // Number display modes (conting zero as the first mode)
#define NUM_SETTINGS_MODES 1             // Number settings modes = 1 (conting zero as the first mode)
#define SLIDE_DELAY 20                   // The time in milliseconds for the slide effect per character in slide mode. Make this higher for a slower effect
#define cls          clear_display       // Clear display

RTC_DS1307 ds1307;                              // Create RTC object

Button buttonA = Button(2, BUTTON_PULLUP);      // Setup button A (using button library)
Button buttonB = Button(3, BUTTON_PULLUP);      // Setup button B (using button library)
//--------------------------------------------------------------------------------
void setup() {
  //EEPROM.write(0, 0);                     // ??? Only first run
  digitalWrite(2, HIGH);                 // turn on pullup resistor for button on pin 2
  digitalWrite(3, HIGH);                 // turn on pullup resistor for button on pin 3
  digitalWrite(4, HIGH);                 // turn on pullup resistor for button on pin 4
  
  
//initialize the matrix panels
  for (int address = 0; address < numDevices; address++) /*The MAX72XX is in power-saving mode on startup*/
  {    
    lc
.shutdown(address, false); /* Set the brightness to a medium values */
    lc.setIntensity(address, intensity); /* and clear the display */
    lc.clearDisplay(address);
  }

//Setup DS1307 RTC
#ifdef AVR
  Wire.begin();
#else
  Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino
#endif
  ds1307.begin(); //start RTC Clock
  dht.begin(); //start DHT 22  (AM2302)
  
 
//Show software hello message
 printhello();
}
//--------------------------------------------------------------------------------
void loop() {
 //run the clock with whatever mode is set by clock_mode - the default is set at top of code.
  switch (clock_mode){
        
  case 0
: 
    slide
();
    break; 
  case 1
: 
    setup_menu
();  
    break
;
  case 2:
    //Exit
    break;
  }
}

//--------------------------------------------------------------------------------
//plot a point on the display
void plot (byte x, byte y, byte val) {

  //select which matrix depending on the x coord
  byte address;
  if (>= 0 && x <= 7)   {
    address = 2;
  }
  if (>= 8 && x <= 15)  {
    address = 1;
    x = x - 8;
  }
  if (>= 16 && x <= 23) {
    address = 0;
    x = x - 16;
  }
  if (val == 1) {
    lc.setLed(address, y, x, true);
  } else {
    lc.setLed(address, y, x, false);
  }
}

//--------------------------------------------------------------------------------
//clear screen
void clear_display() {
  for (byte address = 0; address < numDevices; address++) {
    lc.clearDisplay(address);
  }
}
//--------------------------------------------------------------------------------
//fade screen down
void fade_down() {
  //fade from global intensity to 1
  for (byte i = intensity; i > 0; i--) {
    for (byte address = 0; address < numDevices; address++) {
      lc.setIntensity(address, i);
    }
    delay(30); //change this to change fade down speed
  }
  clear_display(); //clear display completely (off)
  //reset intentsity to global val
  for (byte address = 0; address < numDevices; address++) {
    lc.setIntensity(address, intensity);
  }
}

//--------------------------------------------------------------------------------
//power up led test & display hello
void printhello() {

  byte i = 0;
  char ver_a[6] = "SLIDE";
  char ver_b[6] = "CLOCK";
  char ver_c[6] = "ver.3";
  
  
//test all leds.
  for (byte x = 0; x <= 23; x++) {
    for (byte y = 0; y <= 7; y++) {
      plot(x, y, 1);
    }
  }
  delay(700);
  fade_down();

  while (ver_a[i]) {
    puttinychar((* 4), 1, ver_a[i]);
    delay(35);
    i++;
  }
  delay(700);
  fade_down();
  i = 0;
  while (ver_b[i]) {
    puttinychar((* 4), 1, ver_b[i]);
    delay(35);
    i++;
  }
  delay(700);
  fade_down();
  i = 0;
  while (ver_c[i]) {
    puttinychar((* 4), 1, ver_c[i]);
    delay(35);
    i++;
  }
  delay(700);
  fade_down();
  
}

//--------------------------------------------------------------------------------
// Copy a 3x5 character glyph from the myfont data structure to display memory, with its upper left at the given coordinate
// This is unoptimized and simply uses plot() to draw each dot.
void puttinychar(byte x, byte y, char c)
{
  byte dots;
  if (>= 'A' && c <= 'Z' || (>= 'a' && c <= 'z') ) {
    c &= 0x1F;   // A-Z maps to 1-26
  }
  else if (>= '0' && c <= '9') {
    c = (- '0') + 32;
  }
  else if (== ' ') {
    c = 0; // space
  }
  else if (== '.') {
    c = 27; // full stop
  }
  else if (== ':') {
    c = 28; // colon
  }
  else if (== '\'') {
    c = 29; // single quote mark
  }
  else if (== '!') {
    c = 30; // single quote mark
  }
  else if (== '%') {
    c = 31; // single quote mark
  }

  for (byte col = 0; col < 3; col++) {
    dots = pgm_read_byte_near(&mytinyfont[c][col]);
    for (char row = 0; row < 5; row++) {
      if (dots & (16 >> row))
        plot(+ col, y + row, 1);
      else
        plot
(+ col, y + row, 0);
    }
  }
}

//--------------------------------------------------------------------------------
void slide() {

  byte digits_old[4] = {99, 99, 99, 99}; //old values  we store time in. Set to somthing that will never match the time initially so all digits get draw when the mode starts
  byte digits_new[4]; //new digits time will slide to reveal
  //byte digits_x_pos[4] = {25, 19, 7, 1}; //x pos for which to draw each digit at
  byte digits_x_pos[4] = {19, 13, 6, 0}; //x pos for which to draw each digit at

  char old_char[3]; //used when we use itoa to transpose the current digit (type byte) into a char to pass to the animation function
  char new_char[3]; //used when we use itoa to transpose the new digit (type byte) into a char to pass to the animation function

  cls();

  byte old_secs = rtc[0]; //store seconds in old_secs. We compare secs and old secs. WHen they are different we redraw the display

  //run clock main loop as long as run_mode returns true
  while (1) {
    get_time();
    //check for button press
    if (buttonA.uniquePress()) {
      switch_mode();
      return;
    }
      if (buttonB.uniquePress()) {
      dht.readTemperature();
      dht.readHumidity();
      display_date();
      return;
    }

    //if secs have changed then update the display
    if (rtc[0] != old_secs) {
      old_secs = rtc[0];

      byte hours = rtc[2];
      digits_new[0] = (rtc[1] % 10);         //2 - mins ones
      digits_new[1] = ((rtc[1] / 10) % 10);  //3 - mins tens
      digits_new[2] = (hours % 10);         //4 - hour ones
      digits_new[3] = ((hours / 10) % 10);  //5 - hour tens

      //compare digits 0 to 3 (mins and hours)
      for (byte i = 0; i <= 3; i++) {
        //see if digit has changed...
        if (digits_old[i] != digits_new[i]) {

          //run 9 step animation sequence for each in turn
          for (byte seq = 0; seq <= 9 ; seq++) {
            //convert digit to string
            itoa(digits_old[i], old_char, 10);
            itoa(digits_new[i], new_char, 10);

            //draw the animation frame for each digit
            slideanim(digits_x_pos[i], 0, seq, old_char[0], new_char[0]);
            delay(SLIDE_DELAY);
          }
        }
      }
      //save digita array tol old for comparison next loop
      for (byte i = 0; i <= 3; i++) {
        digits_old[i] =  digits_new[i];
      }
    }//secs/oldsecs
  }//while loop
  fade_down();
}

//--------------------------------------------------------------------------------
//this draws the animation of one char sliding on and the other sliding off. There are 8 steps in the animation, we call the function to draw one of the steps from 0-7
//inputs are are char x and y, animation frame sequence (0-7) and the current and new chars being drawn.
void slideanim(byte x, byte y, byte sequence, char current_c, char new_c) {
  //if sequence number is below 7, we need to draw the current char
  if (sequence < 7) {
    byte dots;
    if (current_c >= 'A' && current_c <= 'Z' ) {
      current_c &= 0x1F;   // A-Z maps to 1-26
    }
    else if (current_c >= 'a' && current_c <= 'z') {
      current_c = (current_c - 'a') + 41;   // A-Z maps to 41-67
    }
    else if (current_c >= '0' && current_c <= '9') {
      current_c = (current_c - '0') + 31;
    }
    else if (current_c == ' ') {
      current_c = 0; // space
    }
    else if (current_c == '.') {
      current_c = 27; // full stop
    }
    else if (current_c == '\'') {
      current_c = 28; // single quote mark
    }
    else if (current_c == ':') {
      current_c = 29; //colon
    }
    else if (current_c == '>') {
      current_c = 30; // clock_mode selector arrow
    }

    byte curr_char_row_max = 8 - sequence; //the maximum number of rows to draw is 6 - sequence number
    byte start_y = sequence; //y position to start at - is same as sequence number. We inc this each loop

    //plot each row up to row maximum (calculated from sequence number)
    for (byte curr_char_row = 0; curr_char_row <= curr_char_row_max; curr_char_row++) {
      for (byte col = 0; col < 5; col++) {
        dots = pgm_read_byte_near(&myfont[current_c][col]);
        if (dots & (128 >> curr_char_row)) //8 row
          plot(+ col, y + start_y, 1); //plot led on
        else
          plot
(+ col, y + start_y, 0); //else plot led off
      }
      start_y++;//add one to y so we draw next row one down
    }
  }

  //draw a blank line between the characters if sequence is between 1 and 7. If we don't do this we get the remnants of the current chars last position left on the display
  if (sequence >= 1 && sequence <= 9) {
    for (byte col = 0; col < 5; col++) {
      plot(+ col, y + (sequence - 1), 0); //the y position to draw the line is equivalent to the sequence number - 1
    }
  }

  //if sequence is above 2, we also need to start drawing the new char
  if (sequence >= 2) {

    //work out char
    byte dots;
    //if (new_c >= 'A' && new_c <= 'Z' || (new_c >= 'a' && new_c <= 'z') ) {
    //  new_c &= 0x1F;   // A-Z maps to 1-26
    //}
    if (new_c >= 'A' && new_c <= 'Z' ) {
      new_c &= 0x1F;   // A-Z maps to 1-26
    }
    else if (new_c >= 'a' && new_c <= 'z') {
      new_c = (new_c - 'a') + 41;   // A-Z maps to 41-67
    }
    else if (new_c >= '0' && new_c <= '9') {
      new_c = (new_c - '0') + 31;
    }
    else if (new_c == ' ') {
      new_c = 0; // space
    }
    else if (new_c == '.') {
      new_c = 27; // full stop
    }
    else if (new_c == '\'') {
      new_c = 28; // single quote mark
    }
    else if (new_c == ':') {
      new_c = 29; // clock_mode selector arrow
    }
    else if (new_c == '>') {
      new_c = 30; // clock_mode selector arrow
    }

    byte newcharrowmin = 7 - (sequence - 2); //minimumm row num to draw for new char - this generates an output of 6 to 0 when fed sequence numbers 2-8. This is the minimum row to draw for the new char
    byte start_y = 0; //y position to start at - is same as sequence number. we inc it each row

    //plot each row up from row minimum (calculated by sequence number) up to 6
    for (byte newcharrow = newcharrowmin; newcharrow <= 7; newcharrow++) {
      for (byte col = 0; col < 5; col++) {
        dots = pgm_read_byte_near(&myfont[new_c][col]);
        if (dots & (128 >> newcharrow)) //8*5 font
          plot(+ col, y + start_y, 1); //plot led on
        else
          plot
(+ col, y + start_y, 0); //else plot led off
      }
      start_y++;//add one to y so we draw next row one down
    }
  }
}

//--------------------------------------------------------------------------------
//display_date - print the day of week, date and month with a flashing cursor effect
void display_date()
{
  cls();
int t = dht.readTemperature();
int h = dht.readHumidity();
  //read the date from the DS1307
  byte dow = rtc[3]; // day of week 0 = Sunday
  byte date = rtc[4];
  byte month = rtc[5];
  int i = 0;
  //print the day name 
  i = 0; 
  while
(days[dow][i])
  {
    puttinychar((i*4+6), 1, days[dow][i]); 
    delay
(40);
    i++;
  }
  delay(1000);
  fade_down();
  cls();
  
  
//print the date & month
  String str_date;
  if (date < 10){str_date+="0";}
  str_date+=date;
  str_date+=".";
  if (month < 10){str_date+="0";}
  str_date+=month;
  
  i 
= 0; 
  while
(str_date[i])
  {
    puttinychar((i*4+3), 1, str_date[i]); 
    delay
(40);
    i++;
  }
  delay(1000);
  fade_down();
  cls();
  

//print temp from DHT 22  (AM2302)
  t = dht.readTemperature();
  h = dht.readHumidity();
  String str_temp = "";
  String str_humi = "";
  str_temp += "t:";
  str_temp += String(t);
  str_temp += "'";
  str_humi += "h:";
  str_humi += String(h);
  str_humi += "%";
  
  i 
= 0;
    while (str_temp[i]) {
    puttinychar((i*4+3), 1, str_temp[i]);
    delay(40);
    i++;
  }
    delay(1500);
    fade_down();
    cls();
  i = 0;
    while (str_humi[i]) {
    puttinychar((i*4+2), 1, str_humi[i]);
    delay(40);
    i++;
  }
    delay(1500);
    fade_down();
    cls();
    

 
}

//--------------------------------------------------------------------------------
//dislpay menu to change the clock mode
void switch_mode() {

  //remember mode we are in. We use this value if we go into settings mode, so we can change back from settings mode (6) to whatever mode we were in.
  old_mode = clock_mode;

  char* modes[] = {
    "Clock", "Setup"
  };

  byte next_clock_mode;
  byte firstrun = 1;

  //loop waiting for button (timeout after 35 loops to return to mode X)
  for (int count = 0; count < 35 ; count++) {

    //if user hits button, change the clock_mode
    if (buttonA.uniquePress() || firstrun == 1) {

      count = 0;
      cls();

      if (firstrun == 0) {
        clock_mode++;
      }
      if (clock_mode > NUM_DISPLAY_MODES) {
        clock_mode = 0;
      }

      //print arrown and current clock_mode name on line one and print next clock_mode name on line two
      char str_top[9];

      //strcpy (str_top, "-");
      strcpy (str_top, modes[clock_mode]);

      next_clock_mode = clock_mode + 1;
      if (next_clock_mode >  NUM_DISPLAY_MODES) {
        next_clock_mode = 0;
      }

      byte i = 0;
      while (str_top[i]) {
        puttinychar(* 4, 1, str_top[i]);
        i++;
      }
      firstrun = 0;
    }
    delay(50);
  }
}

//--------------------------------------------------------------------------------
//dislpay menu to change the clock settings
void setup_menu() {

  char* set_modes[] = {
     "Set", "Bright", "Exit"}; 
  
//if (ampm == 0) { 
  //  set_modes[1] = ("12 Hr"); 
  //}

  byte setting_mode = 0;
  byte next_setting_mode;
  byte firstrun = 1;

  //loop waiting for button (timeout after 35 loops to return to mode X)
  for(int count=0; count < 35 ; count++) {

    //if user hits button, change the clock_mode
    if(buttonA.uniquePress() || firstrun == 1){

      count = 0;
      cls();

      if (firstrun == 0) { 
        setting_mode
++; 
      
} 
      if 
(setting_mode > NUM_SETTINGS_MODES) { 
        setting_mode 
= 0; 
      
}

      //print arrown and current clock_mode name on line one and print next clock_mode name on line two
      char str_top[9];
    
      strcpy 
(str_top, set_modes[setting_mode]);

      next_setting_mode = setting_mode + 1;
      if (next_setting_mode > NUM_SETTINGS_MODES) { 
        next_setting_mode 
= 0; 
      
}
      
      byte i 
= 0;
      while(str_top[i]) {
        puttinychar(i*4, 1, str_top[i]); 
        i
++;
      }

      firstrun = 0;
    }
    delay(50); 
  
}
  
  
//pick the mode 
  switch(setting_mode){
    case 0:
      set_time();    
      break
;
    case 1: 
      set_intensity
(); 
      break
;
    case 2: 
      
//exit menu
      break;
  }
    
  
//change the clock from mode 6 (settings) back to the one it was in before 
  clock_mode=old_mode;
}

//--------------------------------------------------------------------------------
//change screen intensity
void set_intensity() {
  cls();
  byte i = 0;
  char text[7] = "Bright";
  while(text[i]) {
    puttinychar((i*4), 0, text[i]);
    i++;
  }

  //wait for button input
  while (!buttonA.uniquePress()) {

    levelbar (0,6,(intensity*2),2);    //display the intensity level as a bar
    while (buttonB.isPressed()) {

      if(intensity == 11) { 
        intensity 
= 0;
        cls (); 
      
} 
      else 
{
        intensity++; 
      
}
      //print the new value 
      i = 0;
      while(text[i]) {
        puttinychar((i*4), 0, text[i]);
        i++;
      }
      
      
//display the intensity level as a bar
      levelbar (0,6,(intensity*2)+2,2);    
      
      
//change the brightness setting on the displays
      for (byte address = 0; address < numDevices; address++) {
        lc.setIntensity(address, intensity);
      }
      delay(150);
    }
  }
  EEPROM.write(0, intensity);
}

//--------------------------------------------------------------------------------
// display a horizontal bar on the screen at offset xposr by ypos with height and width of xbar, ybar
void levelbar (byte xpos, byte ypos, byte xbar, byte ybar) {
  for (byte x = 0; x < xbar; x++) {
    for (byte y = 0; y <= ybar; y++) {
      plot(x+xpos, y+ypos, 1);
    }
  }
}

//--------------------------------------------------------------------------------
//set time and date routine
void set_time() {

  cls();

  //fill settings with current clock values read from clock
  get_time();
  byte set_min   = rtc[1];
  byte set_hr    = rtc[2];
  byte set_date  = rtc[4];
  byte set_mnth  = rtc[5];
  int  set_yr    = rtc[6]; 

  
//Set function - we pass in: which 'set' message to show at top, current value, reset value, and rollover limit.
  set_date = set_value(2, set_date, 1, 31);
  set_mnth = set_value(3, set_mnth, 1, 12);
  set_yr   = set_value(4, set_yr, 2013, 2099);
  set_hr   = set_value(1, set_hr, 0, 23);
  set_min  = set_value(0, set_min, 0, 59);

  ds1307.adjust(DateTime(set_yr, set_mnth, set_date, set_hr, set_min));
  
  cls
();
}

//--------------------------------------------------------------------------------
//used to set min, hr, date, month, year values. pass 
//message = which 'set' message to print, 
//current value = current value of property we are setting
//reset_value = what to reset value to if to rolls over. E.g. mins roll from 60 to 0, months from 12 to 1
//rollover limit = when value rolls over
int set_value(byte message, int current_value, int reset_value, int rollover_limit){

  cls();
  char messages[6][17]   = {
    "Min", "Hour", "Day", "Month", "Year"};

  //Print "set xyz" top line
  byte i = 0;
  while(messages[message][i])
  {
    puttinychar(i*, 1, messages[message][i]); 
    i
++;
  }

  delay(2000);
  cls();

  //print digits bottom line
  char buffer[5] = "    ";
  itoa(current_value,buffer,10);
  puttinychar(, 1, buffer[0]); 
  puttinychar
(, 1, buffer[1]); 
  puttinychar
(, 1, buffer[2]); 
  puttinychar
(12, 1, buffer[3]); 

  delay
(300);
  //wait for button input
  while (!buttonA.uniquePress()) {

    while (buttonB.isPressed()){

      if(current_value < rollover_limit) { 
        current_value
++;
      } 
      else 
{
        current_value = reset_value;
      }
      //print the new value
      itoa(current_value, buffer ,10);
      puttinychar(, 1, buffer[0]); 
      puttinychar
(, 1, buffer[1]); 
      puttinychar
(, 1, buffer[2]); 
      puttinychar
(12, 1, buffer[3]);    
      delay
(150);
    }
  }
  return current_value;
}
//--------------------------------------------------------------------------------
void get_time()
{
  //get time
  DateTime now = ds1307.now();
  //save time to arrayhumidity
  rtc[6] = now.year();
  rtc[5] = now.month();
  rtc[4] = now.day();
  rtc[3] = now.dayOfWeek(); //returns 0-6 where 0 = Sunday
  rtc[2] = now.hour();
  rtc[1] = now.minute();
  rtc[0] = now.second();

  //flash arduino led on pin 13 every second
  if ( (rtc[0] % 2) == 0) {
    digitalWrite(13, HIGH);
  }
  else {
    digitalWrite(13, LOW);
  }
}

 


И библиотеки для часов на трех матрицах 8x8 MAX7219
lib.zip
Библиотеки для часов на трех матрицах 8x8 MAX7219
(37.72 КБ) 404 скачивания


Собрал на коленке схему для проверки работоспособности.
phpBB [media]
[center]i love you [s]mxIni[/s] Mysql[/center]


Дим M
Автор темы, Администратор
Администратор
Аватара
Дим M
Автор темы, Администратор
Администратор
Сообщения: 1608
Зарегистрирован: 5 апреля 2013
С нами: 10 лет 11 месяцев

#2 Дим » 3 августа 2019, 21:58

Дим писал(а):вышла из строя плата управления матрицей
Как оказалось в последствии - всё рабочее, но переделывать на четыре не буду. Через переводчик перевёл комментарии в коде (что корректно переводилось) и добавил в низ экрана бегающую точку.

phpBB [media]


Код: Выделить всё

//matrix clock 32x8_pro_mini_v1.2 (align data & fix slow DHT22)

//include libraries:
#include "LedControl.h"
#include "FontLEDClock.h"                // Font library
#include "Wire.h"                        
#include "RTClib.h"                      // DS1307 clock
#include "Button.h"                      // Button library by Alexander Brevig
#include "DHT.h"                         // DHT22
#include "EEPROM.h"

#define DS3231_I2C_ADDRESS 0x68
#define DHTPIN 7
#define DHTTYPE DHT22

// DS3231
// SCL pin -> Arduino A5
// SDA pin -> Arduino A4
// VCC pin -> Arduino +5v
// GND pin -> Arduino gnd

// Setup LED Matrix
// pin 6 is connected to the DataIn on the display
// pin 5 is connected to the CLK on the display
// pin 4 is connected to LOAD on the display (CS)

const int numDevices = 3;      // number of MAX7219s used
LedControl lc = LedControl(6,4,5,numDevices); //sets the 3 pins and numDevices

//глобальные переменные
byte intensity = EEPROM.read(0);         // значение интенсивности от EEPROM (0-11)
byte clock_mode = 0;                     // Режим часов по умолчанию. По умолчанию = 0 (основной режим)
byte old_mode = clock_mode;              // Сохраняет предыдущий режим часов, поэтому, если мы перейдем на дату или что-то еще, мы знаем, к какому режиму вернуться после.
byte change_mode_time = 0;               // Держит час, когда режим часов изменится следующим образом, если в случайном режиме.
unsigned long delaytime = 500;           // Мы всегда немного ждем между обновлениями дисплея
int rtc[7];                              // Содержит часы реального времени
float temp3231;
byte tMSB, tLSB;
DHT dht(DHTPIN, DHTTYPE);

//  "Sunday", "Monday", "Tuesday", "Wed", "Thursday", "Friday", "Saturday"
char days[7][4] = {
  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
}; 

//определить константы
#define NUM_DISPLAY_MODES 1              // Режимы отображения чисел (в качестве первого режима используется ноль)
#define NUM_SETTINGS_MODES 1             // Режимы настройки чисел = 1 (в первом режиме - ноль)
#define SLIDE_DELAY 20                   // Время в миллисекундах для эффекта слайда на символ в режиме слайда. Сделайте это выше для более медленного эффекта
#define cls          clear_display       // Очистить дисплей

RTC_DS1307 ds1307;                              // Создать объект RTC

Button buttonA = Button(2, BUTTON_PULLUP);      // Кнопка настройки A (с использованием библиотеки кнопок)
Button buttonB = Button(3, BUTTON_PULLUP);      // Кнопка настройки B (с использованием библиотеки кнопок)
//--------------------------------------------------------------------------------
void setup() {
  //EEPROM.write(0, 0);                     // ??? Только первый запуск
  digitalWrite(2, HIGH);                 // включите подтягивающий резистор для кнопки на контакте 2
  digitalWrite(3, HIGH);                 // включите подтягивающий резистор для кнопки на контакте 3
  digitalWrite(4, HIGH);                 // включите подтягивающий резистор для кнопки на контакте 4
  
  
//нициализировать матричные панели
  for (int address = 0; address < numDevices; address++) /*MAX72XX находится в режиме энергосбережения при запуске*/
  {    
    lc
.shutdown(address, false); /* Установите яркость на средние значения */
    lc.setIntensity(address, intensity); /* и очистить дисплей */
    lc.clearDisplay(address);
  }

//Настроить DS1307 RTC
#ifdef AVR
  Wire.begin();
#else
  Wire1.begin(); // Штырьковые контакты I2C подключаются к шине Alt I2C на Arduino
#endif
  ds1307.begin(); //start RTC Clock
  dht.begin(); //start DHT 22  (AM2302)
  
 
//Показать программное обеспечение приветственное сообщение
//printhello();
}
//--------------------------------------------------------------------------------
void loop() {
 //запускать часы с любым режимом, установленным clock_mode - по умолчанию устанавливается в верхней части кода.
  switch (clock_mode){
        
  case 0
: 
    slide
();
    break; 
  case 1
: 
    setup_menu
();  
    break
;
  case 2:
    //Exit
    break;
  }
}

//--------------------------------------------------------------------------------
//нанесите точку на дисплей
void plot (byte x, byte y, byte val) {

  //выберите матрицу в зависимости от координаты х
  byte address;
  if (>= 0 && x <= 7)   {
    address = 2;
  }
  if (>= 8 && x <= 15)  {
    address = 1;
    x = x - 8;
  }
  if (>= 16 && x <= 23) {
    address = 0;
    x = x - 16;
  }
  if (val == 1) {
    lc.setLed(address, y, x, true);
  } else {
    lc.setLed(address, y, x, false);
  }
}

//--------------------------------------------------------------------------------
//чистый экран
void clear_display() {
  for (byte address = 0; address < numDevices; address++) {
    lc.clearDisplay(address);
  }
}
//--------------------------------------------------------------------------------
//исчезать экран вниз
void fade_down() {
  //fade from global intensity to 1
  for (byte i = intensity; i > 0; i--) {
    for (byte address = 0; address < numDevices; address++) {
      lc.setIntensity(address, i);
    }
    delay(30); //cизменить это, чтобы изменить скорость затухания
  }
  clear_display(); //очистить дисплей полностью (выкл)
  //сбросить намерение к глобальному значению
  for (byte address = 0; address < numDevices; address++) {
    lc.setIntensity(address, intensity);
  }
}

//--------------------------------------------------------------------------------
//индикатор питания и дисплей привет
void printhello() {

  byte i = 0;
  char ver_a[6] = "SLIDE";
  char ver_b[6] = "CLOCK";
  char ver_c[6] = "ver.3";
  
  
//проверить все светодиоды.
  for (byte x = 0; x <= 23; x++) {
    for (byte y = 0; y <= 7; y++) {
      plot(x, y, 1);
    }
  }
  delay(700);
  fade_down();

  while (ver_a[i]) {
    puttinychar((* 4), 1, ver_a[i]);
    delay(35);
    i++;
  }
  delay(700);
  fade_down();
  i = 0;
  while (ver_b[i]) {
    puttinychar((* 4), 1, ver_b[i]);
    delay(35);
    i++;
  }
  delay(700);
  fade_down();
  i = 0;
  while (ver_c[i]) {
    puttinychar((* 4), 1, ver_c[i]);
    delay(35);
    i++;
  }
  delay(700);
  fade_down();
  
}

//--------------------------------------------------------------------------------
// Скопируйте глиф символа 3x5 из структуры данных myfont, чтобы отобразить память с верхним левым краем по заданной координате
// Это неоптимизировано и просто использует plot () для рисования каждой точки.
void puttinychar(byte x, byte y, char c)
{
  byte dots;
  if (>= 'A' && c <= 'Z' || (>= 'a' && c <= 'z') ) {
    c &= 0x1F;   // A-Z нарисуй это 1-26
  }
  else if (>= '0' && c <= '9') {
    c = (- '0') + 32;
  }
  else if (== ' ') {
    c = 0; // space пространство
  }
  else if (== '.') {
    c = 27; // полная остановка
  }
  else if (== ':') {
    c = 28; // двоеточие
  }
  else if (== '\'') {
    c = 29; // знак одинарной кавычки
  }
  else if (== '!') {
    c = 30; // знак одинарной кавычки
  }
  else if (== '%') {
    c = 31; // знак одинарной кавычки
  }

  for (byte col = 0; col < 3; col++) {
    dots = pgm_read_byte_near(&mytinyfont[c][col]);
    for (char row = 0; row < 5; row++) {
      if (dots & (16 >> row))
        plot(+ col, y + row, 1);
      else
        plot
(+ col, y + row, 0);
    }
  }
}

//--------------------------------------------------------------------------------
void slide() {

  byte digits_old[4] = {99, 99, 99, 99}; //старые значения, в которых мы храним время. Установите значение, которое изначально никогда не будет соответствовать времени, поэтому все цифры будут отображаться при запуске режима
  byte digits_new[4]; //время новых цифр будет скользить, чтобы показать
  //byte digits_x_pos[4] = {25, 19, 7, 1}; //x поз, для которого нужно нарисовать каждую цифру в
  byte digits_x_pos[4] = {19, 13, 6, 0}; //x поз, для которого нужно нарисовать каждую цифру в

  char old_char[3]; //используется, когда мы используем itoa для транспонирования текущей цифры (типа байта) в символ для передачи в функцию анимации
  char new_char[3]; //используется, когда мы используем itoa для транспонирования новой цифры (типа байта) в символ для передачи в функцию анимации
  cls();

  byte old_secs = rtc[0]; //хранить секунды в old_secs. Мы сравниваем секунды и старые секунды. Когда они разные, мы перерисовываем дисплей
  
  
//основной цикл запуска часов, пока run_mode возвращает true
  while (1) {
    get_time();
    //проверить на нажатие кнопки
    if (buttonA.uniquePress()) {
      switch_mode();
      return;
    }
      if (buttonB.uniquePress()) {
      dht.readTemperature();
      dht.readHumidity();
      display_date();
      return;
    }

    // если секунды изменились, обновите отображение
    if (rtc[0] != old_secs) {
      old_secs = rtc[0];

      byte hours = rtc[2];
      digits_new[0] = (rtc[1] % 10);         //2 - минут
      digits_new[1] = ((rtc[1] / 10) % 10);  //3 - минут десятки
      digits_new[2] = (hours % 10);         //4 - часовые
      digits_new[3] = ((hours / 10) % 10);  //5 - час десятки

      //сравнить цифры от 0 до 3 (минуты и часы)
      for (byte i = 0; i <= 3; i++) {
        //посмотрите, изменилась ли цифра ...
        if (digits_old[i] != digits_new[i]) {

          //запустить 9 шагов последовательности анимации для каждого по очереди
          for (byte seq = 0; seq <= 9 ; seq++) {
            //преобразовать цифру в строку
            itoa(digits_old[i], old_char, 10);
            itoa(digits_new[i], new_char, 10);

            // нарисуйте кадр анимации для каждой цифры
            slideanim(digits_x_pos[i], 0, seq, old_char[0], new_char[0]);
            delay(SLIDE_DELAY);
          }
        }
      }
      //сохранить цифровой массив слишком старый для сравнения следующий цикл
      for (byte i = 0; i <= 3; i++) {
        digits_old[i] =  digits_new[i];
      }
    }//сек / старые сек
  }//while loop
  fade_down();
}

//--------------------------------------------------------------------------------
// это рисует анимацию скольжения одного символа, а другого - скольжения. В анимации 8 шагов, мы вызываем функцию для рисования одного из шагов от 0 до 7
// входными данными являются char x и y, последовательность кадров анимации (0-7) и текущий и новый отображаемые символы.
void slideanim(byte x, byte y, byte sequence, char current_c, char new_c) {
  //если порядковый номер меньше 7, нам нужно нарисовать текущий символ
  if (sequence < 7) {
    byte dots;
    if (current_c >= 'A' && current_c <= 'Z' ) {
      current_c &= 0x1F;   // A-Z maps to 1-26
    }
    else if (current_c >= 'a' && current_c <= 'z') {
      current_c = (current_c - 'a') + 41;   // A-Z maps to 41-67
    }
    else if (current_c >= '0' && current_c <= '9') {
      current_c = (current_c - '0') + 31;
    }
    else if (current_c == ' ') {
      current_c = 0; // space
    }
    else if (current_c == '.') {
      current_c = 27; // full stop
    }
    else if (current_c == '\'') {
      current_c = 28; // single quote mark
    }
    else if (current_c == ':') {
      current_c = 29; //colon
    }
    else if (current_c == '>') {
      current_c = 30; // clock_mode selector arrow
    }

    byte curr_char_row_max = 8 - sequence; //максимальное количество строк для рисования составляет 6 - порядковый номер
    byte start_y = sequence; //y позиция для начала - такая же, как порядковый номер. Мы включили этот каждый цикл

    //построить каждую строку до максимума строки (рассчитывается по порядковому номеру)
    for (byte curr_char_row = 0; curr_char_row <= curr_char_row_max; curr_char_row++) {
      for (byte col = 0; col < 5; col++) {
        dots = pgm_read_byte_near(&myfont[current_c][col]);
        if (dots & (128 >> curr_char_row)) //8 строка
          plot(+ col, y + start_y, 1); //plot led on
        else
          plot
(+ col, y + start_y, 0); //else plot led off
      }
      start_y++;//добавьте один к y, чтобы мы нарисовали следующий ряд вниз
    }
  }

  //Нарисуйте пустую линию между символами, если последовательность между 1 и 7. Если мы этого не сделаем, мы получим остатки текущей позиции последних символов на дисплее
  if (sequence >= 1 && sequence <= 9) {
    for (byte col = 0; col < 5; col++) {
      plot(+ col, y + (sequence - 1), 0); //позиция y для рисования линии эквивалентна порядковому номеру - 1
    }
  }

  //если последовательность больше 2, нам также нужно начать рисовать новый символ
  if (sequence >= 2) {

    // отрабатывать символ
    byte dots;
    //if (new_c >= 'A' && new_c <= 'Z' || (new_c >= 'a' && new_c <= 'z') ) {
    //  new_c &= 0x1F;   // A-Z maps to 1-26
    //}
    if (new_c >= 'A' && new_c <= 'Z' ) {
      new_c &= 0x1F;   // A-Z maps to 1-26
    }
    else if (new_c >= 'a' && new_c <= 'z') {
      new_c = (new_c - 'a') + 41;   // A-Z maps to 41-67
    }
    else if (new_c >= '0' && new_c <= '9') {
      new_c = (new_c - '0') + 31;
    }
    else if (new_c == ' ') {
      new_c = 0; // space
    }
    else if (new_c == '.') {
      new_c = 27; // full stop
    }
    else if (new_c == '\'') {
      new_c = 28; // single quote mark
    }
    else if (new_c == ':') {
      new_c = 29; // clock_mode selector arrow
    }
    else if (new_c == '>') {
      new_c = 30; // clock_mode selector arrow
    }

    byte newcharrowmin = 7 - (sequence - 2); //минимальная строка строки, чтобы нарисовать для нового символа - это генерирует выходные данные от 6 до 0, когда подается порядковые номера 2-8. Это минимальная строка для нового персонажа
    byte start_y = 0; //y позиция для начала - такая же, как порядковый номер. мы включили это каждый ряд

    //построить каждую строку вверх от минимума строки (рассчитывается по порядковому номеру) до 6
    for (byte newcharrow = newcharrowmin; newcharrow <= 7; newcharrow++) {
      for (byte col = 0; col < 5; col++) {
        dots = pgm_read_byte_near(&myfont[new_c][col]);
        if (dots & (128 >> newcharrow)) //8*5 font
          plot(+ col, y + start_y, 1); //plot led on
        else
          plot
(+ col, y + start_y, 0); //else plot led off
      }
      start_y++;//добавьте один к y, чтобы мы нарисовали следующий ряд вниз
    }
  }
}

//--------------------------------------------------------------------------------
//display_date - печатать день недели, дату и месяц с эффектом мигающего курсора
void display_date()
{
  cls();
int t = dht.readTemperature();
int h = dht.readHumidity();
  //прочитать дату от DS1307
  byte dow = rtc[3]; //день недели 0 = воскресенье
  byte date = rtc[4];
  byte month = rtc[5];
  int i = 0;
  //напечатать название дня 
  i = 0; 
  while
(days[dow][i])
  {
    puttinychar((i*4+6), 1, days[dow][i]); 
    delay
(40);
    i++;
  }
  delay(1000);
  fade_down();
  cls();
  
  
//напечатать дату и месяц
  String str_date;
  if (date < 10){str_date+="0";}
  str_date+=date;
  str_date+=".";
  if (month < 10){str_date+="0";}
  str_date+=month;
  
  i 
= 0; 
  while
(str_date[i])
  {
    puttinychar((i*4+3), 1, str_date[i]); 
    delay
(40);
    i++;
  }
  delay(1000);
  fade_down();
  cls();
  

//темп печати от DHT 22 (AM2302)
  t = dht.readTemperature();
  h = dht.readHumidity();
  String str_temp = "";
  String str_humi = "";
  str_temp += "t:";
  str_temp += String(t);
  str_temp += "'";
  str_humi += "h:";
  str_humi += String(h);
  str_humi += "%";
  
  i 
= 0;
    while (str_temp[i]) {
    puttinychar((i*4+3), 1, str_temp[i]);
    delay(40);
    i++;
  }
    delay(1500);
    fade_down();
    cls();
  i = 0;
    while (str_humi[i]) {
    puttinychar((i*4+2), 1, str_humi[i]);
    delay(40);
    i++;
  }
    delay(1500);
    fade_down();
    cls();
    

 
}

//--------------------------------------------------------------------------------
// отображение меню для изменения режима часов
void switch_mode() {

  //запомните режим, в котором мы находимся. Мы используем это значение, если переходим в режим настроек, поэтому мы можем вернуться из режима настроек (6) в любой режим, в котором мы были.
  old_mode = clock_mode;

  char* modes[] = {
    "Clock", "Setup"
  };

  byte next_clock_mode;
  byte firstrun = 1;

  //ожидание цикла для кнопки (тайм-аут после 35 циклов для возврата в режим X)
  for (int count = 0; count < 35 ; count++) {

    //если пользователь нажимает кнопку, измените clock_mode
    if (buttonA.uniquePress() || firstrun == 1) {

      count = 0;
      cls();

      if (firstrun == 0) {
        clock_mode++;
      }
      if (clock_mode > NUM_DISPLAY_MODES) {
        clock_mode = 0;
      }

      //напечатать стрелку и текущее имя clock_mode в первой строке и напечатать следующее имя clock_mode во второй строке
      char str_top[9];

      //strcpy (str_top, "-");
      strcpy (str_top, modes[clock_mode]);

      next_clock_mode = clock_mode + 1;
      if (next_clock_mode >  NUM_DISPLAY_MODES) {
        next_clock_mode = 0;
      }

      byte i = 0;
      while (str_top[i]) {
        puttinychar(* 4, 1, str_top[i]);
        i++;
      }
      firstrun = 0;
    }
    delay(50);
  }
}

//--------------------------------------------------------------------------------
//меню дисплея для изменения настроек часов
void setup_menu() {

  char* set_modes[] = {
     "Set", "Bright", "Exit"}; 
  
//if (ampm == 0) { 
  //  set_modes[1] = ("12 Hr"); 
  //}

  byte setting_mode = 0;
  byte next_setting_mode;
  byte firstrun = 1;

  //ожидание цикла для кнопки (тайм-аут после 35 циклов для возврата в режим X)
  for(int count=0; count < 35 ; count++) {

    //если пользователь нажимает кнопку, измените clock_mode
    if(buttonA.uniquePress() || firstrun == 1){

      count = 0;
      cls();

      if (firstrun == 0) { 
        setting_mode
++; 
      
} 
      if 
(setting_mode > NUM_SETTINGS_MODES) { 
        setting_mode 
= 0; 
      
}

      //напечатать стрелку и текущее имя clock_mode в первой строке и напечатать следующее имя clock_mode во второй строке
      char str_top[9];
    
      strcpy 
(str_top, set_modes[setting_mode]);

      next_setting_mode = setting_mode + 1;
      if (next_setting_mode > NUM_SETTINGS_MODES) { 
        next_setting_mode 
= 0; 
      
}
      
      byte i 
= 0;
      while(str_top[i]) {
        puttinychar(i*4, 1, str_top[i]); 
        i
++;
      }

      firstrun = 0;
    }
    delay(50); 
  
}
  
  
// выбрать режим
  switch(setting_mode){
    case 0:
      set_time();    
      break
;
    case 1: 
      set_intensity
(); 
      break
;
    case 2: 
      
//exit menu
      break;
  }
    
  
//изменить часы с режима 6 (настройки) обратно на тот, в котором он был раньше
  clock_mode=old_mode;
}

//--------------------------------------------------------------------------------
//изменить интенсивность экрана
void set_intensity() {
  cls();
  byte i = 0;
  char text[7] = "Bright";
  while(text[i]) {
    puttinychar((i*4), 0, text[i]);
    i++;
  }

  //ждать ввода кнопки
  while (!buttonA.uniquePress()) {

    levelbar (0,6,(intensity*2),2);    //отображать уровень интенсивности в виде полосы
    while (buttonB.isPressed()) {

      if(intensity == 11) { 
        intensity 
= 0;
        cls (); 
      
} 
      else 
{
        intensity++; 
      
}
      //напечатать новое значение
      i = 0;
      while(text[i]) {
        puttinychar((i*4), 0, text[i]);
        i++;
      }
      
      
//отображать уровень интенсивности в виде полосы
      levelbar (0,6,(intensity*2)+2,2);    
      
      
//изменить настройку яркости на дисплеях
      for (byte address = 0; address < numDevices; address++) {
        lc.setIntensity(address, intensity);
      }
      delay(150);
    }
  }
  EEPROM.write(0, intensity);
}

//--------------------------------------------------------------------------------
// отобразить горизонтальную полосу на экране со смещением xposr по ypos с высотой и шириной xbar, ybar
void levelbar (byte xpos, byte ypos, byte xbar, byte ybar) {
  for (byte x = 0; x < xbar; x++) {
    for (byte y = 0; y <= ybar; y++) {
      plot(x+xpos, y+ypos, 1);
    }
  }
}

//--------------------------------------------------------------------------------
//установить время и дату рутины
void set_time() {

  cls();

  //заполнить настройки текущими значениями часов, считанными из часов
  get_time();
  byte set_min   = rtc[1];
  byte set_hr    = rtc[2];
  byte set_date  = rtc[4];
  byte set_mnth  = rtc[5];
  int  set_yr    = rtc[6]; 

  
//Задайте функцию - мы передаем: какое «установленное» сообщение показывать сверху, текущее значение, значение сброса и предел опрокидывания.
  set_date = set_value(2, set_date, 1, 31);
  set_mnth = set_value(3, set_mnth, 1, 12);
  set_yr   = set_value(4, set_yr, 2013, 2099);
  set_hr   = set_value(1, set_hr, 0, 23);
  set_min  = set_value(0, set_min, 0, 59);

  ds1307.adjust(DateTime(set_yr, set_mnth, set_date, set_hr, set_min));
  
  cls
();
}

//--------------------------------------------------------------------------------
// используется для установки значений min, hr, date, month, year. проходить
// message = какой «установить» сообщение для печати,
// текущее значение = текущее значение свойства, которое мы устанавливаем
// reset_value = что сбросить значение, если переворачивается. Например. мин катит с 60 до 0, месяцы с 12 до 1
// предел ролловера = когда значение переворачивается
int set_value(byte message, int current_value, int reset_value, int rollover_limit){

  cls();
  char messages[6][17]   = {
    "Min", "Hour", "Day", "Month", "Year"};

  //Print "set xyz" top line
  byte i = 0;
  while(messages[message][i])
  {
    puttinychar(i*, 1, messages[message][i]); 
    i
++;
  }

  delay(2000);
  cls();

  //нижняя строка печатных цифр
  char buffer[5] = "    ";
  itoa(current_value,buffer,10);
  puttinychar(, 1, buffer[0]); 
  puttinychar
(, 1, buffer[1]); 
  puttinychar
(, 1, buffer[2]); 
  puttinychar
(12, 1, buffer[3]); 

  delay
(300);
  //ждать ввода кнопки
  while (!buttonA.uniquePress()) {

    while (buttonB.isPressed()){

      if(current_value < rollover_limit) { 
        current_value
++;
      } 
      else 
{
        current_value = reset_value;
      }
      //напечатать новое значение
      itoa(current_value, buffer ,10);
      puttinychar(, 1, buffer[0]); 
      puttinychar
(, 1, buffer[1]); 
      puttinychar
(, 1, buffer[2]); 
      puttinychar
(12, 1, buffer[3]);    
      delay
(150);
    }
  }
  return current_value;
}
//--------------------------------------------------------------------------------
void get_time()
{
  //получить время
  DateTime now = ds1307.now();
  //сэкономить время на влажность
  rtc[6] = now.year();
  rtc[5] = now.month();
  rtc[4] = now.day();
  rtc[3] = now.dayOfWeek(); //returns 0-6 where 0 = Sunday
  rtc[2] = now.hour();
  rtc[1] = now.minute();
  rtc[0] = now.second();

  //Вспышка Arduino на выводе 13 каждую секунду
  if ( (rtc[0] % 2) == 0) {
    digitalWrite(13, HIGH);
  }
  else {
    digitalWrite(13, LOW);
  }
  //бегает точка внизу дисплея
  {
  lc.setLed(1, 7, 3, true);
  lc.setLed(1, 7, 4, false);
  delay(1000);
  lc.setLed(1, 7, 4, true);
  lc.setLed(1, 7, 3, false);
  delay(1000);
}
}
 
[center]i love you [s]mxIni[/s] Mysql[/center]

Дим M
Автор темы, Администратор
Администратор
Аватара
Дим M
Автор темы, Администратор
Администратор
Сообщения: 1608
Зарегистрирован: 5 апреля 2013
С нами: 10 лет 11 месяцев

#3 Дим » 8 августа 2019, 14:45

Дим писал(а):переделывать на четыре не буду
Зарекалась ворона... всё таки переделал опять на четыре. На данный момент это последний скетч для часов на max7219 Почему переделал на четыре матрицы? - Как часы функционал и отображение меня устраивало, но отображение температуры и прочих данных с датчиков мне не понравилось. Хотел добавить ИК приёмник для управления часами с пульта - получилась какая то галиматья - работать корректно не захотело. Сейчас думаю изменить размер шрифта на такой же как и на трёх матрицах (на всю высоту матрицы).
[center]i love you [s]mxIni[/s] Mysql[/center]

S_Sergey_G
Ст. сержант
Ст. сержант
Аватара
S_Sergey_G
Ст. сержант
Ст. сержант
Сообщения: 92
Зарегистрирован: 28 января 2021
С нами: 3 года 2 месяца

#4 S_Sergey_G » 28 января 2021, 21:43

Здравствуйте. А просто термометр на трех матрицах можно сделать? С датчиком DS18b20. На четырех матрицах у меня есть, но хочется по компактней. А с 4х матриц не могу перевести на 3, (знаний не хватает)

Дим M
Автор темы, Администратор
Администратор
Аватара
Дим M
Автор темы, Администратор
Администратор
Сообщения: 1608
Зарегистрирован: 5 апреля 2013
С нами: 10 лет 11 месяцев

#5 Дим » 28 января 2021, 22:09

S_Sergey_G писал(а):А с 4х матриц не могу перевести на 3
Скинь сюда, схему и код которые у тебя есть на 4 матрицы.
[center]i love you [s]mxIni[/s] Mysql[/center]

S_Sergey_G
Ст. сержант
Ст. сержант
Аватара
S_Sergey_G
Ст. сержант
Ст. сержант
Сообщения: 92
Зарегистрирован: 28 января 2021
С нами: 3 года 2 месяца

#6 S_Sergey_G » 29 января 2021, 10:02

Спасибо, что ответили. Вот код:

Код: Выделить всё

#include "Arduino.h"      //CS 10; CLK 11; DIN 12.
#include "LedControl.h"
#include "OneWire.h"

OneWire ds(8);

LedControl lc LedControl(1211103);

byte Num0[8] =
B0000000,
B01110000,
B10001000,
B10001000,
B10001000,
B10001000,
B10001000,
B01110000 };

byte Num1[8] =
B00000000,
B01000000,
B11000000,
B01000000,
B01000000,
B01000000,
B01000000,
B11100000 };

byte Num2[8] =
B00000000,
B01110000,
B10001000,
B00001000,
B00010000,
B00100000,
B01000000,
B11111000 };

byte Num3[8] =
B00000000,
B11111000,
B00010000,
B00100000,
B00010000,
B00001000,
B10001000,
B01110000 };

byte Num4[8] =
B00000000,
B00010000,
B00110000,
B01010000,
B10010000,
B11111000,
B00010000,
B00010000 };

byte Num5[8] =
B00000000,
B11111000,
B10000000,
B11110000,
B00001000,
B00001000,
B10001000,
B01110000 };

byte Num6[8] =
B00000000,
B00110000,
B01000000,
B10000000,
B11110000,
B10001000,
B10001000,
B01110000 };

byte Num7[8] =
B00000000,
B11111000,
B00001000,
B00001000,
B00010000,
B00100000,
B01000000,
B01000000 };

byte Num8[8] =
B00000000,
B01110000,
B10001000,
B10001000,
B01110000,
B10001000,
B10001000,
B01110000 };

byte Num9[8] =
B00000000,
B01110000,
B10001000,
B10001000,
B01111000,
B00001000,
B00010000,
B01100000 };

byte Minus[8] =
B00000000,
B00000000,
B00000000,
B00000000,
B11100000,
B00000000,
B00000000,
B00000000 };

byte Plus[8] =
B00000000,
B00000000,
B00000000,
B01000000,
B11100000,
B01000000,
B00000000,
B00000000 };

byte Dot[8] =
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B10000000 };

byte DegreeC[8] =
B01100000,
B10010000,
B10010110,
B01101001,
B00001000,
B00001000,
B00001001,
B00000110 };

byte Empty[8] =
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000
};

byte ReadyDigit2[8]; // Include fragment of 1 digit and full 2 digit
byte BufferedDigit[8]; // Push to buffer 1 digit
uint8_t CurrentDigit2intensity;

int HighByteLowByteTReadingSignBitTc_100WholeFract;

unsigned long currentMillisnowMillis;

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

    
intensity 2;

    
lc.shutdown(0false);
    
lc.setIntensity(0intensity);
    
lc.clearDisplay(0);

    
lc.shutdown(1false);
    
lc.setIntensity(1intensity);
    
lc.clearDisplay(1);

    
lc.shutdown(2false);
    
lc.setIntensity(2intensity);
    
lc.clearDisplay(2);

    
lc.shutdown(3false);
    
lc.setIntensity(3intensity);
    
lc.clearDisplay(3);

    
Degree();
}

void loop()
{
    
String Sign;
    
uint8_t ReadyFract;
    
byte i;
    
byte present 0;
    
byte data[12];
    
byte addr[8];

  
nowMillis millis();

    if (
nowMillis currentMillis >= 100)
    {
        
ds.reset_search();
        if (!
ds.search(addr))
        {
            
ds.reset_search();
            return;
        }
        
ds.reset();
        
ds.select(addr);
        
ds.write(0x441);

        
currentMillis millis();
    }

    
present ds.reset();
    
ds.select(addr);
    
ds.write(0xBE);

    for (
09i++)
    {
        
data[i] = ds.read();
    }

    
LowByte data[0];
    
HighByte data[1];
    
TReading = (HighByte << 8) + LowByte;
    
SignBit TReading 0x8000;

    if (
SignBit)
    {
        
TReading = (TReading 0xffff) + 1;
    }
    
Tc_100 = (TReading) + TReading 4;
    
Whole Tc_100 100;
    
Fract Tc_100 100;

    if (
SignBit)
    {
        
Sign "Minus";
    }
    else if (!
SignBit && TReading != 0)
    {
        
Sign "Plus";
    }
    else if (
TReading == 0)
    {
        
Sign "None";
    }

    if (
Fract 10)
    {
        
ReadyFract 0;
    }
    else if (
Fract 10 5)
    {
        
ReadyFract Fract 10;
    }
    else if (
Fract 10 >= 5)
    {
        
ReadyFract = (Fract 10) + 1;
    }

    
Digit1(Whole 10Sign);
    
Digit2(Whole 10);
    
Digit3(ReadyFracttrue);
}

void Digit1(uint8_t DigString Sign)
{
    switch (
Dig)
    {
    case 
0:
    {
        for (
uint8_t i 08i++)
        {
            
BufferedDigit[i] = Empty[i];

          if (
CurrentDigit2 == && CurrentDigit2 != 0)
          {
            
lc.setRow(2iBufferedDigit[i] << 4);
          }

          if (
Sign == "Plus")
          {
            
lc.setRow(3iPlus[i] >> 5);
          }
          else if (
Sign == "Minus")
          {
            
lc.setRow(3iMinus[i] >> 5);
          }
          else if (
Sign == "None")
          {
            
lc.setRow(3iNum0[i] >> 4);
          }
        }
        break;
    }
    case 
1:
    {
        for (
uint8_t i 08i++)
        {
            
BufferedDigit[i] = Num1[i] >> 2;

            if (
CurrentDigit2 == && CurrentDigit2 != 1)
            {
                
lc.setRow(2iBufferedDigit[i] << 4);
            }

            if (
Sign == "Plus")
            {
                
lc.setRow(3iNum1[i] >> Plus[i]);
            }
            else if (
Sign == "Minus")
            {
                
lc.setRow(3iNum1[i] >> Minus[i]);
            }
            else if (
Sign == "None")
            {
                
lc.setRow(3iNum1[i] >> 6);
            }
        }
        break;
    }
    case 
2:
    {
        for (
uint8_t i 08i++)
        {
            
BufferedDigit[i] = Num2[i];

            if (
CurrentDigit2 == && CurrentDigit2 != 2)
            {
                
lc.setRow(2iBufferedDigit[i] << 4);
            }

            if (
Sign == "Plus")
            {
                
lc.setRow(3iNum2[i] >> Plus[i]);
            }
            else if (
Sign == "Minus")
            {
                
lc.setRow(3iNum2[i] >> Minus[i]);
            }
            else if (
Sign == "None")
            {
                
lc.setRow(3iNum2[i] >> 4);
            }
        }
        break;
    }
    case 
3:
    {
        for (
uint8_t i 08i++)
        {
            
BufferedDigit[i] = Num3[i];

            if (
CurrentDigit2 == && CurrentDigit2 != 3)
            {
                
lc.setRow(2iBufferedDigit[i] << 4);
            }

            if (
Sign == "Plus")
            {
                
lc.setRow(3iNum3[i] >> Plus[i]);
            }
            else if (
Sign == "Minus")
            {
                
lc.setRow(3iNum3[i] >> Minus[i]);
            }
            else if (
Sign == "None")
            {
                
lc.setRow(3iNum3[i] >> 4);
            }
        }
        break;
    }
    case 
4:
    {
        for (
uint8_t i 08i++)
        {
            
BufferedDigit[i] = Num4[i];

            if (
CurrentDigit2 == && CurrentDigit2 != 4)
            {
                
lc.setRow(2iBufferedDigit[i] << 4);
            }

            if (
Sign == "Plus")
            {
                
lc.setRow(3iNum4[i] >> Plus[i]);
            }
            else if (
Sign == "Minus")
            {
                
lc.setRow(3iNum4[i] >> Minus[i]);
            }
            else if (
Sign == "None")
            {
                
lc.setRow(3iNum4[i] >> 4);
            }
        }
        break;
    }
    case 
5:
    {
        for (
uint8_t i 08i++)
        {
            
BufferedDigit[i] = Num5[i];

            if (
CurrentDigit2 == && CurrentDigit2 != 5)
            {
                
lc.setRow(2iBufferedDigit[i] << 4);
            }

            if (
Sign == "Plus")
            {
                
lc.setRow(3iNum5[i] >> Plus[i]);
            }
            else if (
Sign == "Minus")
            {
                
lc.setRow(3iNum5[i] >> Minus[i]);
            }
            else if (
Sign == "None")
            {
                
lc.setRow(3iNum5[i] >> 4);
            }
        }
        break;
    }
    case 
6:
    {
        for (
uint8_t i 08i++)
        {
            
BufferedDigit[i] = Num6[i];

            if (
CurrentDigit2 == && CurrentDigit2 != 6)
            {
                
lc.setRow(2iBufferedDigit[i] << 4);
            }

            if (
Sign == "Plus")
            {
                
lc.setRow(3iNum6[i] >> Plus[i]);
            }
            else if (
Sign == "Minus")
            {
                
lc.setRow(3iNum6[i] >> Minus[i]);
            }
            else if (
Sign == "None")
            {
                
lc.setRow(3iNum6[i] >> 4);
            }
        }
        break;
    }
    case 
7:
    {
        for (
uint8_t i 08i++)
        {
            
BufferedDigit[i] = Num7[i];

            if (
CurrentDigit2 == && CurrentDigit2 != 7)
            {
                
lc.setRow(2iBufferedDigit[i] << 4);
            }

            if (
Sign == "Plus")
            {
                
lc.setRow(3iNum7[i] >> Plus[i]);
            }
            else if (
Sign == "Minus")
            {
                
lc.setRow(3iNum7[i] >> Minus[i]);
            }
            else if (
Sign == "None")
            {
                
lc.setRow(3iNum7[i] >> 4);
            }
        }
        break;
    }
    case 
8:
    {
        for (
uint8_t i 08i++)
        {
            
BufferedDigit[i] = Num8[i];

            if (
CurrentDigit2 == && CurrentDigit2 != 8)
            {
                
lc.setRow(2iBufferedDigit[i] << 4);
            }

            if (
Sign == "Plus")
            {
                
lc.setRow(3iNum8[i] >> Plus[i]);
            }
            else if (
Sign == "Minus")
            {
                
lc.setRow(3iNum8[i] >> Minus[i]);
            }
            else if (
Sign == "None")
            {
                
lc.setRow(3iNum8[i] >> 4);
            }
        }
        break;
    }
    case 
9:
    {
        for (
uint8_t i 08i++)
        {
            
BufferedDigit[i] = Num9[i];

            if (
CurrentDigit2 == && CurrentDigit2 != 9)
            {
                
lc.setRow(2iBufferedDigit[i] << 4);
            }

            if (
Sign == "Plus")
            {
                
lc.setRow(3iNum9[i] >> Plus[i]);
            }
            else if (
Sign == "Minus")
            {
                
lc.setRow(3iNum9[i] >> Minus[i]);
            }
            else if (
Sign == "None")
            {
                
lc.setRow(3iNum9[i] >> 4);
            }
        }
        break;
        default:
        
Dig 0;
    }
    }
}

void Digit2(uint8_t Dig)
{
    switch (
Dig)
    {
    case 
0:
    {
        
CurrentDigit2 0;
        for (
uint8_t i 08i++)
        {
            
ReadyDigit2[i] = (BufferedDigit[i] << 4) | (Num0[i] >> 2);
            
lc.setRow(2iReadyDigit2[i]);
        }
        break;
    }
    case 
1:
    {
        
CurrentDigit2 1;
        for (
uint8_t i 08i++)
        {
            
ReadyDigit2[i] = (BufferedDigit[i] << 4) | (Num1[i] >> 3);
            
lc.setRow(2iReadyDigit2[i]);
        }
        break;
    }
    case 
2:
    {
        
CurrentDigit2 2;
        for (
uint8_t i 08i++)
        {
            
ReadyDigit2[i] = (BufferedDigit[i] << 4) | (Num2[i] >> 2);
            
lc.setRow(2iReadyDigit2[i]);
        }
        break;
    }
    case 
3:
    {
        
CurrentDigit2 3;
        for (
uint8_t i 08i++)
        {
            
ReadyDigit2[i] = (BufferedDigit[i] << 4) | (Num3[i] >> 2);
            
lc.setRow(2iReadyDigit2[i]);
        }
        break;
    }
    case 
4:
    {
        
CurrentDigit2 4;
        for (
uint8_t i 08i++)
        {
            
ReadyDigit2[i] = (BufferedDigit[i] << 4) | (Num4[i] >> 2);
            
lc.setRow(2iReadyDigit2[i]);
        }
        break;
    }
    case 
5:
    {
        
CurrentDigit2 5;
        for (
uint8_t i 08i++)
        {
            
ReadyDigit2[i] = (BufferedDigit[i] << 4) | (Num5[i] >> 2);
            
lc.setRow(2iReadyDigit2[i]);
        }
        break;
    }
    case 
6:
    {
        
CurrentDigit2 6;
        for (
uint8_t i 08i++)
        {
            
ReadyDigit2[i] = (BufferedDigit[i] << 4) | (Num6[i] >> 2);
            
lc.setRow(2iReadyDigit2[i]);
        }
        break;
    }
    case 
7:
    {
        
CurrentDigit2 7;
        for (
uint8_t i 08i++)
        {
            
ReadyDigit2[i] = (BufferedDigit[i] << 4) | (Num7[i] >> 2);
            
lc.setRow(2iReadyDigit2[i]);
        }
        break;
    }
    case 
8:
    {
        
CurrentDigit2 8;
        for (
uint8_t i 08i++)
        {
            
ReadyDigit2[i] = (BufferedDigit[i] << 4) | (Num8[i] >> 2);
            
lc.setRow(2iReadyDigit2[i]);
        }
        break;
    }
    case 
9:
    {
        
CurrentDigit2 9;
        for (
uint8_t i 08i++)
        {
            
ReadyDigit2[i] = (BufferedDigit[i] << 4) | (Num9[i] >> 2);
            
lc.setRow(2iReadyDigit2[i]);
        }
        break;
        default:
        
Dig 0;
    }
    }
}

void Digit3(uint8_t Digbool DotBool)
{
    switch (
Dig)
    {
    case 
0:
    {
        if (!
DotBool)
        {
            for (
uint8_t i 08i++)
            {
                
lc.setRow(1iNum0[i] >> 2);
            }
        }
        else
            for (
uint8_t i 08i++)
            {
                
byte Num0Dot[8];
                
Num0Dot[i] = (Num0[i] >> 2) | (Dot[i]);
                
lc.setRow(1iNum0Dot[i]);
            }
        break;
    }
    case 
1:
    {
        if (!
DotBool)
        {
            for (
uint8_t i 08i++)
            {
                
lc.setRow(1iNum1[i] >> 3);
            }
        }
        else
            for (
uint8_t i 08i++)
            {
                
byte Num1Dot[8];
                
Num1Dot[i] = (Num1[i] >> 3) | (Dot[i]);
                
lc.setRow(1iNum1Dot[i]);
            }
        break;
    }
    case 
2:
    {
        if (!
DotBool)
        {
            for (
uint8_t i 08i++)
            {
                
lc.setRow(1iNum2[i] >> 2);
            }
        }
        else
            for (
uint8_t i 08i++)
            {
                
byte Num2Dot[8];
                
Num2Dot[i] = (Num2[i] >> 2) | (Dot[i]);
                
lc.setRow(1iNum2Dot[i]);
            }
        break;
    }
    case 
3:
    {
        if (!
DotBool)
        {

            for (
uint8_t i 08i++)
            {
                
lc.setRow(1iNum3[i] >> 2);
            }
        }
        else
            for (
uint8_t i 08i++)
            {
                
byte Num3Dot[8];
                
Num3Dot[i] = (Num3[i] >> 2) | (Dot[i]);
                
lc.setRow(1iNum3Dot[i]);
            }
        break;
    }
    case 
4:
    {
        if (!
DotBool)
        {

            for (
uint8_t i 08i++)
            {
                
lc.setRow(1iNum4[i] >> 2);
            }
        }
        else
            for (
uint8_t i 08i++)
            {
                
byte Num4Dot[8];
                
Num4Dot[i] = (Num4[i] >> 2) | (Dot[i]);
                
lc.setRow(1iNum4Dot[i]);
            }
        break;
    }
    case 
5:
    {
        if (!
DotBool)
        {
            for (
uint8_t i 08i++)
            {
                
lc.setRow(1iNum5[i] >> 2);
            }
        }
        else
            for (
uint8_t i 08i++)
            {
                
byte Num5Dot[8];
                
Num5Dot[i] = (Num5[i] >> 2) | (Dot[i]);
                
lc.setRow(1iNum5Dot[i]);
            }
        break;
    }
    case 
6:
    {
        if (!
DotBool)
        {
            for (
uint8_t i 08i++)
            {
                
lc.setRow(1iNum6[i] >> 2);
            }
        }
        else
            for (
uint8_t i 08i++)
            {
                
byte Num6Dot[8];
                
Num6Dot[i] = (Num6[i] >> 2) | (Dot[i]);
                
lc.setRow(1iNum6Dot[i]);
            }
        break;
    }
    case 
7:
    {
        if (!
DotBool)
        {
            for (
uint8_t i 08i++)
            {
                
lc.setRow(1iNum7[i] >> 2);
            }
        }
        else
            for (
uint8_t i 08i++)
            {
                
byte Num7Dot[8];
                
Num7Dot[i] = (Num7[i] >> 2) | (Dot[i]);
                
lc.setRow(1iNum7Dot[i]);
            }
        break;
    }
    case 
8:
    {
        if (!
DotBool)
        {
            for (
uint8_t i 08i++)
            {
                
lc.setRow(1iNum8[i] >> 2);
            }
        }
        else
            for (
uint8_t i 08i++)
            {
                
byte Num8Dot[8];
                
Num8Dot[i] = (Num8[i] >> 2) | (Dot[i]);
                
lc.setRow(1iNum8Dot[i]);
            }
        break;
    }
    case 
9:
    {
        if (!
DotBool)
        {
            for (
uint8_t i 08i++)
            {
                
lc.setRow(1iNum9[i] >> 2);
            }
        }
        else
            for (
uint8_t i 08i++)
            {
                
byte Num9Dot[8];
                
Num9Dot[i] = (Num9[i] >> 2) | (Dot[i]);
                
lc.setRow(1iNum9Dot[i]);
            }
        break;
        default:
        
Dig 0;
    }
    }
}

void Degree(void)
{
    for (
uint8_t i 08i++)
    {
        
lc.setRow(0iDegreeC[i]);
    }

Arduino Nano: MAX 7219 CS-10; CLK-11; Din-12. Датчик DS18b20 D-8.

Дим M
Автор темы, Администратор
Администратор
Аватара
Дим M
Автор темы, Администратор
Администратор
Сообщения: 1608
Зарегистрирован: 5 апреля 2013
С нами: 10 лет 11 месяцев

#7 Дим » 29 января 2021, 18:13

S_Sergey_G писал(а):Вот код:
Ты его уже менял?
P.S Не помещается на три матрицы.
[center]i love you [s]mxIni[/s] Mysql[/center]

S_Sergey_G
Ст. сержант
Ст. сержант
Аватара
S_Sergey_G
Ст. сержант
Ст. сержант
Сообщения: 92
Зарегистрирован: 28 января 2021
С нами: 3 года 2 месяца

#8 S_Sergey_G » 29 января 2021, 23:06

Нет код я не менял. На 4х матрицах работает отлично. Но вот на 3 матрицы не двигается в право. Знак °C убираю, третий модуль чистый. В void Digit3 менял после знака (>>) значения в большую сторону во всех (case) цифра двигается со второго модуля, но на третий не переходит.

Дим M
Автор темы, Администратор
Администратор
Аватара
Дим M
Автор темы, Администратор
Администратор
Сообщения: 1608
Зарегистрирован: 5 апреля 2013
С нами: 10 лет 11 месяцев

#9 Дим » 29 января 2021, 23:16

S_Sergey_G писал(а):Нет код я не менял.

Код: Выделить всё

LedControl lc = LedControl(12, 11, 10, 3);

3 - это сколько матриц
Я завтра посмотрю что можно сделать.
[center]i love you [s]mxIni[/s] Mysql[/center]

S_Sergey_G
Ст. сержант
Ст. сержант
Аватара
S_Sergey_G
Ст. сержант
Ст. сержант
Сообщения: 92
Зарегистрирован: 28 января 2021
С нами: 3 года 2 месяца

#10 S_Sergey_G » 29 января 2021, 23:37

3 - это сколько матриц
Эту цифру я подставил, была 4. Я думал это к числу матриц относиться.
Если с "моим" кодом не получиться, можно в Вашем коде оставить только температуру?


  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Программирование»

Кто сейчас на форуме (по активности за 5 минут)

Сейчас этот раздел просматривают: 6 гостей